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
943 KeSetEvent( &pCommSrvc->IrpPoolHasEntries,
947 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
952 // Go through the pool entries and free up the structures.
955 pEntry = pCommSrvc->RequestPoolHead;
957 while( pEntry != NULL)
960 pNextEntry = pEntry->fLink;
962 if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
966 // Here we need to complete the irp, cancelled, and delete the data block
969 pEntry->ResultStatus = STATUS_CANCELLED;
971 KeSetEvent( &pEntry->Event,
985 // Cleanup the control structure for the request pool
988 pCommSrvc->RequestPoolHead = NULL;
990 pCommSrvc->RequestPoolTail = NULL;
992 pCommSrvc->IrpPoolRequestIndex = 1;
994 KeClearEvent( &pCommSrvc->IrpPoolHasEntries);
996 KeClearEvent( &pCommSrvc->IrpPoolHasReleaseEntries);
999 // Release the irp pool lock.
1002 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1005 // Go through the result pool entries and free up the structures.
1008 pEntry = pCommSrvc->ResultPoolHead;
1010 while( pEntry != NULL)
1013 pNextEntry = pEntry->fLink;
1015 pEntry->ResultStatus = STATUS_CANCELLED;
1018 // Here we will set the event of the requestor and let the blocked thread
1019 // free the data block
1022 KeSetEvent( &pEntry->Event,
1027 // Go onto the next entry
1030 pEntry = pNextEntry;
1034 // Cleanup the control structure for the result pool
1037 pCommSrvc->ResultPoolHead = NULL;
1039 pCommSrvc->ResultPoolTail = NULL;
1042 // Release the result pool lock.
1045 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1052 AFSInsertRequest( IN AFSCommSrvcCB *CommSrvc,
1053 IN AFSPoolEntry *Entry)
1056 NTSTATUS ntStatus = STATUS_SUCCESS;
1061 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1062 AFS_TRACE_LEVEL_VERBOSE,
1063 "AFSInsertRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
1064 &CommSrvc->IrpPoolLock,
1065 PsGetCurrentThread());
1067 AFSAcquireExcl( &CommSrvc->IrpPoolLock,
1070 if( CommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1073 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1076 if( CommSrvc->RequestPoolHead == NULL)
1079 CommSrvc->RequestPoolHead = Entry;
1084 CommSrvc->RequestPoolTail->fLink = Entry;
1086 Entry->bLink = CommSrvc->RequestPoolTail;
1089 CommSrvc->RequestPoolTail = Entry;
1091 if( Entry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1094 KeSetEvent( &CommSrvc->IrpPoolHasReleaseEntries,
1101 KeSetEvent( &CommSrvc->IrpPoolHasEntries,
1106 InterlockedIncrement( &CommSrvc->QueueCount);
1110 AFSReleaseResource( &CommSrvc->IrpPoolLock);
1117 AFSProcessIrpRequest( IN PIRP Irp)
1120 NTSTATUS ntStatus = STATUS_SUCCESS;
1121 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1122 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1123 AFSCommSrvcCB *pCommSrvc = NULL;
1124 AFSPoolEntry *pEntry = NULL, *pPrevEntry = NULL;
1125 AFSCommRequest *pRequest = NULL;
1126 BOOLEAN bReleaseRequestThread = FALSE;
1132 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1134 pRequest = (AFSCommRequest *)Irp->AssociatedIrp.SystemBuffer;
1136 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1137 AFS_TRACE_LEVEL_VERBOSE,
1138 "AFSProcessIrpRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
1139 &pCommSrvc->IrpPoolLock,
1140 PsGetCurrentThread());
1142 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1145 if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1148 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1150 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1153 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1156 // Is this a dedicated flush thread?
1159 if( BooleanFlagOn( pRequest->RequestFlags, AFS_REQUEST_RELEASE_THREAD))
1162 bReleaseRequestThread = TRUE;
1166 // Populate the objects array for the non release only threads
1167 // Release only workers can only process release extent events
1168 // whereas normal workers can process any kind of event.
1169 // Release only workers are present to ensure there cannot be
1170 // a deadlock due to all extents held by the redirector and
1171 // there not be a worker available to release them.
1174 Objects[0] = &pCommSrvc->IrpPoolHasReleaseEntries;
1176 Objects[1] = &pCommSrvc->IrpPoolHasEntries;
1179 // Wait on the 'have items' event until we can retrieve an item
1185 if( bReleaseRequestThread)
1188 ntStatus = KeWaitForSingleObject( &pCommSrvc->IrpPoolHasReleaseEntries,
1194 if( ntStatus != STATUS_SUCCESS)
1197 ntStatus = STATUS_DEVICE_NOT_READY;
1206 ntStatus = KeWaitForMultipleObjects( 2,
1215 if( ntStatus != STATUS_WAIT_0 &&
1216 ntStatus != STATUS_WAIT_1)
1219 ntStatus = STATUS_DEVICE_NOT_READY;
1226 // Grab the lock on the request pool
1229 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1230 AFS_TRACE_LEVEL_VERBOSE,
1231 "AFSProcessIrpRequest Acquiring IrpPoolLock (WAIT) lock %08lX EXCL %08lX\n",
1232 &pCommSrvc->IrpPoolLock,
1233 PsGetCurrentThread());
1235 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1238 if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1241 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1243 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1247 // If this is a dedicated flush thread only look for a flush request in the queue
1250 if( bReleaseRequestThread)
1253 pEntry = pCommSrvc->RequestPoolHead;
1257 while( pEntry != NULL)
1260 if( pEntry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1263 if( pPrevEntry == NULL)
1266 pCommSrvc->RequestPoolHead = pEntry->fLink;
1268 if( pCommSrvc->RequestPoolHead == NULL)
1271 pCommSrvc->RequestPoolTail = NULL;
1277 pPrevEntry->fLink = pEntry->fLink;
1279 if( pPrevEntry->fLink == NULL)
1282 pCommSrvc->RequestPoolTail = pPrevEntry;
1289 pPrevEntry = pEntry;
1291 pEntry = pEntry->fLink;
1294 if( pCommSrvc->RequestPoolHead == NULL)
1297 KeClearEvent( &pCommSrvc->IrpPoolHasEntries);
1303 KeClearEvent( &pCommSrvc->IrpPoolHasReleaseEntries);
1307 // And release the request pool lock
1310 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1315 pEntry = pCommSrvc->RequestPoolHead;
1320 pCommSrvc->RequestPoolHead = pEntry->fLink;
1322 pEntry->bLink = NULL;
1324 if( pCommSrvc->RequestPoolHead == NULL)
1327 pCommSrvc->RequestPoolTail = NULL;
1333 KeClearEvent( &pCommSrvc->IrpPoolHasEntries);
1337 // And release the request pool lock
1340 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1344 // Insert the entry into the result pool, if we have one
1351 // Move the request data into the passed in buffer
1354 ASSERT( sizeof( AFSCommRequest) +
1355 pEntry->FileName.Length +
1356 pEntry->DataLength <= pIrpSp->Parameters.DeviceIoControl.OutputBufferLength);
1358 RtlCopyMemory( &pRequest->AuthGroup,
1362 pRequest->FileId = pEntry->FileId;
1364 pRequest->RequestType = pEntry->RequestType;
1366 pRequest->RequestIndex = pEntry->RequestIndex;
1368 pRequest->RequestFlags = pEntry->RequestFlags;
1370 pRequest->NameLength = pEntry->FileName.Length;
1372 pRequest->QueueCount = InterlockedDecrement( &pCommSrvc->QueueCount);
1374 if( pRequest->NameLength > 0)
1377 RtlCopyMemory( pRequest->Name,
1378 pEntry->FileName.Buffer,
1379 pRequest->NameLength);
1382 pRequest->DataOffset = 0;
1384 pRequest->DataLength = pEntry->DataLength;
1386 if( pRequest->DataLength > 0)
1389 pRequest->DataOffset = pEntry->FileName.Length;
1391 RtlCopyMemory( (void *)((char *)pRequest->Name + pRequest->DataOffset),
1393 pRequest->DataLength);
1396 pRequest->ResultBufferLength = 0;
1398 if( pEntry->ResultBufferLength != NULL)
1401 pRequest->ResultBufferLength = *(pEntry->ResultBufferLength);
1404 Irp->IoStatus.Information = sizeof( AFSCommRequest) +
1405 pEntry->FileName.Length +
1409 // If this is a synchronous request then move the request into the
1413 if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
1416 pEntry->fLink = NULL;
1417 pEntry->bLink = NULL;
1419 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1420 AFS_TRACE_LEVEL_VERBOSE,
1421 "AFSProcessIrpRequest Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
1422 &pCommSrvc->ResultPoolLock,
1423 PsGetCurrentThread());
1425 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1428 if( pCommSrvc->ResultPoolHead == NULL)
1431 pCommSrvc->ResultPoolHead = pEntry;
1436 pCommSrvc->ResultPoolTail->fLink = pEntry;
1438 pEntry->bLink = pCommSrvc->ResultPoolTail;
1441 pCommSrvc->ResultPoolTail = pEntry;
1443 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1449 // Free up the pool entry
1452 ExFreePool( pEntry);
1468 AFSProcessIrpResult( IN PIRP Irp)
1471 NTSTATUS ntStatus = STATUS_SUCCESS;
1472 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1473 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1474 AFSCommSrvcCB *pCommSrvc = NULL;
1475 AFSPoolEntry *pCurrentEntry = NULL;
1476 AFSCommResult *pResult = NULL;
1477 ULONG ulCopyLen = 0;
1482 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1485 // Get the request for the incoming result
1488 pResult = (AFSCommResult *)Irp->AssociatedIrp.SystemBuffer;
1490 if( pResult == NULL)
1493 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1497 // Go look for our entry
1500 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1501 AFS_TRACE_LEVEL_VERBOSE,
1502 "AFSProcessIrpResult Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
1503 &pCommSrvc->ResultPoolLock,
1504 PsGetCurrentThread());
1506 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1509 pCurrentEntry = pCommSrvc->ResultPoolHead;
1511 while( pCurrentEntry != NULL)
1514 if( pCurrentEntry->RequestIndex == pResult->RequestIndex)
1518 // Found the entry so remove it from the queue
1521 if( pCurrentEntry->bLink == NULL)
1525 // At the head of the list
1528 pCommSrvc->ResultPoolHead = pCurrentEntry->fLink;
1530 if( pCommSrvc->ResultPoolHead != NULL)
1533 pCommSrvc->ResultPoolHead->bLink = NULL;
1539 pCurrentEntry->bLink->fLink = pCurrentEntry->fLink;
1542 if( pCurrentEntry->fLink == NULL)
1545 pCommSrvc->ResultPoolTail = pCurrentEntry->bLink;
1547 if( pCommSrvc->ResultPoolTail != NULL)
1550 pCommSrvc->ResultPoolTail->fLink = NULL;
1556 pCurrentEntry->fLink->bLink = pCurrentEntry->bLink;
1562 pCurrentEntry = pCurrentEntry->fLink;
1565 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1567 if( pCurrentEntry == NULL)
1570 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1574 // OK, move in the result information
1577 pCurrentEntry->ResultStatus = pResult->ResultStatus;
1579 if( ( pCurrentEntry->ResultStatus == STATUS_SUCCESS ||
1580 pCurrentEntry->ResultStatus == STATUS_BUFFER_OVERFLOW) &&
1581 pCurrentEntry->ResultBufferLength != NULL &&
1582 pCurrentEntry->ResultBuffer != NULL)
1585 ASSERT( pResult->ResultBufferLength <= *(pCurrentEntry->ResultBufferLength));
1587 ulCopyLen = pResult->ResultBufferLength;
1589 if( ulCopyLen > *(pCurrentEntry->ResultBufferLength))
1591 ulCopyLen = *(pCurrentEntry->ResultBufferLength);
1594 *(pCurrentEntry->ResultBufferLength) = ulCopyLen;
1596 if( pResult->ResultBufferLength > 0)
1599 RtlCopyMemory( pCurrentEntry->ResultBuffer,
1600 pResult->ResultData,
1605 KeSetEvent( &pCurrentEntry->Event,
1611 if( !NT_SUCCESS( ntStatus))