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;
390 AFSCheckIoctlPermissions( IN ULONG ControlCode)
392 switch ( ControlCode)
395 // First the FS ioctls
398 case IOCTL_AFS_INITIALIZE_CONTROL_DEVICE:
401 // Only a System Service can run this (unless we are compiled
402 // for debug with the correct flags set.
405 if ( !AFSIsUser( SeExports->SeLocalSystemSid)
407 && !BooleanFlagOn( AFSDebugFlags, AFS_DBG_DISABLE_SYSTEM_SID_CHECK)
412 return STATUS_ACCESS_DENIED;
414 return STATUS_SUCCESS;
416 case IOCTL_AFS_INITIALIZE_REDIRECTOR_DEVICE:
417 case IOCTL_AFS_PROCESS_IRP_REQUEST:
418 case IOCTL_AFS_PROCESS_IRP_RESULT:
419 case IOCTL_AFS_SYSNAME_NOTIFICATION:
420 case IOCTL_AFS_SHUTDOWN:
423 // Once initialized, only the service can call these
426 if ( !AFSIsService())
429 return STATUS_ACCESS_DENIED;
431 return STATUS_SUCCESS;
433 case IOCTL_AFS_CONFIGURE_DEBUG_TRACE:
434 case IOCTL_AFS_GET_TRACE_BUFFER:
435 case IOCTL_AFS_FORCE_CRASH:
438 // Any admin can call these
441 if ( !AFSIsInGroup( SeExports->SeAliasAdminsSid))
444 return STATUS_ACCESS_DENIED;
446 return STATUS_SUCCESS;
448 case IOCTL_AFS_AUTHGROUP_CREATE_AND_SET:
449 case IOCTL_AFS_AUTHGROUP_QUERY:
450 case IOCTL_AFS_AUTHGROUP_SET:
451 case IOCTL_AFS_AUTHGROUP_RESET:
452 case IOCTL_AFS_AUTHGROUP_LOGON_CREATE:
453 case IOCTL_AFS_AUTHGROUP_SID_CREATE:
454 case IOCTL_AFS_AUTHGROUP_SID_QUERY:
457 // Anyone can call these.
460 return STATUS_SUCCESS;
463 // And now the LIB ioctls
466 case IOCTL_AFS_INITIALIZE_LIBRARY_DEVICE:
469 // Only the kernel can issue this
472 return STATUS_ACCESS_DENIED;
474 case IOCTL_AFS_STATUS_REQUEST:
475 case 0x140390: // IOCTL_LMR_DISABLE_LOCAL_BUFFERING
478 // Anyone can call these.
481 return STATUS_SUCCESS;
483 case IOCTL_AFS_ADD_CONNECTION:
484 case IOCTL_AFS_CANCEL_CONNECTION:
485 case IOCTL_AFS_GET_CONNECTION:
486 case IOCTL_AFS_LIST_CONNECTIONS:
487 case IOCTL_AFS_GET_CONNECTION_INFORMATION:
490 // These must only be called by the network provider but we
491 // don't have a method of enforcing that at the moment.
494 return STATUS_SUCCESS;
496 case IOCTL_AFS_SET_FILE_EXTENTS:
497 case IOCTL_AFS_RELEASE_FILE_EXTENTS:
498 case IOCTL_AFS_SET_FILE_EXTENT_FAILURE:
499 case IOCTL_AFS_INVALIDATE_CACHE:
500 case IOCTL_AFS_NETWORK_STATUS:
501 case IOCTL_AFS_VOLUME_STATUS:
504 // Again, service only
507 if ( !AFSIsService())
510 return STATUS_ACCESS_DENIED;
512 return STATUS_SUCCESS;
514 case IOCTL_AFS_GET_OBJECT_INFORMATION:
520 if ( !AFSIsInGroup( SeExports->SeAliasAdminsSid))
523 return STATUS_ACCESS_DENIED;
525 return STATUS_SUCCESS;
530 // NOTE that for security we police all known functions here
531 // and return STATUS_NOT_IMPLEMENTED. So new ioctls need to
532 // be added both here and either below or in
533 // ..\lib\AFSDevControl.cpp
536 return STATUS_NOT_IMPLEMENTED;
540 AFSProcessControlRequest( IN PIRP Irp)
543 NTSTATUS ntStatus = STATUS_SUCCESS;
544 PIO_STACK_LOCATION pIrpSp;
545 ULONG ulIoControlCode;
546 BOOLEAN bCompleteRequest = TRUE;
547 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
552 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
554 ulIoControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
556 ntStatus = AFSCheckIoctlPermissions( ulIoControlCode);
558 if ( !NT_SUCCESS( ntStatus))
560 try_return( ntStatus);
563 switch( ulIoControlCode)
566 case IOCTL_AFS_INITIALIZE_CONTROL_DEVICE:
569 // Go intialize the pool
571 ntStatus = AFSInitIrpPool();
573 if( !NT_SUCCESS( ntStatus))
584 // Tag this instance as the one to close the irp pool when it is closed
587 pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_CONTROL_INSTANCE);
589 AFSRegisterService();
594 case IOCTL_AFS_INITIALIZE_REDIRECTOR_DEVICE:
597 AFSRedirectorInitInfo *pRedirInitInfo = (AFSRedirectorInitInfo *)Irp->AssociatedIrp.SystemBuffer;
600 // Extract off the passed in information which contains the
601 // cache file parameters
604 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSRedirectorInitInfo) ||
605 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSRedirectorInitInfo, CacheFileName) +
606 pRedirInitInfo->CacheFileNameLength)
609 ntStatus = STATUS_INVALID_PARAMETER;
615 // Initialize the Redirector device
618 ntStatus = AFSInitializeRedirector( pRedirInitInfo);
620 if( !NT_SUCCESS( ntStatus))
627 // Stash away context so we know the instance used to initialize the redirector
630 pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_REDIRECTOR_INSTANCE);
635 case IOCTL_AFS_PROCESS_IRP_REQUEST:
638 ntStatus = AFSProcessIrpRequest( Irp);
643 case IOCTL_AFS_PROCESS_IRP_RESULT:
646 ntStatus = AFSProcessIrpResult( Irp);
651 case IOCTL_AFS_SYSNAME_NOTIFICATION:
654 AFSSysNameNotificationCB *pSysNameInfo = (AFSSysNameNotificationCB *)Irp->AssociatedIrp.SystemBuffer;
656 if( pSysNameInfo == NULL ||
657 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSSysNameNotificationCB))
660 ntStatus = STATUS_INVALID_PARAMETER;
665 ntStatus = AFSSetSysNameInformation( pSysNameInfo,
666 pIrpSp->Parameters.DeviceIoControl.InputBufferLength);
671 case IOCTL_AFS_CONFIGURE_DEBUG_TRACE:
674 AFSTraceConfigCB *pTraceInfo = (AFSTraceConfigCB *)Irp->AssociatedIrp.SystemBuffer;
676 if( pTraceInfo == NULL ||
677 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSTraceConfigCB))
680 ntStatus = STATUS_INVALID_PARAMETER;
685 ntStatus = AFSConfigureTrace( pTraceInfo);
690 case IOCTL_AFS_GET_TRACE_BUFFER:
693 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0)
696 ntStatus = STATUS_INVALID_PARAMETER;
701 ntStatus = AFSGetTraceBuffer( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
702 Irp->AssociatedIrp.SystemBuffer,
703 &Irp->IoStatus.Information);
708 case IOCTL_AFS_FORCE_CRASH:
713 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_FLAG_ENABLE_FORCE_CRASH))
716 KeBugCheck( (ULONG)-1);
723 #ifdef NOT_IMPLEMENTED
724 case IOCTL_AFS_LOAD_LIBRARY:
727 AFSLoadLibraryCB *pLoadLib = (AFSLoadLibraryCB *)Irp->AssociatedIrp.SystemBuffer;
728 UNICODE_STRING uniServicePath;
730 if( pLoadLib == NULL ||
731 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSLoadLibraryCB) ||
732 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSLoadLibraryCB, LibraryServicePath) +
733 pLoadLib->LibraryServicePathLength)
736 ntStatus = STATUS_INVALID_PARAMETER;
741 uniServicePath.Length = pLoadLib->LibraryServicePathLength;
742 uniServicePath.MaximumLength = uniServicePath.Length;
744 uniServicePath.Buffer = pLoadLib->LibraryServicePath;
746 if( uniServicePath.Length == 0)
749 ntStatus = STATUS_INVALID_PARAMETER;
754 ntStatus = AFSLoadLibrary( pLoadLib->Flags,
757 if( NT_SUCCESS( ntStatus))
761 // Intialize the library
764 ntStatus = AFSInitializeLibrary( NULL,
771 case IOCTL_AFS_UNLOAD_LIBRARY:
775 // Try to unload the library we currently have in place
778 ntStatus = AFSUnloadLibrary( FALSE);
784 case IOCTL_AFS_SHUTDOWN:
787 ntStatus = AFSShutdownRedirector();
792 case IOCTL_AFS_AUTHGROUP_CREATE_AND_SET:
795 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
797 if( pAuthGroupRequestCB == NULL ||
798 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
801 ntStatus = STATUS_INVALID_PARAMETER;
806 ntStatus = AFSCreateSetProcessAuthGroup( pAuthGroupRequestCB);
811 case IOCTL_AFS_AUTHGROUP_QUERY:
814 ntStatus = AFSQueryProcessAuthGroupList( ( GUID *)Irp->AssociatedIrp.SystemBuffer,
815 pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
816 &Irp->IoStatus.Information);
821 case IOCTL_AFS_AUTHGROUP_SET:
824 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
826 if( pAuthGroupRequestCB == NULL ||
827 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
830 ntStatus = STATUS_INVALID_PARAMETER;
835 ntStatus = AFSSetActiveProcessAuthGroup( pAuthGroupRequestCB);
840 case IOCTL_AFS_AUTHGROUP_RESET:
843 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
845 if( pAuthGroupRequestCB == NULL ||
846 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
849 ntStatus = STATUS_INVALID_PARAMETER;
854 ntStatus = AFSResetActiveProcessAuthGroup( pAuthGroupRequestCB);
859 case IOCTL_AFS_AUTHGROUP_LOGON_CREATE:
860 case IOCTL_AFS_AUTHGROUP_SID_CREATE:
863 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
865 if( pAuthGroupRequestCB != NULL &&
866 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
869 ntStatus = STATUS_INVALID_PARAMETER;
874 ntStatus = AFSCreateAuthGroupForSIDorLogonSession( pAuthGroupRequestCB,
875 ulIoControlCode == IOCTL_AFS_AUTHGROUP_LOGON_CREATE);
880 case IOCTL_AFS_AUTHGROUP_SID_QUERY:
883 AFSAuthGroupRequestCB *pAuthGroupRequestCB = NULL;
885 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( GUID))
887 ntStatus = STATUS_INVALID_PARAMETER;
891 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof( AFSAuthGroupRequestCB))
893 pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
896 ntStatus = AFSQueryAuthGroup( pAuthGroupRequestCB,
897 (GUID *)Irp->AssociatedIrp.SystemBuffer,
898 &Irp->IoStatus.Information);
907 // Check the state of the library
910 ntStatus = AFSCheckLibraryState( Irp);
912 if( !NT_SUCCESS( ntStatus) ||
913 ntStatus == STATUS_PENDING)
916 if( ntStatus == STATUS_PENDING)
918 bCompleteRequest = FALSE;
924 bCompleteRequest = FALSE;
926 IoSkipCurrentIrpStackLocation( Irp);
928 ntStatus = IoCallDriver( pDevExt->Specific.Control.LibraryDeviceObject,
932 // Indicate the library is done with the request
935 AFSClearLibraryRequest();
942 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
945 ntStatus = STATUS_UNSUCCESSFUL;
947 AFSDumpTraceFilesFnc();
952 if( bCompleteRequest)
955 Irp->IoStatus.Status = ntStatus;
957 AFSCompleteRequest( Irp,
968 NTSTATUS ntStatus = STATUS_SUCCESS;
969 AFSCommSrvcCB *pCommSrvc = NULL;
970 BOOLEAN bReleasePools = FALSE;
971 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
976 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
979 // Whenever we change state we must grab both pool locks. On the checking of the state
980 // within the processing routines for these respective pools, we only grab one lock to
981 // minimize serialization. The ordering is always the Irp pool then the result pool
982 // locks. We also do this in the tear down of the pool
985 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
986 AFS_TRACE_LEVEL_VERBOSE,
987 "AFSInitIrpPool Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
988 &pCommSrvc->IrpPoolLock,
989 PsGetCurrentThread());
991 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
994 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
995 AFS_TRACE_LEVEL_VERBOSE,
996 "AFSInitIrpPool Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
997 &pCommSrvc->ResultPoolLock,
998 PsGetCurrentThread());
1000 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1003 bReleasePools = TRUE;
1006 // The pool can be either ACTIVE or INACTIVE. If the pool state is INACTIVE and we
1007 // are receiving the INIT request, then activate it. If the pool is ACTIVE, then we
1008 // shouldn't be getting this request ...
1011 if( pCommSrvc->IrpPoolControlFlag == POOL_ACTIVE)
1015 // We have already been activated so just fail this request
1018 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1020 else if( pCommSrvc->IrpPoolControlFlag == POOL_INACTIVE)
1024 // The pool is currently INACTIVE so start it up and ready it to
1025 // receive irp requests
1028 pCommSrvc->IrpPoolControlFlag = POOL_ACTIVE;
1030 pDevExt->Specific.Control.ServiceProcess = (PKPROCESS)PsGetCurrentProcess();
1032 try_return( ntStatus = STATUS_SUCCESS);
1038 // The pool is in some mixed state, fail the request.
1041 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1049 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1051 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1062 AFSPoolEntry *pEntry = NULL, *pNextEntry = NULL;
1063 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1064 AFSCommSrvcCB *pCommSrvc = (AFSCommSrvcCB *)&pDevExt->Specific.Control.CommServiceCB;
1070 // When we change the state, grab both pool locks exclusive. The order is always the
1071 // Irp pool then the result pool lock
1074 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1075 AFS_TRACE_LEVEL_VERBOSE,
1076 "AFSCleanupIrpPool Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
1077 &pCommSrvc->IrpPoolLock,
1078 PsGetCurrentThread());
1080 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1083 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1084 AFS_TRACE_LEVEL_VERBOSE,
1085 "AFSCleanupIrpPool Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
1086 &pCommSrvc->ResultPoolLock,
1087 PsGetCurrentThread());
1089 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1093 // Indicate we are pending stop
1096 pCommSrvc->IrpPoolControlFlag = POOL_INACTIVE;
1099 // Set the event to release any waiting workers
1100 // (everyone waits on IrpPoolHasReleaseEntries)
1103 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1108 // Go through the pool entries and free up the structures.
1111 pEntry = pCommSrvc->RequestPoolHead;
1113 while( pEntry != NULL)
1116 pNextEntry = pEntry->fLink;
1118 if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
1122 // Here we need to complete the irp, cancelled, and delete the data block
1125 pEntry->ResultStatus = (ULONG) STATUS_CANCELLED;
1127 KeSetEvent( &pEntry->Event,
1134 ExFreePool( pEntry);
1137 pEntry = pNextEntry;
1141 // Cleanup the control structure for the request pool
1144 pCommSrvc->RequestPoolHead = NULL;
1146 pCommSrvc->RequestPoolTail = NULL;
1148 pCommSrvc->IrpPoolRequestIndex = 1;
1150 KeClearEvent( &pCommSrvc->IrpPoolHasEntries);
1152 KeClearEvent( &pCommSrvc->IrpPoolHasReleaseEntries);
1155 // Release the irp pool lock.
1158 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1161 // Go through the result pool entries and free up the structures.
1164 pEntry = pCommSrvc->ResultPoolHead;
1166 while( pEntry != NULL)
1169 pNextEntry = pEntry->fLink;
1171 pEntry->ResultStatus = (ULONG) STATUS_CANCELLED;
1174 // Here we will set the event of the requestor and let the blocked thread
1175 // free the data block
1178 KeSetEvent( &pEntry->Event,
1183 // Go onto the next entry
1186 pEntry = pNextEntry;
1190 // Cleanup the control structure for the result pool
1193 pCommSrvc->ResultPoolHead = NULL;
1195 pCommSrvc->ResultPoolTail = NULL;
1198 // Release the result pool lock.
1201 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1209 AFSInsertRequest( IN AFSCommSrvcCB *CommSrvc,
1210 IN AFSPoolEntry *Entry)
1213 NTSTATUS ntStatus = STATUS_SUCCESS;
1218 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1219 AFS_TRACE_LEVEL_VERBOSE,
1220 "AFSInsertRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
1221 &CommSrvc->IrpPoolLock,
1222 PsGetCurrentThread());
1224 AFSAcquireExcl( &CommSrvc->IrpPoolLock,
1227 if( CommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1230 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1233 if( CommSrvc->RequestPoolHead == NULL)
1236 CommSrvc->RequestPoolHead = Entry;
1241 CommSrvc->RequestPoolTail->fLink = Entry;
1243 Entry->bLink = CommSrvc->RequestPoolTail;
1246 CommSrvc->RequestPoolTail = Entry;
1248 if( Entry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1251 KeSetEvent( &CommSrvc->IrpPoolHasReleaseEntries,
1258 KeSetEvent( &CommSrvc->IrpPoolHasEntries,
1263 InterlockedIncrement( &CommSrvc->QueueCount);
1267 AFSReleaseResource( &CommSrvc->IrpPoolLock);
1274 AFSProcessIrpRequest( IN PIRP Irp)
1277 NTSTATUS ntStatus = STATUS_SUCCESS;
1278 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1279 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1280 AFSCommSrvcCB *pCommSrvc = NULL;
1281 AFSPoolEntry *pEntry = NULL, *pPrevEntry = NULL;
1282 AFSCommRequest *pRequest = NULL;
1283 BOOLEAN bReleaseRequestThread = FALSE;
1289 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1291 pRequest = (AFSCommRequest *)Irp->AssociatedIrp.SystemBuffer;
1293 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1294 AFS_TRACE_LEVEL_VERBOSE,
1295 "AFSProcessIrpRequest Acquiring IrpPoolLock lock %08lX EXCL %08lX\n",
1296 &pCommSrvc->IrpPoolLock,
1297 PsGetCurrentThread());
1299 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1302 if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1305 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1307 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1310 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1313 // Is this a dedicated flush thread?
1316 if( BooleanFlagOn( pRequest->RequestFlags, AFS_REQUEST_RELEASE_THREAD))
1319 bReleaseRequestThread = TRUE;
1323 // Populate the objects array for the non release only threads
1324 // Release only workers can only process release extent events
1325 // whereas normal workers can process any kind of event.
1326 // Release only workers are present to ensure there cannot be
1327 // a deadlock due to all extents held by the redirector and
1328 // there not be a worker available to release them.
1331 Objects[0] = &pCommSrvc->IrpPoolHasReleaseEntries;
1333 Objects[1] = &pCommSrvc->IrpPoolHasEntries;
1336 // Wait on the 'have items' event until we can retrieve an item
1342 if( bReleaseRequestThread)
1345 ntStatus = KeWaitForSingleObject( &pCommSrvc->IrpPoolHasReleaseEntries,
1351 if( ntStatus != STATUS_SUCCESS)
1354 ntStatus = STATUS_DEVICE_NOT_READY;
1363 ntStatus = KeWaitForMultipleObjects( 2,
1372 if( ntStatus != STATUS_WAIT_0 &&
1373 ntStatus != STATUS_WAIT_1)
1376 ntStatus = STATUS_DEVICE_NOT_READY;
1383 // Grab the lock on the request pool
1386 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1387 AFS_TRACE_LEVEL_VERBOSE,
1388 "AFSProcessIrpRequest Acquiring IrpPoolLock (WAIT) lock %08lX EXCL %08lX\n",
1389 &pCommSrvc->IrpPoolLock,
1390 PsGetCurrentThread());
1392 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1395 if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1398 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1401 // Wake up the next worker since this is a SynchronizationEvent
1404 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1408 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1412 // If this is a dedicated flush thread only look for a flush request in the queue
1415 if( bReleaseRequestThread)
1418 pEntry = pCommSrvc->RequestPoolHead;
1422 while( pEntry != NULL)
1425 if( pEntry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1428 if( pPrevEntry == NULL)
1431 pCommSrvc->RequestPoolHead = pEntry->fLink;
1433 if( pCommSrvc->RequestPoolHead == NULL)
1436 pCommSrvc->RequestPoolTail = NULL;
1442 pPrevEntry->fLink = pEntry->fLink;
1444 if( pPrevEntry->fLink == NULL)
1447 pCommSrvc->RequestPoolTail = pPrevEntry;
1454 pPrevEntry = pEntry;
1456 pEntry = pEntry->fLink;
1463 // There might be another release entry pending
1466 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1472 // And release the request pool lock
1475 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1480 pEntry = pCommSrvc->RequestPoolHead;
1485 pCommSrvc->RequestPoolHead = pEntry->fLink;
1487 pEntry->bLink = NULL;
1489 if( pCommSrvc->RequestPoolHead == NULL)
1492 pCommSrvc->RequestPoolTail = NULL;
1497 KeSetEvent( &pCommSrvc->IrpPoolHasEntries,
1504 // And release the request pool lock
1507 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1511 // Insert the entry into the result pool, if we have one
1518 // Move the request data into the passed in buffer
1521 ASSERT( sizeof( AFSCommRequest) +
1522 pEntry->FileName.Length +
1523 pEntry->DataLength <= pIrpSp->Parameters.DeviceIoControl.OutputBufferLength);
1525 RtlCopyMemory( &pRequest->AuthGroup,
1529 pRequest->FileId = pEntry->FileId;
1531 pRequest->RequestType = pEntry->RequestType;
1533 pRequest->RequestIndex = pEntry->RequestIndex;
1535 pRequest->RequestFlags = pEntry->RequestFlags;
1537 pRequest->NameLength = pEntry->FileName.Length;
1539 pRequest->QueueCount = InterlockedDecrement( &pCommSrvc->QueueCount);
1541 if( pRequest->NameLength > 0)
1544 RtlCopyMemory( pRequest->Name,
1545 pEntry->FileName.Buffer,
1546 pRequest->NameLength);
1549 pRequest->DataOffset = 0;
1551 pRequest->DataLength = pEntry->DataLength;
1553 if( pRequest->DataLength > 0)
1556 pRequest->DataOffset = pEntry->FileName.Length;
1558 RtlCopyMemory( (void *)((char *)pRequest->Name + pRequest->DataOffset),
1560 pRequest->DataLength);
1563 pRequest->ResultBufferLength = 0;
1565 if( pEntry->ResultBufferLength != NULL)
1568 pRequest->ResultBufferLength = *(pEntry->ResultBufferLength);
1571 Irp->IoStatus.Information = sizeof( AFSCommRequest) +
1572 pEntry->FileName.Length +
1576 // If this is a synchronous request then move the request into the
1580 if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
1583 pEntry->fLink = NULL;
1584 pEntry->bLink = NULL;
1586 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1587 AFS_TRACE_LEVEL_VERBOSE,
1588 "AFSProcessIrpRequest Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
1589 &pCommSrvc->ResultPoolLock,
1590 PsGetCurrentThread());
1592 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1595 if( pCommSrvc->ResultPoolHead == NULL)
1598 pCommSrvc->ResultPoolHead = pEntry;
1603 pCommSrvc->ResultPoolTail->fLink = pEntry;
1605 pEntry->bLink = pCommSrvc->ResultPoolTail;
1608 pCommSrvc->ResultPoolTail = pEntry;
1610 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1616 // Free up the pool entry
1619 ExFreePool( pEntry);
1635 AFSProcessIrpResult( IN PIRP Irp)
1638 NTSTATUS ntStatus = STATUS_SUCCESS;
1639 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1640 AFSCommSrvcCB *pCommSrvc = NULL;
1641 AFSPoolEntry *pCurrentEntry = NULL;
1642 AFSCommResult *pResult = NULL;
1643 ULONG ulCopyLen = 0;
1648 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1651 // Get the request for the incoming result
1654 pResult = (AFSCommResult *)Irp->AssociatedIrp.SystemBuffer;
1656 if( pResult == NULL)
1659 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1663 // Go look for our entry
1666 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1667 AFS_TRACE_LEVEL_VERBOSE,
1668 "AFSProcessIrpResult Acquiring ResultPoolLock lock %08lX EXCL %08lX\n",
1669 &pCommSrvc->ResultPoolLock,
1670 PsGetCurrentThread());
1672 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1675 pCurrentEntry = pCommSrvc->ResultPoolHead;
1677 while( pCurrentEntry != NULL)
1680 if( pCurrentEntry->RequestIndex == pResult->RequestIndex)
1684 // Found the entry so remove it from the queue
1687 if( pCurrentEntry->bLink == NULL)
1691 // At the head of the list
1694 pCommSrvc->ResultPoolHead = pCurrentEntry->fLink;
1696 if( pCommSrvc->ResultPoolHead != NULL)
1699 pCommSrvc->ResultPoolHead->bLink = NULL;
1705 pCurrentEntry->bLink->fLink = pCurrentEntry->fLink;
1708 if( pCurrentEntry->fLink == NULL)
1711 pCommSrvc->ResultPoolTail = pCurrentEntry->bLink;
1713 if( pCommSrvc->ResultPoolTail != NULL)
1716 pCommSrvc->ResultPoolTail->fLink = NULL;
1722 pCurrentEntry->fLink->bLink = pCurrentEntry->bLink;
1728 pCurrentEntry = pCurrentEntry->fLink;
1731 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1733 if( pCurrentEntry == NULL)
1736 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1740 // OK, move in the result information
1743 pCurrentEntry->ResultStatus = pResult->ResultStatus;
1745 if( ( pCurrentEntry->ResultStatus == STATUS_SUCCESS ||
1746 pCurrentEntry->ResultStatus == STATUS_BUFFER_OVERFLOW) &&
1747 pCurrentEntry->ResultBufferLength != NULL &&
1748 pCurrentEntry->ResultBuffer != NULL)
1751 ASSERT( pResult->ResultBufferLength <= *(pCurrentEntry->ResultBufferLength));
1753 ulCopyLen = pResult->ResultBufferLength;
1755 if( ulCopyLen > *(pCurrentEntry->ResultBufferLength))
1757 ulCopyLen = *(pCurrentEntry->ResultBufferLength);
1760 *(pCurrentEntry->ResultBufferLength) = ulCopyLen;
1762 if( pResult->ResultBufferLength > 0)
1765 RtlCopyMemory( pCurrentEntry->ResultBuffer,
1766 pResult->ResultData,
1771 KeSetEvent( &pCurrentEntry->Event,
1777 if( !NT_SUCCESS( ntStatus))