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;
401 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
403 ulIoControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
405 switch( ulIoControlCode)
408 case IOCTL_AFS_INITIALIZE_CONTROL_DEVICE:
410 if ( !AFSIsUser( SeExports->SeLocalSystemSid)
412 && !BooleanFlagOn( AFSDebugFlags, AFS_DBG_DISABLE_SYSTEM_SID_CHECK)
417 ntStatus = STATUS_ACCESS_DENIED;
421 // Go intialize the pool
423 ntStatus = AFSInitIrpPool();
425 if( !NT_SUCCESS( ntStatus))
436 // Tag this instance as the one to close the irp pool when it is closed
439 pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_CONTROL_INSTANCE);
441 AFSRegisterService();
446 case IOCTL_AFS_INITIALIZE_REDIRECTOR_DEVICE:
449 AFSRedirectorInitInfo *pRedirInitInfo = (AFSRedirectorInitInfo *)Irp->AssociatedIrp.SystemBuffer;
451 if ( !AFSIsService())
454 ntStatus = STATUS_ACCESS_DENIED;
460 // Extract off the passed in information which contains the
461 // cache file parameters
464 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSRedirectorInitInfo) ||
465 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSRedirectorInitInfo, CacheFileName) +
466 pRedirInitInfo->CacheFileNameLength)
469 ntStatus = STATUS_INVALID_PARAMETER;
475 // Initialize the Redirector device
478 ntStatus = AFSInitializeRedirector( pRedirInitInfo);
480 if( !NT_SUCCESS( ntStatus))
487 // Stash away context so we know the instance used to initialize the redirector
490 pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_REDIRECTOR_INSTANCE);
495 case IOCTL_AFS_PROCESS_IRP_REQUEST:
498 if ( !AFSIsService())
501 ntStatus = STATUS_ACCESS_DENIED;
506 ntStatus = AFSProcessIrpRequest( Irp);
511 case IOCTL_AFS_PROCESS_IRP_RESULT:
514 if ( !AFSIsService())
517 ntStatus = STATUS_ACCESS_DENIED;
522 ntStatus = AFSProcessIrpResult( Irp);
527 case IOCTL_AFS_SYSNAME_NOTIFICATION:
530 AFSSysNameNotificationCB *pSysNameInfo = (AFSSysNameNotificationCB *)Irp->AssociatedIrp.SystemBuffer;
532 if ( !AFSIsService())
535 ntStatus = STATUS_ACCESS_DENIED;
540 if( pSysNameInfo == NULL ||
541 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSSysNameNotificationCB))
544 ntStatus = STATUS_INVALID_PARAMETER;
549 ntStatus = AFSSetSysNameInformation( pSysNameInfo,
550 pIrpSp->Parameters.DeviceIoControl.InputBufferLength);
555 case IOCTL_AFS_CONFIGURE_DEBUG_TRACE:
558 AFSTraceConfigCB *pTraceInfo = (AFSTraceConfigCB *)Irp->AssociatedIrp.SystemBuffer;
560 if ( !AFSIsInGroup( SeExports->SeAliasAdminsSid))
563 ntStatus = STATUS_ACCESS_DENIED;
567 if( pTraceInfo == NULL ||
568 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSTraceConfigCB))
571 ntStatus = STATUS_INVALID_PARAMETER;
576 ntStatus = AFSConfigureTrace( pTraceInfo);
581 case IOCTL_AFS_GET_TRACE_BUFFER:
584 if ( !AFSIsInGroup( SeExports->SeAliasAdminsSid))
587 ntStatus = STATUS_ACCESS_DENIED;
591 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0)
594 ntStatus = STATUS_INVALID_PARAMETER;
599 ntStatus = AFSGetTraceBuffer( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
600 Irp->AssociatedIrp.SystemBuffer,
601 &Irp->IoStatus.Information);
606 case IOCTL_AFS_FORCE_CRASH:
609 if ( !AFSIsInGroup( SeExports->SeAliasAdminsSid))
612 ntStatus = STATUS_ACCESS_DENIED;
618 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_FLAG_ENABLE_FORCE_CRASH))
621 KeBugCheck( (ULONG)-1);
628 #ifdef NOT_IMPLEMENTED
629 case IOCTL_AFS_LOAD_LIBRARY:
632 AFSLoadLibraryCB *pLoadLib = (AFSLoadLibraryCB *)Irp->AssociatedIrp.SystemBuffer;
633 UNICODE_STRING uniServicePath;
635 if( pLoadLib == NULL ||
636 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSLoadLibraryCB) ||
637 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSLoadLibraryCB, LibraryServicePath) +
638 pLoadLib->LibraryServicePathLength)
641 ntStatus = STATUS_INVALID_PARAMETER;
646 uniServicePath.Length = pLoadLib->LibraryServicePathLength;
647 uniServicePath.MaximumLength = uniServicePath.Length;
649 uniServicePath.Buffer = pLoadLib->LibraryServicePath;
651 if( uniServicePath.Length == 0)
654 ntStatus = STATUS_INVALID_PARAMETER;
659 ntStatus = AFSLoadLibrary( pLoadLib->Flags,
662 if( NT_SUCCESS( ntStatus))
666 // Intialize the library
669 ntStatus = AFSInitializeLibrary( NULL,
676 case IOCTL_AFS_UNLOAD_LIBRARY:
680 // Try to unload the library we currently have in place
683 ntStatus = AFSUnloadLibrary( FALSE);
689 case IOCTL_AFS_SHUTDOWN:
692 if ( !AFSIsService())
695 ntStatus = STATUS_ACCESS_DENIED;
700 ntStatus = AFSShutdownRedirector();
705 case IOCTL_AFS_AUTHGROUP_CREATE_AND_SET:
708 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
710 if( pAuthGroupRequestCB == NULL ||
711 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
714 ntStatus = STATUS_INVALID_PARAMETER;
719 ntStatus = AFSCreateSetProcessAuthGroup( pAuthGroupRequestCB);
724 case IOCTL_AFS_AUTHGROUP_QUERY:
727 ntStatus = AFSQueryProcessAuthGroupList( ( GUID *)Irp->AssociatedIrp.SystemBuffer,
728 pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
729 &Irp->IoStatus.Information);
734 case IOCTL_AFS_AUTHGROUP_SET:
737 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
739 if( pAuthGroupRequestCB == NULL ||
740 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
743 ntStatus = STATUS_INVALID_PARAMETER;
748 ntStatus = AFSSetActiveProcessAuthGroup( pAuthGroupRequestCB);
753 case IOCTL_AFS_AUTHGROUP_RESET:
756 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
758 if( pAuthGroupRequestCB == NULL ||
759 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
762 ntStatus = STATUS_INVALID_PARAMETER;
767 ntStatus = AFSResetActiveProcessAuthGroup( pAuthGroupRequestCB);
772 case IOCTL_AFS_AUTHGROUP_LOGON_CREATE:
773 case IOCTL_AFS_AUTHGROUP_SID_CREATE:
776 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
778 if( pAuthGroupRequestCB != NULL &&
779 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
782 ntStatus = STATUS_INVALID_PARAMETER;
787 ntStatus = AFSCreateAuthGroupForSIDorLogonSession( pAuthGroupRequestCB,
788 ulIoControlCode == IOCTL_AFS_AUTHGROUP_LOGON_CREATE);
793 case IOCTL_AFS_AUTHGROUP_SID_QUERY:
796 AFSAuthGroupRequestCB *pAuthGroupRequestCB = NULL;
798 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( GUID))
800 ntStatus = STATUS_INVALID_PARAMETER;
804 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof( AFSAuthGroupRequestCB))
806 pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
809 ntStatus = AFSQueryAuthGroup( pAuthGroupRequestCB,
810 (GUID *)Irp->AssociatedIrp.SystemBuffer,
811 &Irp->IoStatus.Information);
820 // Check the state of the library
823 ntStatus = AFSCheckLibraryState( Irp);
825 if( !NT_SUCCESS( ntStatus) ||
826 ntStatus == STATUS_PENDING)
829 if( ntStatus == STATUS_PENDING)
831 bCompleteRequest = FALSE;
837 bCompleteRequest = FALSE;
839 IoSkipCurrentIrpStackLocation( Irp);
841 ntStatus = IoCallDriver( pDevExt->Specific.Control.LibraryDeviceObject,
845 // Indicate the library is done with the request
848 AFSClearLibraryRequest();
857 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
860 ntStatus = STATUS_UNSUCCESSFUL;
862 AFSDumpTraceFilesFnc();
865 if( bCompleteRequest)
868 Irp->IoStatus.Status = ntStatus;
870 AFSCompleteRequest( Irp,
881 NTSTATUS ntStatus = STATUS_SUCCESS;
882 AFSCommSrvcCB *pCommSrvc = NULL;
883 BOOLEAN bReleasePools = FALSE;
884 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
889 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
892 // Whenever we change state we must grab both pool locks. On the checking of the state
893 // within the processing routines for these respective pools, we only grab one lock to
894 // minimize serialization. The ordering is always the Irp pool then the result pool
895 // locks. We also do this in the tear down of the pool
898 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
899 AFS_TRACE_LEVEL_VERBOSE,
900 "AFSInitIrpPool Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
901 &pCommSrvc->IrpPoolLock,
902 PsGetCurrentThread());
904 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
907 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
908 AFS_TRACE_LEVEL_VERBOSE,
909 "AFSInitIrpPool Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
910 &pCommSrvc->ResultPoolLock,
911 PsGetCurrentThread());
913 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
916 bReleasePools = TRUE;
919 // The pool can be either ACTIVE or INACTIVE. If the pool state is INACTIVE and we
920 // are receiving the INIT request, then activate it. If the pool is ACTIVE, then we
921 // shouldn't be getting this request ...
924 if( pCommSrvc->IrpPoolControlFlag == POOL_ACTIVE)
928 // We have already been activated so just fail this request
931 try_return( ntStatus = STATUS_INVALID_PARAMETER);
933 else if( pCommSrvc->IrpPoolControlFlag == POOL_INACTIVE)
937 // The pool is currently INACTIVE so start it up and ready it to
938 // receive irp requests
941 pCommSrvc->IrpPoolControlFlag = POOL_ACTIVE;
943 pDevExt->Specific.Control.ServiceProcess = (PKPROCESS)PsGetCurrentProcess();
945 try_return( ntStatus = STATUS_SUCCESS);
951 // The pool is in some mixed state, fail the request.
954 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
962 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
964 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
975 AFSPoolEntry *pEntry = NULL, *pNextEntry = NULL;
976 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
977 AFSCommSrvcCB *pCommSrvc = (AFSCommSrvcCB *)&pDevExt->Specific.Control.CommServiceCB;
983 // When we change the state, grab both pool locks exclusive. The order is always the
984 // Irp pool then the result pool lock
987 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
988 AFS_TRACE_LEVEL_VERBOSE,
989 "AFSCleanupIrpPool Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
990 &pCommSrvc->IrpPoolLock,
991 PsGetCurrentThread());
993 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
996 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
997 AFS_TRACE_LEVEL_VERBOSE,
998 "AFSCleanupIrpPool Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
999 &pCommSrvc->ResultPoolLock,
1000 PsGetCurrentThread());
1002 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1006 // Indicate we are pending stop
1009 pCommSrvc->IrpPoolControlFlag = POOL_INACTIVE;
1012 // Set the event to release any waiting workers
1013 // (everyone waits on IrpPoolHasReleaseEntries)
1016 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1021 // Go through the pool entries and free up the structures.
1024 pEntry = pCommSrvc->RequestPoolHead;
1026 while( pEntry != NULL)
1029 pNextEntry = pEntry->fLink;
1031 if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
1035 // Here we need to complete the irp, cancelled, and delete the data block
1038 pEntry->ResultStatus = (ULONG) STATUS_CANCELLED;
1040 KeSetEvent( &pEntry->Event,
1047 ExFreePool( pEntry);
1050 pEntry = pNextEntry;
1054 // Cleanup the control structure for the request pool
1057 pCommSrvc->RequestPoolHead = NULL;
1059 pCommSrvc->RequestPoolTail = NULL;
1061 pCommSrvc->IrpPoolRequestIndex = 1;
1063 KeClearEvent( &pCommSrvc->IrpPoolHasEntries);
1065 KeClearEvent( &pCommSrvc->IrpPoolHasReleaseEntries);
1068 // Release the irp pool lock.
1071 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1074 // Go through the result pool entries and free up the structures.
1077 pEntry = pCommSrvc->ResultPoolHead;
1079 while( pEntry != NULL)
1082 pNextEntry = pEntry->fLink;
1084 pEntry->ResultStatus = (ULONG) STATUS_CANCELLED;
1087 // Here we will set the event of the requestor and let the blocked thread
1088 // free the data block
1091 KeSetEvent( &pEntry->Event,
1096 // Go onto the next entry
1099 pEntry = pNextEntry;
1103 // Cleanup the control structure for the result pool
1106 pCommSrvc->ResultPoolHead = NULL;
1108 pCommSrvc->ResultPoolTail = NULL;
1111 // Release the result pool lock.
1114 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1122 AFSInsertRequest( IN AFSCommSrvcCB *CommSrvc,
1123 IN AFSPoolEntry *Entry)
1126 NTSTATUS ntStatus = STATUS_SUCCESS;
1131 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1132 AFS_TRACE_LEVEL_VERBOSE,
1133 "AFSInsertRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
1134 &CommSrvc->IrpPoolLock,
1135 PsGetCurrentThread());
1137 AFSAcquireExcl( &CommSrvc->IrpPoolLock,
1140 if( CommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1143 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1146 if( CommSrvc->RequestPoolHead == NULL)
1149 CommSrvc->RequestPoolHead = Entry;
1154 CommSrvc->RequestPoolTail->fLink = Entry;
1156 Entry->bLink = CommSrvc->RequestPoolTail;
1159 CommSrvc->RequestPoolTail = Entry;
1161 if( Entry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1164 KeSetEvent( &CommSrvc->IrpPoolHasReleaseEntries,
1171 KeSetEvent( &CommSrvc->IrpPoolHasEntries,
1176 InterlockedIncrement( &CommSrvc->QueueCount);
1180 AFSReleaseResource( &CommSrvc->IrpPoolLock);
1187 AFSProcessIrpRequest( IN PIRP Irp)
1190 NTSTATUS ntStatus = STATUS_SUCCESS;
1191 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1192 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1193 AFSCommSrvcCB *pCommSrvc = NULL;
1194 AFSPoolEntry *pEntry = NULL, *pPrevEntry = NULL;
1195 AFSCommRequest *pRequest = NULL;
1196 BOOLEAN bReleaseRequestThread = FALSE;
1202 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1204 pRequest = (AFSCommRequest *)Irp->AssociatedIrp.SystemBuffer;
1206 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1207 AFS_TRACE_LEVEL_VERBOSE,
1208 "AFSProcessIrpRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
1209 &pCommSrvc->IrpPoolLock,
1210 PsGetCurrentThread());
1212 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1215 if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1218 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1220 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1223 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1226 // Is this a dedicated flush thread?
1229 if( BooleanFlagOn( pRequest->RequestFlags, AFS_REQUEST_RELEASE_THREAD))
1232 bReleaseRequestThread = TRUE;
1236 // Populate the objects array for the non release only threads
1237 // Release only workers can only process release extent events
1238 // whereas normal workers can process any kind of event.
1239 // Release only workers are present to ensure there cannot be
1240 // a deadlock due to all extents held by the redirector and
1241 // there not be a worker available to release them.
1244 Objects[0] = &pCommSrvc->IrpPoolHasReleaseEntries;
1246 Objects[1] = &pCommSrvc->IrpPoolHasEntries;
1249 // Wait on the 'have items' event until we can retrieve an item
1255 if( bReleaseRequestThread)
1258 ntStatus = KeWaitForSingleObject( &pCommSrvc->IrpPoolHasReleaseEntries,
1264 if( ntStatus != STATUS_SUCCESS)
1267 ntStatus = STATUS_DEVICE_NOT_READY;
1276 ntStatus = KeWaitForMultipleObjects( 2,
1285 if( ntStatus != STATUS_WAIT_0 &&
1286 ntStatus != STATUS_WAIT_1)
1289 ntStatus = STATUS_DEVICE_NOT_READY;
1296 // Grab the lock on the request pool
1299 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1300 AFS_TRACE_LEVEL_VERBOSE,
1301 "AFSProcessIrpRequest Acquiring IrpPoolLock (WAIT) lock %08lX EXCL %08lX\n",
1302 &pCommSrvc->IrpPoolLock,
1303 PsGetCurrentThread());
1305 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1308 if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1311 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1314 // Wake up the next worker since this is a SynchronizationEvent
1317 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1321 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1325 // If this is a dedicated flush thread only look for a flush request in the queue
1328 if( bReleaseRequestThread)
1331 pEntry = pCommSrvc->RequestPoolHead;
1335 while( pEntry != NULL)
1338 if( pEntry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1341 if( pPrevEntry == NULL)
1344 pCommSrvc->RequestPoolHead = pEntry->fLink;
1346 if( pCommSrvc->RequestPoolHead == NULL)
1349 pCommSrvc->RequestPoolTail = NULL;
1355 pPrevEntry->fLink = pEntry->fLink;
1357 if( pPrevEntry->fLink == NULL)
1360 pCommSrvc->RequestPoolTail = pPrevEntry;
1367 pPrevEntry = pEntry;
1369 pEntry = pEntry->fLink;
1376 // There might be another release entry pending
1379 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1385 // And release the request pool lock
1388 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1393 pEntry = pCommSrvc->RequestPoolHead;
1398 pCommSrvc->RequestPoolHead = pEntry->fLink;
1400 pEntry->bLink = NULL;
1402 if( pCommSrvc->RequestPoolHead == NULL)
1405 pCommSrvc->RequestPoolTail = NULL;
1410 KeSetEvent( &pCommSrvc->IrpPoolHasEntries,
1417 // And release the request pool lock
1420 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1424 // Insert the entry into the result pool, if we have one
1431 // Move the request data into the passed in buffer
1434 ASSERT( sizeof( AFSCommRequest) +
1435 pEntry->FileName.Length +
1436 pEntry->DataLength <= pIrpSp->Parameters.DeviceIoControl.OutputBufferLength);
1438 RtlCopyMemory( &pRequest->AuthGroup,
1442 pRequest->FileId = pEntry->FileId;
1444 pRequest->RequestType = pEntry->RequestType;
1446 pRequest->RequestIndex = pEntry->RequestIndex;
1448 pRequest->RequestFlags = pEntry->RequestFlags;
1450 pRequest->NameLength = pEntry->FileName.Length;
1452 pRequest->QueueCount = InterlockedDecrement( &pCommSrvc->QueueCount);
1454 if( pRequest->NameLength > 0)
1457 RtlCopyMemory( pRequest->Name,
1458 pEntry->FileName.Buffer,
1459 pRequest->NameLength);
1462 pRequest->DataOffset = 0;
1464 pRequest->DataLength = pEntry->DataLength;
1466 if( pRequest->DataLength > 0)
1469 pRequest->DataOffset = pEntry->FileName.Length;
1471 RtlCopyMemory( (void *)((char *)pRequest->Name + pRequest->DataOffset),
1473 pRequest->DataLength);
1476 pRequest->ResultBufferLength = 0;
1478 if( pEntry->ResultBufferLength != NULL)
1481 pRequest->ResultBufferLength = *(pEntry->ResultBufferLength);
1484 Irp->IoStatus.Information = sizeof( AFSCommRequest) +
1485 pEntry->FileName.Length +
1489 // If this is a synchronous request then move the request into the
1493 if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
1496 pEntry->fLink = NULL;
1497 pEntry->bLink = NULL;
1499 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1500 AFS_TRACE_LEVEL_VERBOSE,
1501 "AFSProcessIrpRequest Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
1502 &pCommSrvc->ResultPoolLock,
1503 PsGetCurrentThread());
1505 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1508 if( pCommSrvc->ResultPoolHead == NULL)
1511 pCommSrvc->ResultPoolHead = pEntry;
1516 pCommSrvc->ResultPoolTail->fLink = pEntry;
1518 pEntry->bLink = pCommSrvc->ResultPoolTail;
1521 pCommSrvc->ResultPoolTail = pEntry;
1523 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1529 // Free up the pool entry
1532 ExFreePool( pEntry);
1548 AFSProcessIrpResult( IN PIRP Irp)
1551 NTSTATUS ntStatus = STATUS_SUCCESS;
1552 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1553 AFSCommSrvcCB *pCommSrvc = NULL;
1554 AFSPoolEntry *pCurrentEntry = NULL;
1555 AFSCommResult *pResult = NULL;
1556 ULONG ulCopyLen = 0;
1561 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1564 // Get the request for the incoming result
1567 pResult = (AFSCommResult *)Irp->AssociatedIrp.SystemBuffer;
1569 if( pResult == NULL)
1572 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1576 // Go look for our entry
1579 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1580 AFS_TRACE_LEVEL_VERBOSE,
1581 "AFSProcessIrpResult Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
1582 &pCommSrvc->ResultPoolLock,
1583 PsGetCurrentThread());
1585 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1588 pCurrentEntry = pCommSrvc->ResultPoolHead;
1590 while( pCurrentEntry != NULL)
1593 if( pCurrentEntry->RequestIndex == pResult->RequestIndex)
1597 // Found the entry so remove it from the queue
1600 if( pCurrentEntry->bLink == NULL)
1604 // At the head of the list
1607 pCommSrvc->ResultPoolHead = pCurrentEntry->fLink;
1609 if( pCommSrvc->ResultPoolHead != NULL)
1612 pCommSrvc->ResultPoolHead->bLink = NULL;
1618 pCurrentEntry->bLink->fLink = pCurrentEntry->fLink;
1621 if( pCurrentEntry->fLink == NULL)
1624 pCommSrvc->ResultPoolTail = pCurrentEntry->bLink;
1626 if( pCommSrvc->ResultPoolTail != NULL)
1629 pCommSrvc->ResultPoolTail->fLink = NULL;
1635 pCurrentEntry->fLink->bLink = pCurrentEntry->bLink;
1641 pCurrentEntry = pCurrentEntry->fLink;
1644 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1646 if( pCurrentEntry == NULL)
1649 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1653 // OK, move in the result information
1656 pCurrentEntry->ResultStatus = pResult->ResultStatus;
1658 if( ( pCurrentEntry->ResultStatus == STATUS_SUCCESS ||
1659 pCurrentEntry->ResultStatus == STATUS_BUFFER_OVERFLOW) &&
1660 pCurrentEntry->ResultBufferLength != NULL &&
1661 pCurrentEntry->ResultBuffer != NULL)
1664 ASSERT( pResult->ResultBufferLength <= *(pCurrentEntry->ResultBufferLength));
1666 ulCopyLen = pResult->ResultBufferLength;
1668 if( ulCopyLen > *(pCurrentEntry->ResultBufferLength))
1670 ulCopyLen = *(pCurrentEntry->ResultBufferLength);
1673 *(pCurrentEntry->ResultBufferLength) = ulCopyLen;
1675 if( pResult->ResultBufferLength > 0)
1678 RtlCopyMemory( pCurrentEntry->ResultBuffer,
1679 pResult->ResultData,
1684 KeSetEvent( &pCurrentEntry->Event,
1690 if( !NT_SUCCESS( ntStatus))