2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSCommSupport.cpp
39 #include "AFSCommon.h"
42 AFSReleaseFid( IN AFSFileID *FileId)
45 NTSTATUS ntStatus = STATUS_SUCCESS;
50 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
65 AFSProcessRequest( IN ULONG RequestType,
66 IN ULONG RequestFlags,
68 IN PUNICODE_STRING FileName,
72 IN OUT void *ResultBuffer,
73 IN OUT PULONG ResultBufferLength)
76 NTSTATUS ntStatus = STATUS_SUCCESS;
77 AFSPoolEntry stPoolEntry, *pPoolEntry = NULL;
78 AFSCommSrvcCB *pCommSrvc = NULL;
79 BOOLEAN bReleasePool = FALSE;
80 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
81 AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
82 BOOLEAN bWait = BooleanFlagOn( RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS);
83 ULONG ulPoolEntryLength = 0;
84 BOOLEAN bDecrementCount = FALSE;
89 if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
91 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
94 if( InterlockedIncrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 1)
96 KeClearEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent);
99 bDecrementCount = TRUE;
101 pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
104 // Grab the pool resource and check the state
107 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
108 AFS_TRACE_LEVEL_VERBOSE,
109 "AFSProcessRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
110 &pCommSrvc->IrpPoolLock,
111 PsGetCurrentThread());
113 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
118 if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
122 // Pool not running so bail.
125 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
129 // If this is an async request we need to allocate a pool entry for the request
132 pPoolEntry = &stPoolEntry;
137 ASSERT( ResultBuffer == NULL);
139 ulPoolEntryLength = sizeof( AFSPoolEntry) + QuadAlign( DataLength);
141 if( FileName != NULL)
144 ulPoolEntryLength += FileName->Length;
147 pPoolEntry = (AFSPoolEntry *)AFSExAllocatePoolWithTag( NonPagedPool,
151 if( pPoolEntry == NULL)
154 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
157 RtlZeroMemory( pPoolEntry,
160 pPoolEntry->Data = (void *)((char *)pPoolEntry + sizeof( AFSPoolEntry));
162 pPoolEntry->FileName.Buffer = (WCHAR *)((char *)pPoolEntry->Data + DataLength);
167 RtlZeroMemory( pPoolEntry,
168 sizeof( AFSPoolEntry));
170 KeInitializeEvent( &pPoolEntry->Event,
175 pPoolEntry->RequestType = RequestType;
177 pPoolEntry->RequestIndex = pCommSrvc->IrpPoolRequestIndex++;
179 pPoolEntry->RequestFlags = RequestFlags;
181 pPoolEntry->ResultBufferLength = 0;
186 pPoolEntry->FileId = *FileId;
189 pPoolEntry->FileName.Length = 0;
191 if( FileName != NULL)
197 pPoolEntry->FileName = *FileName;
202 pPoolEntry->FileName.Length = FileName->Length;
204 pPoolEntry->FileName.MaximumLength = pPoolEntry->FileName.Length;
206 RtlCopyMemory( pPoolEntry->FileName.Buffer,
208 pPoolEntry->FileName.Length);
213 // Move in the data if there is some
216 pPoolEntry->DataLength = DataLength;
225 pPoolEntry->Data = Data;
230 RtlCopyMemory( pPoolEntry->Data,
236 pPoolEntry->ResultBuffer = ResultBuffer;
238 pPoolEntry->ResultBufferLength = ResultBufferLength;
241 // Store off the auth group
244 if( AuthGroup == NULL)
246 AFSRetrieveAuthGroup( (ULONGLONG)PsGetCurrentProcessId(),
247 (ULONGLONG)PsGetCurrentThreadId(),
248 &pPoolEntry->AuthGroup);
252 RtlCopyMemory( &pPoolEntry->AuthGroup,
257 if( AFSIsLocalSystemAuthGroup( &pPoolEntry->AuthGroup))
259 SetFlag( pPoolEntry->RequestFlags, AFS_REQUEST_LOCAL_SYSTEM_PAG);
262 if( AFSIsNoPAGAuthGroup( &pPoolEntry->AuthGroup))
266 "AFSProcessRequest NoPAG Auth Group %08lX\n",
267 PsGetCurrentThread());
271 // Indicate the type of process
276 if( !AFSIs64BitProcess( (ULONGLONG)PsGetCurrentProcessId()))
278 SetFlag( pPoolEntry->RequestFlags, AFS_REQUEST_FLAG_WOW64);
284 // Insert the entry into the request pool
287 ntStatus = AFSInsertRequest( pCommSrvc,
290 if( !NT_SUCCESS( ntStatus))
296 ExFreePool( pPoolEntry);
299 try_return( ntStatus);
303 // Drop the lock on the pool prior to waiting
306 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
308 bReleasePool = FALSE;
311 // Wait for the result if this is NOT an asynchronous request
318 // Wait for the result of the request. We specify no timeout ...
321 ntStatus = KeWaitForSingleObject( &pPoolEntry->Event,
328 // Process the result of the request
331 if( ntStatus == STATUS_SUCCESS)
334 ntStatus = pPoolEntry->ResultStatus;
339 ntStatus = STATUS_DEVICE_NOT_READY;
348 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
351 if( bDecrementCount &&
352 InterlockedDecrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 0)
354 KeSetEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent,
359 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()))
365 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
368 if( bDecrementCount &&
369 InterlockedDecrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 0)
371 KeSetEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent,
376 if ( ntStatus == STATUS_SUCCESS)
379 ntStatus = STATUS_UNSUCCESSFUL;
387 AFSProcessControlRequest( IN PIRP Irp)
390 NTSTATUS ntStatus = STATUS_SUCCESS;
391 PIO_STACK_LOCATION pIrpSp;
392 ULONG ulIoControlCode;
393 BOOLEAN bCompleteRequest = TRUE;
394 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
395 ULONG ulBytesProcessed = 0;
400 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
402 ulIoControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
404 switch( ulIoControlCode)
407 case IOCTL_AFS_INITIALIZE_CONTROL_DEVICE:
411 // Go intialize the pool
414 ntStatus = AFSInitIrpPool();
416 if( !NT_SUCCESS( ntStatus))
427 // Tag this instance as the one to close the irp pool when it is closed
430 pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_CONTROL_INSTANCE);
435 case IOCTL_AFS_INITIALIZE_REDIRECTOR_DEVICE:
438 AFSRedirectorInitInfo *pRedirInitInfo = (AFSRedirectorInitInfo *)Irp->AssociatedIrp.SystemBuffer;
441 // Extract off the passed in information which contains the
442 // cache file parameters
445 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSRedirectorInitInfo) ||
446 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSRedirectorInitInfo, CacheFileName) +
447 pRedirInitInfo->CacheFileNameLength)
450 ntStatus = STATUS_INVALID_PARAMETER;
456 // Initialize the Redirector device
459 ntStatus = AFSInitializeRedirector( pRedirInitInfo);
461 if( !NT_SUCCESS( ntStatus))
468 // Stash away context so we know the instance used to initialize the redirector
471 pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_REDIRECTOR_INSTANCE);
476 case IOCTL_AFS_PROCESS_IRP_REQUEST:
479 ntStatus = AFSProcessIrpRequest( Irp);
484 case IOCTL_AFS_PROCESS_IRP_RESULT:
487 ntStatus = AFSProcessIrpResult( Irp);
492 case IOCTL_AFS_SYSNAME_NOTIFICATION:
495 AFSSysNameNotificationCB *pSysNameInfo = (AFSSysNameNotificationCB *)Irp->AssociatedIrp.SystemBuffer;
497 if( pSysNameInfo == NULL ||
498 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSSysNameNotificationCB))
501 ntStatus = STATUS_INVALID_PARAMETER;
506 ntStatus = AFSSetSysNameInformation( pSysNameInfo,
507 pIrpSp->Parameters.DeviceIoControl.InputBufferLength);
512 case IOCTL_AFS_CONFIGURE_DEBUG_TRACE:
515 AFSTraceConfigCB *pTraceInfo = (AFSTraceConfigCB *)Irp->AssociatedIrp.SystemBuffer;
517 if( pTraceInfo == NULL ||
518 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSTraceConfigCB))
521 ntStatus = STATUS_INVALID_PARAMETER;
526 ntStatus = AFSConfigureTrace( pTraceInfo);
531 case IOCTL_AFS_GET_TRACE_BUFFER:
534 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0)
537 ntStatus = STATUS_INVALID_PARAMETER;
542 ntStatus = AFSGetTraceBuffer( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
543 Irp->AssociatedIrp.SystemBuffer,
544 &Irp->IoStatus.Information);
549 case IOCTL_AFS_FORCE_CRASH:
554 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_FLAG_ENABLE_FORCE_CRASH))
557 KeBugCheck( (ULONG)-1);
564 #ifdef NOT_IMPLEMENTED
565 case IOCTL_AFS_LOAD_LIBRARY:
568 AFSLoadLibraryCB *pLoadLib = (AFSLoadLibraryCB *)Irp->AssociatedIrp.SystemBuffer;
569 UNICODE_STRING uniServicePath;
571 if( pLoadLib == NULL ||
572 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSLoadLibraryCB) ||
573 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSLoadLibraryCB, LibraryServicePath) +
574 pLoadLib->LibraryServicePathLength)
577 ntStatus = STATUS_INVALID_PARAMETER;
582 uniServicePath.Length = pLoadLib->LibraryServicePathLength;
583 uniServicePath.MaximumLength = uniServicePath.Length;
585 uniServicePath.Buffer = pLoadLib->LibraryServicePath;
587 if( uniServicePath.Length == 0)
590 ntStatus = STATUS_INVALID_PARAMETER;
595 ntStatus = AFSLoadLibrary( pLoadLib->Flags,
598 if( NT_SUCCESS( ntStatus))
602 // Intialize the library
605 ntStatus = AFSInitializeLibrary( NULL,
612 case IOCTL_AFS_UNLOAD_LIBRARY:
616 // Try to unload the library we currently have in place
619 ntStatus = AFSUnloadLibrary( FALSE);
625 case IOCTL_AFS_SHUTDOWN:
628 ntStatus = AFSShutdownRedirector();
633 case IOCTL_AFS_AUTHGROUP_CREATE_AND_SET:
637 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
639 if( pAuthGroupRequestCB == NULL ||
640 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
643 ntStatus = STATUS_INVALID_PARAMETER;
648 ntStatus = AFSCreateSetProcessAuthGroup( pAuthGroupRequestCB);
653 case IOCTL_AFS_AUTHGROUP_QUERY:
656 ntStatus = AFSQueryProcessAuthGroupList( ( GUID *)Irp->AssociatedIrp.SystemBuffer,
657 pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
658 &Irp->IoStatus.Information);
663 case IOCTL_AFS_AUTHGROUP_SET:
666 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
668 if( pAuthGroupRequestCB == NULL ||
669 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
672 ntStatus = STATUS_INVALID_PARAMETER;
677 ntStatus = AFSSetActiveProcessAuthGroup( pAuthGroupRequestCB);
682 case IOCTL_AFS_AUTHGROUP_RESET:
685 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
687 if( pAuthGroupRequestCB == NULL ||
688 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
691 ntStatus = STATUS_INVALID_PARAMETER;
696 ntStatus = AFSResetActiveProcessAuthGroup( pAuthGroupRequestCB);
701 case IOCTL_AFS_AUTHGROUP_LOGON_CREATE:
702 case IOCTL_AFS_AUTHGROUP_SID_CREATE:
705 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
707 if( pAuthGroupRequestCB != NULL &&
708 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
711 ntStatus = STATUS_INVALID_PARAMETER;
716 ntStatus = AFSCreateAuthGroupForSIDorLogonSession( pAuthGroupRequestCB,
717 ulIoControlCode == IOCTL_AFS_AUTHGROUP_LOGON_CREATE);
722 case IOCTL_AFS_AUTHGROUP_SID_QUERY:
725 AFSAuthGroupRequestCB *pAuthGroupRequestCB = NULL;
727 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( GUID))
729 ntStatus = STATUS_INVALID_PARAMETER;
733 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof( AFSAuthGroupRequestCB))
735 pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
738 ntStatus = AFSQueryAuthGroup( pAuthGroupRequestCB,
739 (GUID *)Irp->AssociatedIrp.SystemBuffer,
740 &Irp->IoStatus.Information);
749 // Check the state of the library
752 ntStatus = AFSCheckLibraryState( Irp);
754 if( !NT_SUCCESS( ntStatus) ||
755 ntStatus == STATUS_PENDING)
758 if( ntStatus == STATUS_PENDING)
760 bCompleteRequest = FALSE;
766 bCompleteRequest = FALSE;
768 IoSkipCurrentIrpStackLocation( Irp);
770 ntStatus = IoCallDriver( pDevExt->Specific.Control.LibraryDeviceObject,
774 // Indicate the library is done with the request
777 AFSClearLibraryRequest();
786 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()))
789 ntStatus = STATUS_UNSUCCESSFUL;
792 if( bCompleteRequest)
795 Irp->IoStatus.Status = ntStatus;
797 AFSCompleteRequest( Irp,
808 NTSTATUS ntStatus = STATUS_SUCCESS;
809 AFSCommSrvcCB *pCommSrvc = NULL;
810 BOOLEAN bReleasePools = FALSE;
811 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
816 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
819 // Whenever we change state we must grab both pool locks. On the checking of the state
820 // within the processing routines for these respective pools, we only grab one lock to
821 // minimize serialization. The ordering is always the Irp pool then the result pool
822 // locks. We also do this in the tear down of the pool
825 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
826 AFS_TRACE_LEVEL_VERBOSE,
827 "AFSInitIrpPool Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
828 &pCommSrvc->IrpPoolLock,
829 PsGetCurrentThread());
831 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
834 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
835 AFS_TRACE_LEVEL_VERBOSE,
836 "AFSInitIrpPool Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
837 &pCommSrvc->ResultPoolLock,
838 PsGetCurrentThread());
840 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
843 bReleasePools = TRUE;
846 // The pool can be either ACTIVE or INACTIVE. If the pool state is INACTIVE and we
847 // are receiving the INIT request, then activate it. If the pool is ACTIVE, then we
848 // shouldn't be getting this request ...
851 if( pCommSrvc->IrpPoolControlFlag == POOL_ACTIVE)
855 // We have already been activated so just fail this request
858 try_return( ntStatus = STATUS_INVALID_PARAMETER);
860 else if( pCommSrvc->IrpPoolControlFlag == POOL_INACTIVE)
864 // The pool is currently INACTIVE so start it up and ready it to
865 // receive irp requests
868 pCommSrvc->IrpPoolControlFlag = POOL_ACTIVE;
870 pDevExt->Specific.Control.ServiceProcess = (PKPROCESS)PsGetCurrentProcess();
872 try_return( ntStatus = STATUS_SUCCESS);
878 // The pool is in some mixed state, fail the request.
881 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
889 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
891 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
902 NTSTATUS ntStatus = STATUS_SUCCESS;
903 AFSPoolEntry *pEntry = NULL, *pNextEntry = NULL;
904 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
905 AFSCommSrvcCB *pCommSrvc = (AFSCommSrvcCB *)&pDevExt->Specific.Control.CommServiceCB;
911 // When we change the state, grab both pool locks exclusive. The order is always the
912 // Irp pool then the result pool lock
915 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
916 AFS_TRACE_LEVEL_VERBOSE,
917 "AFSCleanupIrpPool Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
918 &pCommSrvc->IrpPoolLock,
919 PsGetCurrentThread());
921 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
924 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
925 AFS_TRACE_LEVEL_VERBOSE,
926 "AFSCleanupIrpPool Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
927 &pCommSrvc->ResultPoolLock,
928 PsGetCurrentThread());
930 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
934 // Indicate we are pending stop
937 pCommSrvc->IrpPoolControlFlag = POOL_INACTIVE;
940 // Set the event to release any waiting workers
941 // (everyone waits on IrpPoolHasReleaseEntries)
944 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
949 // Go through the pool entries and free up the structures.
952 pEntry = pCommSrvc->RequestPoolHead;
954 while( pEntry != NULL)
957 pNextEntry = pEntry->fLink;
959 if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
963 // Here we need to complete the irp, cancelled, and delete the data block
966 pEntry->ResultStatus = STATUS_CANCELLED;
968 KeSetEvent( &pEntry->Event,
982 // Cleanup the control structure for the request pool
985 pCommSrvc->RequestPoolHead = NULL;
987 pCommSrvc->RequestPoolTail = NULL;
989 pCommSrvc->IrpPoolRequestIndex = 1;
991 KeClearEvent( &pCommSrvc->IrpPoolHasEntries);
993 KeClearEvent( &pCommSrvc->IrpPoolHasReleaseEntries);
996 // Release the irp pool lock.
999 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1002 // Go through the result pool entries and free up the structures.
1005 pEntry = pCommSrvc->ResultPoolHead;
1007 while( pEntry != NULL)
1010 pNextEntry = pEntry->fLink;
1012 pEntry->ResultStatus = STATUS_CANCELLED;
1015 // Here we will set the event of the requestor and let the blocked thread
1016 // free the data block
1019 KeSetEvent( &pEntry->Event,
1024 // Go onto the next entry
1027 pEntry = pNextEntry;
1031 // Cleanup the control structure for the result pool
1034 pCommSrvc->ResultPoolHead = NULL;
1036 pCommSrvc->ResultPoolTail = NULL;
1039 // Release the result pool lock.
1042 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1049 AFSInsertRequest( IN AFSCommSrvcCB *CommSrvc,
1050 IN AFSPoolEntry *Entry)
1053 NTSTATUS ntStatus = STATUS_SUCCESS;
1058 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1059 AFS_TRACE_LEVEL_VERBOSE,
1060 "AFSInsertRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
1061 &CommSrvc->IrpPoolLock,
1062 PsGetCurrentThread());
1064 AFSAcquireExcl( &CommSrvc->IrpPoolLock,
1067 if( CommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1070 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1073 if( CommSrvc->RequestPoolHead == NULL)
1076 CommSrvc->RequestPoolHead = Entry;
1081 CommSrvc->RequestPoolTail->fLink = Entry;
1083 Entry->bLink = CommSrvc->RequestPoolTail;
1086 CommSrvc->RequestPoolTail = Entry;
1088 if( Entry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1091 KeSetEvent( &CommSrvc->IrpPoolHasReleaseEntries,
1098 KeSetEvent( &CommSrvc->IrpPoolHasEntries,
1103 InterlockedIncrement( &CommSrvc->QueueCount);
1107 AFSReleaseResource( &CommSrvc->IrpPoolLock);
1114 AFSProcessIrpRequest( IN PIRP Irp)
1117 NTSTATUS ntStatus = STATUS_SUCCESS;
1118 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1119 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1120 AFSCommSrvcCB *pCommSrvc = NULL;
1121 AFSPoolEntry *pEntry = NULL, *pPrevEntry = NULL;
1122 AFSCommRequest *pRequest = NULL;
1123 BOOLEAN bReleaseRequestThread = FALSE;
1129 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1131 pRequest = (AFSCommRequest *)Irp->AssociatedIrp.SystemBuffer;
1133 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1134 AFS_TRACE_LEVEL_VERBOSE,
1135 "AFSProcessIrpRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
1136 &pCommSrvc->IrpPoolLock,
1137 PsGetCurrentThread());
1139 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1142 if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1145 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1147 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1150 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1153 // Is this a dedicated flush thread?
1156 if( BooleanFlagOn( pRequest->RequestFlags, AFS_REQUEST_RELEASE_THREAD))
1159 bReleaseRequestThread = TRUE;
1163 // Populate the objects array for the non release only threads
1164 // Release only workers can only process release extent events
1165 // whereas normal workers can process any kind of event.
1166 // Release only workers are present to ensure there cannot be
1167 // a deadlock due to all extents held by the redirector and
1168 // there not be a worker available to release them.
1171 Objects[0] = &pCommSrvc->IrpPoolHasReleaseEntries;
1173 Objects[1] = &pCommSrvc->IrpPoolHasEntries;
1176 // Wait on the 'have items' event until we can retrieve an item
1182 if( bReleaseRequestThread)
1185 ntStatus = KeWaitForSingleObject( &pCommSrvc->IrpPoolHasReleaseEntries,
1191 if( ntStatus != STATUS_SUCCESS)
1194 ntStatus = STATUS_DEVICE_NOT_READY;
1203 ntStatus = KeWaitForMultipleObjects( 2,
1212 if( ntStatus != STATUS_WAIT_0 &&
1213 ntStatus != STATUS_WAIT_1)
1216 ntStatus = STATUS_DEVICE_NOT_READY;
1223 // Grab the lock on the request pool
1226 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1227 AFS_TRACE_LEVEL_VERBOSE,
1228 "AFSProcessIrpRequest Acquiring IrpPoolLock (WAIT) lock %08lX EXCL %08lX\n",
1229 &pCommSrvc->IrpPoolLock,
1230 PsGetCurrentThread());
1232 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1235 if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1238 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1241 // Wake up the next worker since this is a SynchronizationEvent
1244 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1248 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1252 // If this is a dedicated flush thread only look for a flush request in the queue
1255 if( bReleaseRequestThread)
1258 pEntry = pCommSrvc->RequestPoolHead;
1262 while( pEntry != NULL)
1265 if( pEntry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1268 if( pPrevEntry == NULL)
1271 pCommSrvc->RequestPoolHead = pEntry->fLink;
1273 if( pCommSrvc->RequestPoolHead == NULL)
1276 pCommSrvc->RequestPoolTail = NULL;
1282 pPrevEntry->fLink = pEntry->fLink;
1284 if( pPrevEntry->fLink == NULL)
1287 pCommSrvc->RequestPoolTail = pPrevEntry;
1294 pPrevEntry = pEntry;
1296 pEntry = pEntry->fLink;
1303 // There might be another release entry pending
1306 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1312 // And release the request pool lock
1315 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1320 pEntry = pCommSrvc->RequestPoolHead;
1325 pCommSrvc->RequestPoolHead = pEntry->fLink;
1327 pEntry->bLink = NULL;
1329 if( pCommSrvc->RequestPoolHead == NULL)
1332 pCommSrvc->RequestPoolTail = NULL;
1337 KeSetEvent( &pCommSrvc->IrpPoolHasEntries,
1344 // And release the request pool lock
1347 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1351 // Insert the entry into the result pool, if we have one
1358 // Move the request data into the passed in buffer
1361 ASSERT( sizeof( AFSCommRequest) +
1362 pEntry->FileName.Length +
1363 pEntry->DataLength <= pIrpSp->Parameters.DeviceIoControl.OutputBufferLength);
1365 RtlCopyMemory( &pRequest->AuthGroup,
1369 pRequest->FileId = pEntry->FileId;
1371 pRequest->RequestType = pEntry->RequestType;
1373 pRequest->RequestIndex = pEntry->RequestIndex;
1375 pRequest->RequestFlags = pEntry->RequestFlags;
1377 pRequest->NameLength = pEntry->FileName.Length;
1379 pRequest->QueueCount = InterlockedDecrement( &pCommSrvc->QueueCount);
1381 if( pRequest->NameLength > 0)
1384 RtlCopyMemory( pRequest->Name,
1385 pEntry->FileName.Buffer,
1386 pRequest->NameLength);
1389 pRequest->DataOffset = 0;
1391 pRequest->DataLength = pEntry->DataLength;
1393 if( pRequest->DataLength > 0)
1396 pRequest->DataOffset = pEntry->FileName.Length;
1398 RtlCopyMemory( (void *)((char *)pRequest->Name + pRequest->DataOffset),
1400 pRequest->DataLength);
1403 pRequest->ResultBufferLength = 0;
1405 if( pEntry->ResultBufferLength != NULL)
1408 pRequest->ResultBufferLength = *(pEntry->ResultBufferLength);
1411 Irp->IoStatus.Information = sizeof( AFSCommRequest) +
1412 pEntry->FileName.Length +
1416 // If this is a synchronous request then move the request into the
1420 if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
1423 pEntry->fLink = NULL;
1424 pEntry->bLink = NULL;
1426 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1427 AFS_TRACE_LEVEL_VERBOSE,
1428 "AFSProcessIrpRequest Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
1429 &pCommSrvc->ResultPoolLock,
1430 PsGetCurrentThread());
1432 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1435 if( pCommSrvc->ResultPoolHead == NULL)
1438 pCommSrvc->ResultPoolHead = pEntry;
1443 pCommSrvc->ResultPoolTail->fLink = pEntry;
1445 pEntry->bLink = pCommSrvc->ResultPoolTail;
1448 pCommSrvc->ResultPoolTail = pEntry;
1450 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1456 // Free up the pool entry
1459 ExFreePool( pEntry);
1475 AFSProcessIrpResult( IN PIRP Irp)
1478 NTSTATUS ntStatus = STATUS_SUCCESS;
1479 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1480 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1481 AFSCommSrvcCB *pCommSrvc = NULL;
1482 AFSPoolEntry *pCurrentEntry = NULL;
1483 AFSCommResult *pResult = NULL;
1484 ULONG ulCopyLen = 0;
1489 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1492 // Get the request for the incoming result
1495 pResult = (AFSCommResult *)Irp->AssociatedIrp.SystemBuffer;
1497 if( pResult == NULL)
1500 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1504 // Go look for our entry
1507 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1508 AFS_TRACE_LEVEL_VERBOSE,
1509 "AFSProcessIrpResult Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
1510 &pCommSrvc->ResultPoolLock,
1511 PsGetCurrentThread());
1513 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1516 pCurrentEntry = pCommSrvc->ResultPoolHead;
1518 while( pCurrentEntry != NULL)
1521 if( pCurrentEntry->RequestIndex == pResult->RequestIndex)
1525 // Found the entry so remove it from the queue
1528 if( pCurrentEntry->bLink == NULL)
1532 // At the head of the list
1535 pCommSrvc->ResultPoolHead = pCurrentEntry->fLink;
1537 if( pCommSrvc->ResultPoolHead != NULL)
1540 pCommSrvc->ResultPoolHead->bLink = NULL;
1546 pCurrentEntry->bLink->fLink = pCurrentEntry->fLink;
1549 if( pCurrentEntry->fLink == NULL)
1552 pCommSrvc->ResultPoolTail = pCurrentEntry->bLink;
1554 if( pCommSrvc->ResultPoolTail != NULL)
1557 pCommSrvc->ResultPoolTail->fLink = NULL;
1563 pCurrentEntry->fLink->bLink = pCurrentEntry->bLink;
1569 pCurrentEntry = pCurrentEntry->fLink;
1572 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1574 if( pCurrentEntry == NULL)
1577 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1581 // OK, move in the result information
1584 pCurrentEntry->ResultStatus = pResult->ResultStatus;
1586 if( ( pCurrentEntry->ResultStatus == STATUS_SUCCESS ||
1587 pCurrentEntry->ResultStatus == STATUS_BUFFER_OVERFLOW) &&
1588 pCurrentEntry->ResultBufferLength != NULL &&
1589 pCurrentEntry->ResultBuffer != NULL)
1592 ASSERT( pResult->ResultBufferLength <= *(pCurrentEntry->ResultBufferLength));
1594 ulCopyLen = pResult->ResultBufferLength;
1596 if( ulCopyLen > *(pCurrentEntry->ResultBufferLength))
1598 ulCopyLen = *(pCurrentEntry->ResultBufferLength);
1601 *(pCurrentEntry->ResultBufferLength) = ulCopyLen;
1603 if( pResult->ResultBufferLength > 0)
1606 RtlCopyMemory( pCurrentEntry->ResultBuffer,
1607 pResult->ResultData,
1612 KeSetEvent( &pCurrentEntry->Event,
1618 if( !NT_SUCCESS( ntStatus))