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( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
362 AFSDumpTraceFilesFnc();
367 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
370 if( bDecrementCount &&
371 InterlockedDecrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 0)
373 KeSetEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent,
378 if ( ntStatus == STATUS_SUCCESS)
381 ntStatus = STATUS_UNSUCCESSFUL;
389 AFSProcessControlRequest( IN PIRP Irp)
392 NTSTATUS ntStatus = STATUS_SUCCESS;
393 PIO_STACK_LOCATION pIrpSp;
394 ULONG ulIoControlCode;
395 BOOLEAN bCompleteRequest = TRUE;
396 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
397 ULONG ulBytesProcessed = 0;
402 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
404 ulIoControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
406 switch( ulIoControlCode)
409 case IOCTL_AFS_INITIALIZE_CONTROL_DEVICE:
413 // Go intialize the pool
416 ntStatus = AFSInitIrpPool();
418 if( !NT_SUCCESS( ntStatus))
429 // Tag this instance as the one to close the irp pool when it is closed
432 pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_CONTROL_INSTANCE);
437 case IOCTL_AFS_INITIALIZE_REDIRECTOR_DEVICE:
440 AFSRedirectorInitInfo *pRedirInitInfo = (AFSRedirectorInitInfo *)Irp->AssociatedIrp.SystemBuffer;
443 // Extract off the passed in information which contains the
444 // cache file parameters
447 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSRedirectorInitInfo) ||
448 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSRedirectorInitInfo, CacheFileName) +
449 pRedirInitInfo->CacheFileNameLength)
452 ntStatus = STATUS_INVALID_PARAMETER;
458 // Initialize the Redirector device
461 ntStatus = AFSInitializeRedirector( pRedirInitInfo);
463 if( !NT_SUCCESS( ntStatus))
470 // Stash away context so we know the instance used to initialize the redirector
473 pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_REDIRECTOR_INSTANCE);
478 case IOCTL_AFS_PROCESS_IRP_REQUEST:
481 ntStatus = AFSProcessIrpRequest( Irp);
486 case IOCTL_AFS_PROCESS_IRP_RESULT:
489 ntStatus = AFSProcessIrpResult( Irp);
494 case IOCTL_AFS_SYSNAME_NOTIFICATION:
497 AFSSysNameNotificationCB *pSysNameInfo = (AFSSysNameNotificationCB *)Irp->AssociatedIrp.SystemBuffer;
499 if( pSysNameInfo == NULL ||
500 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSSysNameNotificationCB))
503 ntStatus = STATUS_INVALID_PARAMETER;
508 ntStatus = AFSSetSysNameInformation( pSysNameInfo,
509 pIrpSp->Parameters.DeviceIoControl.InputBufferLength);
514 case IOCTL_AFS_CONFIGURE_DEBUG_TRACE:
517 AFSTraceConfigCB *pTraceInfo = (AFSTraceConfigCB *)Irp->AssociatedIrp.SystemBuffer;
519 if( pTraceInfo == NULL ||
520 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSTraceConfigCB))
523 ntStatus = STATUS_INVALID_PARAMETER;
528 ntStatus = AFSConfigureTrace( pTraceInfo);
533 case IOCTL_AFS_GET_TRACE_BUFFER:
536 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0)
539 ntStatus = STATUS_INVALID_PARAMETER;
544 ntStatus = AFSGetTraceBuffer( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
545 Irp->AssociatedIrp.SystemBuffer,
546 &Irp->IoStatus.Information);
551 case IOCTL_AFS_FORCE_CRASH:
556 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_FLAG_ENABLE_FORCE_CRASH))
559 KeBugCheck( (ULONG)-1);
566 #ifdef NOT_IMPLEMENTED
567 case IOCTL_AFS_LOAD_LIBRARY:
570 AFSLoadLibraryCB *pLoadLib = (AFSLoadLibraryCB *)Irp->AssociatedIrp.SystemBuffer;
571 UNICODE_STRING uniServicePath;
573 if( pLoadLib == NULL ||
574 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSLoadLibraryCB) ||
575 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSLoadLibraryCB, LibraryServicePath) +
576 pLoadLib->LibraryServicePathLength)
579 ntStatus = STATUS_INVALID_PARAMETER;
584 uniServicePath.Length = pLoadLib->LibraryServicePathLength;
585 uniServicePath.MaximumLength = uniServicePath.Length;
587 uniServicePath.Buffer = pLoadLib->LibraryServicePath;
589 if( uniServicePath.Length == 0)
592 ntStatus = STATUS_INVALID_PARAMETER;
597 ntStatus = AFSLoadLibrary( pLoadLib->Flags,
600 if( NT_SUCCESS( ntStatus))
604 // Intialize the library
607 ntStatus = AFSInitializeLibrary( NULL,
614 case IOCTL_AFS_UNLOAD_LIBRARY:
618 // Try to unload the library we currently have in place
621 ntStatus = AFSUnloadLibrary( FALSE);
627 case IOCTL_AFS_SHUTDOWN:
630 ntStatus = AFSShutdownRedirector();
635 case IOCTL_AFS_AUTHGROUP_CREATE_AND_SET:
639 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
641 if( pAuthGroupRequestCB == NULL ||
642 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
645 ntStatus = STATUS_INVALID_PARAMETER;
650 ntStatus = AFSCreateSetProcessAuthGroup( pAuthGroupRequestCB);
655 case IOCTL_AFS_AUTHGROUP_QUERY:
658 ntStatus = AFSQueryProcessAuthGroupList( ( GUID *)Irp->AssociatedIrp.SystemBuffer,
659 pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
660 &Irp->IoStatus.Information);
665 case IOCTL_AFS_AUTHGROUP_SET:
668 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
670 if( pAuthGroupRequestCB == NULL ||
671 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
674 ntStatus = STATUS_INVALID_PARAMETER;
679 ntStatus = AFSSetActiveProcessAuthGroup( pAuthGroupRequestCB);
684 case IOCTL_AFS_AUTHGROUP_RESET:
687 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
689 if( pAuthGroupRequestCB == NULL ||
690 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
693 ntStatus = STATUS_INVALID_PARAMETER;
698 ntStatus = AFSResetActiveProcessAuthGroup( pAuthGroupRequestCB);
703 case IOCTL_AFS_AUTHGROUP_LOGON_CREATE:
704 case IOCTL_AFS_AUTHGROUP_SID_CREATE:
707 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
709 if( pAuthGroupRequestCB != NULL &&
710 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
713 ntStatus = STATUS_INVALID_PARAMETER;
718 ntStatus = AFSCreateAuthGroupForSIDorLogonSession( pAuthGroupRequestCB,
719 ulIoControlCode == IOCTL_AFS_AUTHGROUP_LOGON_CREATE);
724 case IOCTL_AFS_AUTHGROUP_SID_QUERY:
727 AFSAuthGroupRequestCB *pAuthGroupRequestCB = NULL;
729 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( GUID))
731 ntStatus = STATUS_INVALID_PARAMETER;
735 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof( AFSAuthGroupRequestCB))
737 pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
740 ntStatus = AFSQueryAuthGroup( pAuthGroupRequestCB,
741 (GUID *)Irp->AssociatedIrp.SystemBuffer,
742 &Irp->IoStatus.Information);
751 // Check the state of the library
754 ntStatus = AFSCheckLibraryState( Irp);
756 if( !NT_SUCCESS( ntStatus) ||
757 ntStatus == STATUS_PENDING)
760 if( ntStatus == STATUS_PENDING)
762 bCompleteRequest = FALSE;
768 bCompleteRequest = FALSE;
770 IoSkipCurrentIrpStackLocation( Irp);
772 ntStatus = IoCallDriver( pDevExt->Specific.Control.LibraryDeviceObject,
776 // Indicate the library is done with the request
779 AFSClearLibraryRequest();
788 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
791 ntStatus = STATUS_UNSUCCESSFUL;
793 AFSDumpTraceFilesFnc();
796 if( bCompleteRequest)
799 Irp->IoStatus.Status = ntStatus;
801 AFSCompleteRequest( Irp,
812 NTSTATUS ntStatus = STATUS_SUCCESS;
813 AFSCommSrvcCB *pCommSrvc = NULL;
814 BOOLEAN bReleasePools = FALSE;
815 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
820 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
823 // Whenever we change state we must grab both pool locks. On the checking of the state
824 // within the processing routines for these respective pools, we only grab one lock to
825 // minimize serialization. The ordering is always the Irp pool then the result pool
826 // locks. We also do this in the tear down of the pool
829 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
830 AFS_TRACE_LEVEL_VERBOSE,
831 "AFSInitIrpPool Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
832 &pCommSrvc->IrpPoolLock,
833 PsGetCurrentThread());
835 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
838 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
839 AFS_TRACE_LEVEL_VERBOSE,
840 "AFSInitIrpPool Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
841 &pCommSrvc->ResultPoolLock,
842 PsGetCurrentThread());
844 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
847 bReleasePools = TRUE;
850 // The pool can be either ACTIVE or INACTIVE. If the pool state is INACTIVE and we
851 // are receiving the INIT request, then activate it. If the pool is ACTIVE, then we
852 // shouldn't be getting this request ...
855 if( pCommSrvc->IrpPoolControlFlag == POOL_ACTIVE)
859 // We have already been activated so just fail this request
862 try_return( ntStatus = STATUS_INVALID_PARAMETER);
864 else if( pCommSrvc->IrpPoolControlFlag == POOL_INACTIVE)
868 // The pool is currently INACTIVE so start it up and ready it to
869 // receive irp requests
872 pCommSrvc->IrpPoolControlFlag = POOL_ACTIVE;
874 pDevExt->Specific.Control.ServiceProcess = (PKPROCESS)PsGetCurrentProcess();
876 try_return( ntStatus = STATUS_SUCCESS);
882 // The pool is in some mixed state, fail the request.
885 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
893 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
895 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
906 NTSTATUS ntStatus = STATUS_SUCCESS;
907 AFSPoolEntry *pEntry = NULL, *pNextEntry = NULL;
908 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
909 AFSCommSrvcCB *pCommSrvc = (AFSCommSrvcCB *)&pDevExt->Specific.Control.CommServiceCB;
915 // When we change the state, grab both pool locks exclusive. The order is always the
916 // Irp pool then the result pool lock
919 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
920 AFS_TRACE_LEVEL_VERBOSE,
921 "AFSCleanupIrpPool Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
922 &pCommSrvc->IrpPoolLock,
923 PsGetCurrentThread());
925 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
928 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
929 AFS_TRACE_LEVEL_VERBOSE,
930 "AFSCleanupIrpPool Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
931 &pCommSrvc->ResultPoolLock,
932 PsGetCurrentThread());
934 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
938 // Indicate we are pending stop
941 pCommSrvc->IrpPoolControlFlag = POOL_INACTIVE;
944 // Set the event to release any waiting workers
945 // (everyone waits on IrpPoolHasReleaseEntries)
948 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
953 // Go through the pool entries and free up the structures.
956 pEntry = pCommSrvc->RequestPoolHead;
958 while( pEntry != NULL)
961 pNextEntry = pEntry->fLink;
963 if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
967 // Here we need to complete the irp, cancelled, and delete the data block
970 pEntry->ResultStatus = STATUS_CANCELLED;
972 KeSetEvent( &pEntry->Event,
986 // Cleanup the control structure for the request pool
989 pCommSrvc->RequestPoolHead = NULL;
991 pCommSrvc->RequestPoolTail = NULL;
993 pCommSrvc->IrpPoolRequestIndex = 1;
995 KeClearEvent( &pCommSrvc->IrpPoolHasEntries);
997 KeClearEvent( &pCommSrvc->IrpPoolHasReleaseEntries);
1000 // Release the irp pool lock.
1003 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1006 // Go through the result pool entries and free up the structures.
1009 pEntry = pCommSrvc->ResultPoolHead;
1011 while( pEntry != NULL)
1014 pNextEntry = pEntry->fLink;
1016 pEntry->ResultStatus = STATUS_CANCELLED;
1019 // Here we will set the event of the requestor and let the blocked thread
1020 // free the data block
1023 KeSetEvent( &pEntry->Event,
1028 // Go onto the next entry
1031 pEntry = pNextEntry;
1035 // Cleanup the control structure for the result pool
1038 pCommSrvc->ResultPoolHead = NULL;
1040 pCommSrvc->ResultPoolTail = NULL;
1043 // Release the result pool lock.
1046 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1053 AFSInsertRequest( IN AFSCommSrvcCB *CommSrvc,
1054 IN AFSPoolEntry *Entry)
1057 NTSTATUS ntStatus = STATUS_SUCCESS;
1062 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1063 AFS_TRACE_LEVEL_VERBOSE,
1064 "AFSInsertRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
1065 &CommSrvc->IrpPoolLock,
1066 PsGetCurrentThread());
1068 AFSAcquireExcl( &CommSrvc->IrpPoolLock,
1071 if( CommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1074 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1077 if( CommSrvc->RequestPoolHead == NULL)
1080 CommSrvc->RequestPoolHead = Entry;
1085 CommSrvc->RequestPoolTail->fLink = Entry;
1087 Entry->bLink = CommSrvc->RequestPoolTail;
1090 CommSrvc->RequestPoolTail = Entry;
1092 if( Entry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1095 KeSetEvent( &CommSrvc->IrpPoolHasReleaseEntries,
1102 KeSetEvent( &CommSrvc->IrpPoolHasEntries,
1107 InterlockedIncrement( &CommSrvc->QueueCount);
1111 AFSReleaseResource( &CommSrvc->IrpPoolLock);
1118 AFSProcessIrpRequest( IN PIRP Irp)
1121 NTSTATUS ntStatus = STATUS_SUCCESS;
1122 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1123 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1124 AFSCommSrvcCB *pCommSrvc = NULL;
1125 AFSPoolEntry *pEntry = NULL, *pPrevEntry = NULL;
1126 AFSCommRequest *pRequest = NULL;
1127 BOOLEAN bReleaseRequestThread = FALSE;
1133 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1135 pRequest = (AFSCommRequest *)Irp->AssociatedIrp.SystemBuffer;
1137 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1138 AFS_TRACE_LEVEL_VERBOSE,
1139 "AFSProcessIrpRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
1140 &pCommSrvc->IrpPoolLock,
1141 PsGetCurrentThread());
1143 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1146 if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1149 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1151 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1154 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1157 // Is this a dedicated flush thread?
1160 if( BooleanFlagOn( pRequest->RequestFlags, AFS_REQUEST_RELEASE_THREAD))
1163 bReleaseRequestThread = TRUE;
1167 // Populate the objects array for the non release only threads
1168 // Release only workers can only process release extent events
1169 // whereas normal workers can process any kind of event.
1170 // Release only workers are present to ensure there cannot be
1171 // a deadlock due to all extents held by the redirector and
1172 // there not be a worker available to release them.
1175 Objects[0] = &pCommSrvc->IrpPoolHasReleaseEntries;
1177 Objects[1] = &pCommSrvc->IrpPoolHasEntries;
1180 // Wait on the 'have items' event until we can retrieve an item
1186 if( bReleaseRequestThread)
1189 ntStatus = KeWaitForSingleObject( &pCommSrvc->IrpPoolHasReleaseEntries,
1195 if( ntStatus != STATUS_SUCCESS)
1198 ntStatus = STATUS_DEVICE_NOT_READY;
1207 ntStatus = KeWaitForMultipleObjects( 2,
1216 if( ntStatus != STATUS_WAIT_0 &&
1217 ntStatus != STATUS_WAIT_1)
1220 ntStatus = STATUS_DEVICE_NOT_READY;
1227 // Grab the lock on the request pool
1230 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1231 AFS_TRACE_LEVEL_VERBOSE,
1232 "AFSProcessIrpRequest Acquiring IrpPoolLock (WAIT) lock %08lX EXCL %08lX\n",
1233 &pCommSrvc->IrpPoolLock,
1234 PsGetCurrentThread());
1236 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1239 if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1242 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1245 // Wake up the next worker since this is a SynchronizationEvent
1248 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1252 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1256 // If this is a dedicated flush thread only look for a flush request in the queue
1259 if( bReleaseRequestThread)
1262 pEntry = pCommSrvc->RequestPoolHead;
1266 while( pEntry != NULL)
1269 if( pEntry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1272 if( pPrevEntry == NULL)
1275 pCommSrvc->RequestPoolHead = pEntry->fLink;
1277 if( pCommSrvc->RequestPoolHead == NULL)
1280 pCommSrvc->RequestPoolTail = NULL;
1286 pPrevEntry->fLink = pEntry->fLink;
1288 if( pPrevEntry->fLink == NULL)
1291 pCommSrvc->RequestPoolTail = pPrevEntry;
1298 pPrevEntry = pEntry;
1300 pEntry = pEntry->fLink;
1307 // There might be another release entry pending
1310 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1316 // And release the request pool lock
1319 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1324 pEntry = pCommSrvc->RequestPoolHead;
1329 pCommSrvc->RequestPoolHead = pEntry->fLink;
1331 pEntry->bLink = NULL;
1333 if( pCommSrvc->RequestPoolHead == NULL)
1336 pCommSrvc->RequestPoolTail = NULL;
1341 KeSetEvent( &pCommSrvc->IrpPoolHasEntries,
1348 // And release the request pool lock
1351 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1355 // Insert the entry into the result pool, if we have one
1362 // Move the request data into the passed in buffer
1365 ASSERT( sizeof( AFSCommRequest) +
1366 pEntry->FileName.Length +
1367 pEntry->DataLength <= pIrpSp->Parameters.DeviceIoControl.OutputBufferLength);
1369 RtlCopyMemory( &pRequest->AuthGroup,
1373 pRequest->FileId = pEntry->FileId;
1375 pRequest->RequestType = pEntry->RequestType;
1377 pRequest->RequestIndex = pEntry->RequestIndex;
1379 pRequest->RequestFlags = pEntry->RequestFlags;
1381 pRequest->NameLength = pEntry->FileName.Length;
1383 pRequest->QueueCount = InterlockedDecrement( &pCommSrvc->QueueCount);
1385 if( pRequest->NameLength > 0)
1388 RtlCopyMemory( pRequest->Name,
1389 pEntry->FileName.Buffer,
1390 pRequest->NameLength);
1393 pRequest->DataOffset = 0;
1395 pRequest->DataLength = pEntry->DataLength;
1397 if( pRequest->DataLength > 0)
1400 pRequest->DataOffset = pEntry->FileName.Length;
1402 RtlCopyMemory( (void *)((char *)pRequest->Name + pRequest->DataOffset),
1404 pRequest->DataLength);
1407 pRequest->ResultBufferLength = 0;
1409 if( pEntry->ResultBufferLength != NULL)
1412 pRequest->ResultBufferLength = *(pEntry->ResultBufferLength);
1415 Irp->IoStatus.Information = sizeof( AFSCommRequest) +
1416 pEntry->FileName.Length +
1420 // If this is a synchronous request then move the request into the
1424 if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
1427 pEntry->fLink = NULL;
1428 pEntry->bLink = NULL;
1430 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1431 AFS_TRACE_LEVEL_VERBOSE,
1432 "AFSProcessIrpRequest Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
1433 &pCommSrvc->ResultPoolLock,
1434 PsGetCurrentThread());
1436 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1439 if( pCommSrvc->ResultPoolHead == NULL)
1442 pCommSrvc->ResultPoolHead = pEntry;
1447 pCommSrvc->ResultPoolTail->fLink = pEntry;
1449 pEntry->bLink = pCommSrvc->ResultPoolTail;
1452 pCommSrvc->ResultPoolTail = pEntry;
1454 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1460 // Free up the pool entry
1463 ExFreePool( pEntry);
1479 AFSProcessIrpResult( IN PIRP Irp)
1482 NTSTATUS ntStatus = STATUS_SUCCESS;
1483 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1484 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1485 AFSCommSrvcCB *pCommSrvc = NULL;
1486 AFSPoolEntry *pCurrentEntry = NULL;
1487 AFSCommResult *pResult = NULL;
1488 ULONG ulCopyLen = 0;
1493 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1496 // Get the request for the incoming result
1499 pResult = (AFSCommResult *)Irp->AssociatedIrp.SystemBuffer;
1501 if( pResult == NULL)
1504 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1508 // Go look for our entry
1511 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1512 AFS_TRACE_LEVEL_VERBOSE,
1513 "AFSProcessIrpResult Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
1514 &pCommSrvc->ResultPoolLock,
1515 PsGetCurrentThread());
1517 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1520 pCurrentEntry = pCommSrvc->ResultPoolHead;
1522 while( pCurrentEntry != NULL)
1525 if( pCurrentEntry->RequestIndex == pResult->RequestIndex)
1529 // Found the entry so remove it from the queue
1532 if( pCurrentEntry->bLink == NULL)
1536 // At the head of the list
1539 pCommSrvc->ResultPoolHead = pCurrentEntry->fLink;
1541 if( pCommSrvc->ResultPoolHead != NULL)
1544 pCommSrvc->ResultPoolHead->bLink = NULL;
1550 pCurrentEntry->bLink->fLink = pCurrentEntry->fLink;
1553 if( pCurrentEntry->fLink == NULL)
1556 pCommSrvc->ResultPoolTail = pCurrentEntry->bLink;
1558 if( pCommSrvc->ResultPoolTail != NULL)
1561 pCommSrvc->ResultPoolTail->fLink = NULL;
1567 pCurrentEntry->fLink->bLink = pCurrentEntry->bLink;
1573 pCurrentEntry = pCurrentEntry->fLink;
1576 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1578 if( pCurrentEntry == NULL)
1581 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1585 // OK, move in the result information
1588 pCurrentEntry->ResultStatus = pResult->ResultStatus;
1590 if( ( pCurrentEntry->ResultStatus == STATUS_SUCCESS ||
1591 pCurrentEntry->ResultStatus == STATUS_BUFFER_OVERFLOW) &&
1592 pCurrentEntry->ResultBufferLength != NULL &&
1593 pCurrentEntry->ResultBuffer != NULL)
1596 ASSERT( pResult->ResultBufferLength <= *(pCurrentEntry->ResultBufferLength));
1598 ulCopyLen = pResult->ResultBufferLength;
1600 if( ulCopyLen > *(pCurrentEntry->ResultBufferLength))
1602 ulCopyLen = *(pCurrentEntry->ResultBufferLength);
1605 *(pCurrentEntry->ResultBufferLength) = ulCopyLen;
1607 if( pResult->ResultBufferLength > 0)
1610 RtlCopyMemory( pCurrentEntry->ResultBuffer,
1611 pResult->ResultData,
1616 KeSetEvent( &pCurrentEntry->Event,
1622 if( !NT_SUCCESS( ntStatus))