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,
67 AFSProcessRequest( IN ULONG RequestType,
68 IN ULONG RequestFlags,
70 IN PUNICODE_STRING FileName,
76 IN OUT void *ResultBuffer,
77 IN OUT PULONG ResultBufferLength)
80 NTSTATUS ntStatus = STATUS_SUCCESS;
81 AFSPoolEntry stPoolEntry, *pPoolEntry = NULL;
82 AFSCommSrvcCB *pCommSrvc = NULL;
83 BOOLEAN bReleasePool = FALSE;
84 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
85 AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
86 BOOLEAN bWait = BooleanFlagOn( RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS);
87 ULONG ulPoolEntryLength = 0;
88 BOOLEAN bDecrementCount = FALSE;
93 if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
95 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
98 if( InterlockedIncrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 1)
100 KeClearEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent);
103 bDecrementCount = TRUE;
105 pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
108 // Grab the pool resource and check the state
111 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
112 AFS_TRACE_LEVEL_VERBOSE,
113 "AFSProcessRequest Acquiring IrpPoolLock lock %p EXCL %08lX\n",
114 &pCommSrvc->IrpPoolLock,
115 PsGetCurrentThread()));
117 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
122 if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
126 // Pool not running so bail.
129 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
133 // If this is an async request we need to allocate a pool entry for the request
136 pPoolEntry = &stPoolEntry;
141 ASSERT( ResultBuffer == NULL);
143 ulPoolEntryLength = sizeof( AFSPoolEntry) + QuadAlign( DataLength);
145 if( FileName != NULL)
148 ulPoolEntryLength += FileName->Length;
151 pPoolEntry = (AFSPoolEntry *)AFSExAllocatePoolWithTag( NonPagedPool,
155 if( pPoolEntry == NULL)
158 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
161 RtlZeroMemory( pPoolEntry,
164 pPoolEntry->Data = (void *)((char *)pPoolEntry + sizeof( AFSPoolEntry));
166 pPoolEntry->FileName.Buffer = (WCHAR *)((char *)pPoolEntry->Data + DataLength);
171 RtlZeroMemory( pPoolEntry,
172 sizeof( AFSPoolEntry));
174 KeInitializeEvent( &pPoolEntry->Event,
179 pPoolEntry->RequestType = RequestType;
181 pPoolEntry->RequestIndex = pCommSrvc->IrpPoolRequestIndex++;
183 pPoolEntry->RequestFlags = RequestFlags;
185 pPoolEntry->ResultBufferLength = 0;
190 pPoolEntry->FileId = *FileId;
193 pPoolEntry->FileName.Length = 0;
195 if( FileName != NULL)
201 pPoolEntry->FileName = *FileName;
206 pPoolEntry->FileName.Length = FileName->Length;
208 pPoolEntry->FileName.MaximumLength = pPoolEntry->FileName.Length;
210 RtlCopyMemory( pPoolEntry->FileName.Buffer,
212 pPoolEntry->FileName.Length);
217 // Move in the data if there is some
220 pPoolEntry->DataLength = DataLength;
229 pPoolEntry->Data = Data;
234 RtlCopyMemory( pPoolEntry->Data,
240 pPoolEntry->ResultBuffer = ResultBuffer;
242 pPoolEntry->ResultBufferLength = ResultBufferLength;
245 // Store off the auth group
248 if( AuthGroup == NULL)
250 AFSRetrieveAuthGroup( (ULONGLONG)PsGetCurrentProcessId(),
251 (ULONGLONG)PsGetCurrentThreadId(),
252 &pPoolEntry->AuthGroup);
256 RtlCopyMemory( &pPoolEntry->AuthGroup,
261 if( AFSIsLocalSystemAuthGroup( &pPoolEntry->AuthGroup))
263 SetFlag( pPoolEntry->RequestFlags, AFS_REQUEST_LOCAL_SYSTEM_PAG);
266 if( AFSIsNoPAGAuthGroup( &pPoolEntry->AuthGroup))
270 "AFSProcessRequest NoPAG Auth Group %08lX\n",
271 PsGetCurrentThread()));
275 // Indicate the type of process
280 if( !AFSIs64BitProcess( (ULONGLONG)PsGetCurrentProcessId()))
282 SetFlag( pPoolEntry->RequestFlags, AFS_REQUEST_FLAG_WOW64);
288 // Insert the entry into the request pool
291 ntStatus = AFSInsertRequest( pCommSrvc,
294 if( !NT_SUCCESS( ntStatus))
300 ExFreePool( pPoolEntry);
303 try_return( ntStatus);
307 // Drop the lock on the pool prior to waiting
310 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
312 bReleasePool = FALSE;
315 // Wait for the result if this is NOT an asynchronous request
322 // Wait for the result of the request. We specify no timeout ...
325 ntStatus = KeWaitForSingleObject( &pPoolEntry->Event,
332 // Process the result of the request
335 if( ntStatus == STATUS_SUCCESS)
338 ntStatus = pPoolEntry->ResultStatus;
343 ntStatus = STATUS_DEVICE_NOT_READY;
352 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
355 if( bDecrementCount &&
356 InterlockedDecrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 0)
358 KeSetEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent,
363 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
366 AFSDumpTraceFilesFnc();
371 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
374 if( bDecrementCount &&
375 InterlockedDecrement( &pControlDevExt->Specific.Control.OutstandingServiceRequestCount) == 0)
377 KeSetEvent( &pControlDevExt->Specific.Control.OutstandingServiceRequestEvent,
382 if ( ntStatus == STATUS_SUCCESS)
385 ntStatus = STATUS_UNSUCCESSFUL;
394 AFSCheckIoctlPermissions( IN ULONG ControlCode)
396 switch ( ControlCode)
399 // First the FS ioctls
402 case IOCTL_AFS_INITIALIZE_CONTROL_DEVICE:
405 // Only a System Service can run this (unless we are compiled
406 // for debug with the correct flags set.
409 if ( !AFSIsUser( SeExports->SeLocalSystemSid)
411 && !BooleanFlagOn( AFSDebugFlags, AFS_DBG_DISABLE_SYSTEM_SID_CHECK)
416 return STATUS_ACCESS_DENIED;
418 return STATUS_SUCCESS;
420 case IOCTL_AFS_INITIALIZE_REDIRECTOR_DEVICE:
421 case IOCTL_AFS_PROCESS_IRP_REQUEST:
422 case IOCTL_AFS_PROCESS_IRP_RESULT:
423 case IOCTL_AFS_SYSNAME_NOTIFICATION:
424 case IOCTL_AFS_SHUTDOWN:
427 // Once initialized, only the service can call these
430 if ( !AFSIsService())
433 return STATUS_ACCESS_DENIED;
435 return STATUS_SUCCESS;
437 case IOCTL_AFS_CONFIGURE_DEBUG_TRACE:
438 case IOCTL_AFS_GET_TRACE_BUFFER:
439 case IOCTL_AFS_FORCE_CRASH:
442 // Any admin can call these
445 if ( !AFSIsInGroup( SeExports->SeAliasAdminsSid))
448 return STATUS_ACCESS_DENIED;
450 return STATUS_SUCCESS;
452 case IOCTL_AFS_AUTHGROUP_CREATE_AND_SET:
453 case IOCTL_AFS_AUTHGROUP_QUERY:
454 case IOCTL_AFS_AUTHGROUP_SET:
455 case IOCTL_AFS_AUTHGROUP_RESET:
456 case IOCTL_AFS_AUTHGROUP_LOGON_CREATE:
457 case IOCTL_AFS_AUTHGROUP_SID_CREATE:
458 case IOCTL_AFS_AUTHGROUP_SID_QUERY:
461 // Anyone can call these.
464 return STATUS_SUCCESS;
467 // And now the LIB ioctls
470 case IOCTL_AFS_INITIALIZE_LIBRARY_DEVICE:
471 case IOCTL_AFS_CONFIG_LIBRARY_TRACE:
474 // Only the kernel can issue this
477 return STATUS_ACCESS_DENIED;
479 case IOCTL_AFS_STATUS_REQUEST:
480 case 0x140390: // IOCTL_LMR_DISABLE_LOCAL_BUFFERING
483 // Anyone can call these.
486 return STATUS_SUCCESS;
488 case IOCTL_AFS_ADD_CONNECTION:
489 case IOCTL_AFS_CANCEL_CONNECTION:
490 case IOCTL_AFS_GET_CONNECTION:
491 case IOCTL_AFS_LIST_CONNECTIONS:
492 case IOCTL_AFS_GET_CONNECTION_INFORMATION:
495 // These must only be called by the network provider but we
496 // don't have a method of enforcing that at the moment.
499 return STATUS_SUCCESS;
501 case IOCTL_AFS_SET_FILE_EXTENTS:
502 case IOCTL_AFS_RELEASE_FILE_EXTENTS:
503 case IOCTL_AFS_SET_FILE_EXTENT_FAILURE:
504 case IOCTL_AFS_INVALIDATE_CACHE:
505 case IOCTL_AFS_NETWORK_STATUS:
506 case IOCTL_AFS_VOLUME_STATUS:
509 // Again, service only
512 if ( !AFSIsService())
515 return STATUS_ACCESS_DENIED;
517 return STATUS_SUCCESS;
519 case IOCTL_AFS_GET_OBJECT_INFORMATION:
525 if ( !AFSIsInGroup( SeExports->SeAliasAdminsSid))
528 return STATUS_ACCESS_DENIED;
530 return STATUS_SUCCESS;
535 // NOTE that for security we police all known functions here
536 // and return STATUS_NOT_IMPLEMENTED. So new ioctls need to
537 // be added both here and either below or in
538 // ..\lib\AFSDevControl.cpp
541 return STATUS_NOT_IMPLEMENTED;
545 AFSProcessControlRequest( IN PIRP Irp)
548 NTSTATUS ntStatus = STATUS_SUCCESS;
549 PIO_STACK_LOCATION pIrpSp;
550 ULONG ulIoControlCode;
551 BOOLEAN bCompleteRequest = TRUE;
552 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
557 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
559 ulIoControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
561 ntStatus = AFSCheckIoctlPermissions( ulIoControlCode);
563 if ( !NT_SUCCESS( ntStatus))
565 try_return( ntStatus);
568 switch( ulIoControlCode)
571 case IOCTL_AFS_INITIALIZE_CONTROL_DEVICE:
574 // Go intialize the pool
576 ntStatus = AFSInitIrpPool();
578 if( !NT_SUCCESS( ntStatus))
589 // Tag this instance as the one to close the irp pool when it is closed
592 pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_CONTROL_INSTANCE);
594 AFSRegisterService();
599 case IOCTL_AFS_INITIALIZE_REDIRECTOR_DEVICE:
602 AFSRedirectorInitInfo *pRedirInitInfo = (AFSRedirectorInitInfo *)Irp->AssociatedIrp.SystemBuffer;
605 // Extract off the passed in information which contains the
606 // cache file parameters
609 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSRedirectorInitInfo) ||
610 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSRedirectorInitInfo, CacheFileName) +
611 pRedirInitInfo->CacheFileNameLength)
614 ntStatus = STATUS_INVALID_PARAMETER;
620 // Initialize the Redirector device
623 ntStatus = AFSInitializeRedirector( pRedirInitInfo);
625 if( !NT_SUCCESS( ntStatus))
632 // Stash away context so we know the instance used to initialize the redirector
635 pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_REDIRECTOR_INSTANCE);
640 case IOCTL_AFS_PROCESS_IRP_REQUEST:
643 ntStatus = AFSProcessIrpRequest( Irp);
648 case IOCTL_AFS_PROCESS_IRP_RESULT:
651 ntStatus = AFSProcessIrpResult( Irp);
656 case IOCTL_AFS_SYSNAME_NOTIFICATION:
659 AFSSysNameNotificationCB *pSysNameInfo = (AFSSysNameNotificationCB *)Irp->AssociatedIrp.SystemBuffer;
661 if( pSysNameInfo == NULL ||
662 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSSysNameNotificationCB))
665 ntStatus = STATUS_INVALID_PARAMETER;
670 ntStatus = AFSSetSysNameInformation( pSysNameInfo,
671 pIrpSp->Parameters.DeviceIoControl.InputBufferLength);
676 case IOCTL_AFS_CONFIGURE_DEBUG_TRACE:
679 AFSTraceConfigCB *pTraceInfo = (AFSTraceConfigCB *)Irp->AssociatedIrp.SystemBuffer;
681 if( pTraceInfo == NULL ||
682 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSTraceConfigCB))
685 ntStatus = STATUS_INVALID_PARAMETER;
690 ntStatus = AFSConfigureTrace( pTraceInfo);
695 case IOCTL_AFS_GET_TRACE_BUFFER:
698 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0)
701 ntStatus = STATUS_INVALID_PARAMETER;
706 ntStatus = AFSGetTraceBuffer( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
707 Irp->AssociatedIrp.SystemBuffer,
708 &Irp->IoStatus.Information);
713 case IOCTL_AFS_FORCE_CRASH:
718 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_FLAG_ENABLE_FORCE_CRASH))
721 KeBugCheck( (ULONG)-1);
728 #ifdef NOT_IMPLEMENTED
729 case IOCTL_AFS_LOAD_LIBRARY:
732 AFSLoadLibraryCB *pLoadLib = (AFSLoadLibraryCB *)Irp->AssociatedIrp.SystemBuffer;
733 UNICODE_STRING uniServicePath;
735 if( pLoadLib == NULL ||
736 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSLoadLibraryCB) ||
737 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSLoadLibraryCB, LibraryServicePath) +
738 pLoadLib->LibraryServicePathLength)
741 ntStatus = STATUS_INVALID_PARAMETER;
746 uniServicePath.Length = pLoadLib->LibraryServicePathLength;
747 uniServicePath.MaximumLength = uniServicePath.Length;
749 uniServicePath.Buffer = pLoadLib->LibraryServicePath;
751 if( uniServicePath.Length == 0)
754 ntStatus = STATUS_INVALID_PARAMETER;
759 ntStatus = AFSLoadLibrary( pLoadLib->Flags,
762 if( NT_SUCCESS( ntStatus))
766 // Intialize the library
769 ntStatus = AFSInitializeLibrary( NULL,
776 case IOCTL_AFS_UNLOAD_LIBRARY:
780 // Try to unload the library we currently have in place
783 ntStatus = AFSUnloadLibrary( FALSE);
789 case IOCTL_AFS_SHUTDOWN:
792 ntStatus = AFSShutdownRedirector();
797 case IOCTL_AFS_AUTHGROUP_CREATE_AND_SET:
800 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
802 if( pAuthGroupRequestCB == NULL ||
803 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
806 ntStatus = STATUS_INVALID_PARAMETER;
811 ntStatus = AFSCreateSetProcessAuthGroup( pAuthGroupRequestCB);
816 case IOCTL_AFS_AUTHGROUP_QUERY:
819 ntStatus = AFSQueryProcessAuthGroupList( ( GUID *)Irp->AssociatedIrp.SystemBuffer,
820 pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
821 &Irp->IoStatus.Information);
826 case IOCTL_AFS_AUTHGROUP_SET:
829 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
831 if( pAuthGroupRequestCB == NULL ||
832 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
835 ntStatus = STATUS_INVALID_PARAMETER;
840 ntStatus = AFSSetActiveProcessAuthGroup( pAuthGroupRequestCB);
845 case IOCTL_AFS_AUTHGROUP_RESET:
848 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
850 if( pAuthGroupRequestCB == NULL ||
851 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
854 ntStatus = STATUS_INVALID_PARAMETER;
859 ntStatus = AFSResetActiveProcessAuthGroup( pAuthGroupRequestCB);
864 case IOCTL_AFS_AUTHGROUP_LOGON_CREATE:
865 case IOCTL_AFS_AUTHGROUP_SID_CREATE:
868 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
870 if( pAuthGroupRequestCB != NULL &&
871 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
874 ntStatus = STATUS_INVALID_PARAMETER;
879 ntStatus = AFSCreateAuthGroupForSIDorLogonSession( pAuthGroupRequestCB,
880 ulIoControlCode == IOCTL_AFS_AUTHGROUP_LOGON_CREATE);
885 case IOCTL_AFS_AUTHGROUP_SID_QUERY:
888 AFSAuthGroupRequestCB *pAuthGroupRequestCB = NULL;
890 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( GUID))
892 ntStatus = STATUS_INVALID_PARAMETER;
896 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof( AFSAuthGroupRequestCB))
898 pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
901 ntStatus = AFSQueryAuthGroup( pAuthGroupRequestCB,
902 (GUID *)Irp->AssociatedIrp.SystemBuffer,
903 &Irp->IoStatus.Information);
912 // Check the state of the library
915 ntStatus = AFSCheckLibraryState( Irp);
917 if( !NT_SUCCESS( ntStatus) ||
918 ntStatus == STATUS_PENDING)
921 if( ntStatus == STATUS_PENDING)
923 bCompleteRequest = FALSE;
929 bCompleteRequest = FALSE;
931 IoSkipCurrentIrpStackLocation( Irp);
933 ntStatus = IoCallDriver( pDevExt->Specific.Control.LibraryDeviceObject,
937 // Indicate the library is done with the request
940 AFSClearLibraryRequest();
947 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
950 ntStatus = STATUS_UNSUCCESSFUL;
952 AFSDumpTraceFilesFnc();
957 if( bCompleteRequest)
960 Irp->IoStatus.Status = ntStatus;
962 AFSCompleteRequest( Irp,
973 NTSTATUS ntStatus = STATUS_SUCCESS;
974 AFSCommSrvcCB *pCommSrvc = NULL;
975 BOOLEAN bReleasePools = FALSE;
976 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
981 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
984 // Whenever we change state we must grab both pool locks. On the checking of the state
985 // within the processing routines for these respective pools, we only grab one lock to
986 // minimize serialization. The ordering is always the Irp pool then the result pool
987 // locks. We also do this in the tear down of the pool
990 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
991 AFS_TRACE_LEVEL_VERBOSE,
992 "AFSInitIrpPool Acquiring IrpPoolLock lock %p EXCL %08lX\n",
993 &pCommSrvc->IrpPoolLock,
994 PsGetCurrentThread()));
996 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
999 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1000 AFS_TRACE_LEVEL_VERBOSE,
1001 "AFSInitIrpPool Acquiring ResultPoolLock lock %p EXCL %08lX\n",
1002 &pCommSrvc->ResultPoolLock,
1003 PsGetCurrentThread()));
1005 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1008 bReleasePools = TRUE;
1011 // The pool can be either ACTIVE or INACTIVE. If the pool state is INACTIVE and we
1012 // are receiving the INIT request, then activate it. If the pool is ACTIVE, then we
1013 // shouldn't be getting this request ...
1016 if( pCommSrvc->IrpPoolControlFlag == POOL_ACTIVE)
1020 // We have already been activated so just fail this request
1023 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1025 else if( pCommSrvc->IrpPoolControlFlag == POOL_INACTIVE)
1029 // The pool is currently INACTIVE so start it up and ready it to
1030 // receive irp requests
1033 pCommSrvc->IrpPoolControlFlag = POOL_ACTIVE;
1035 pDevExt->Specific.Control.ServiceProcess = (PKPROCESS)PsGetCurrentProcess();
1037 try_return( ntStatus = STATUS_SUCCESS);
1043 // The pool is in some mixed state, fail the request.
1046 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1054 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1056 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1067 AFSPoolEntry *pEntry = NULL, *pNextEntry = NULL;
1068 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1069 AFSCommSrvcCB *pCommSrvc = (AFSCommSrvcCB *)&pDevExt->Specific.Control.CommServiceCB;
1075 // When we change the state, grab both pool locks exclusive. The order is always the
1076 // Irp pool then the result pool lock
1079 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1080 AFS_TRACE_LEVEL_VERBOSE,
1081 "AFSCleanupIrpPool Acquiring IrpPoolLock lock %p EXCL %08lX\n",
1082 &pCommSrvc->IrpPoolLock,
1083 PsGetCurrentThread()));
1085 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1088 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1089 AFS_TRACE_LEVEL_VERBOSE,
1090 "AFSCleanupIrpPool Acquiring ResultPoolLock lock %p EXCL %08lX\n",
1091 &pCommSrvc->ResultPoolLock,
1092 PsGetCurrentThread()));
1094 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1098 // Indicate we are pending stop
1101 pCommSrvc->IrpPoolControlFlag = POOL_INACTIVE;
1104 // Set the event to release any waiting workers
1105 // (everyone waits on IrpPoolHasReleaseEntries)
1108 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1113 // Go through the pool entries and free up the structures.
1116 pEntry = pCommSrvc->RequestPoolHead;
1118 while( pEntry != NULL)
1121 pNextEntry = pEntry->fLink;
1123 if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
1127 // Here we need to complete the irp, cancelled, and delete the data block
1130 pEntry->ResultStatus = (ULONG) STATUS_CANCELLED;
1132 KeSetEvent( &pEntry->Event,
1139 ExFreePool( pEntry);
1142 pEntry = pNextEntry;
1146 // Cleanup the control structure for the request pool
1149 pCommSrvc->RequestPoolHead = NULL;
1151 pCommSrvc->RequestPoolTail = NULL;
1153 pCommSrvc->IrpPoolRequestIndex = 1;
1155 KeClearEvent( &pCommSrvc->IrpPoolHasEntries);
1157 KeClearEvent( &pCommSrvc->IrpPoolHasReleaseEntries);
1160 // Release the irp pool lock.
1163 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1166 // Go through the result pool entries and free up the structures.
1169 pEntry = pCommSrvc->ResultPoolHead;
1171 while( pEntry != NULL)
1174 pNextEntry = pEntry->fLink;
1176 pEntry->ResultStatus = (ULONG) STATUS_CANCELLED;
1178 if( pEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_READ_FILE ||
1179 pEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_WRITE_FILE)
1182 AFSFileIOCB *pFileIO = (AFSFileIOCB *)pEntry->Data;
1184 if( pFileIO->MappedIOBuffer != NULL)
1186 MmUnmapLockedPages( pFileIO->MappedIOBuffer,
1187 (PMDL)pFileIO->SystemIOBufferMdl);
1189 pFileIO->MappedIOBuffer = NULL;
1194 // Here we will set the event of the requestor and let the blocked thread
1195 // free the data block
1198 KeSetEvent( &pEntry->Event,
1203 // Go onto the next entry
1206 pEntry = pNextEntry;
1210 // Cleanup the control structure for the result pool
1213 pCommSrvc->ResultPoolHead = NULL;
1215 pCommSrvc->ResultPoolTail = NULL;
1218 // Release the result pool lock.
1221 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1229 AFSInsertRequest( IN AFSCommSrvcCB *CommSrvc,
1230 IN AFSPoolEntry *Entry)
1233 NTSTATUS ntStatus = STATUS_SUCCESS;
1238 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1239 AFS_TRACE_LEVEL_VERBOSE,
1240 "AFSInsertRequest Acquiring IrpPoolLock lock %p EXCL %08lX\n",
1241 &CommSrvc->IrpPoolLock,
1242 PsGetCurrentThread()));
1244 AFSAcquireExcl( &CommSrvc->IrpPoolLock,
1247 if( CommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1250 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1253 if( CommSrvc->RequestPoolHead == NULL)
1256 CommSrvc->RequestPoolHead = Entry;
1261 CommSrvc->RequestPoolTail->fLink = Entry;
1263 Entry->bLink = CommSrvc->RequestPoolTail;
1266 CommSrvc->RequestPoolTail = Entry;
1268 if( Entry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1271 KeSetEvent( &CommSrvc->IrpPoolHasReleaseEntries,
1278 KeSetEvent( &CommSrvc->IrpPoolHasEntries,
1283 InterlockedIncrement( &CommSrvc->QueueCount);
1287 AFSReleaseResource( &CommSrvc->IrpPoolLock);
1294 AFSProcessIrpRequest( IN PIRP Irp)
1297 NTSTATUS ntStatus = STATUS_SUCCESS;
1298 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1299 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1300 AFSCommSrvcCB *pCommSrvc = NULL;
1301 AFSPoolEntry *pEntry = NULL, *pPrevEntry = NULL;
1302 AFSCommRequest *pRequest = NULL;
1303 BOOLEAN bReleaseRequestThread = FALSE;
1309 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1311 pRequest = (AFSCommRequest *)Irp->AssociatedIrp.SystemBuffer;
1313 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1314 AFS_TRACE_LEVEL_VERBOSE,
1315 "AFSProcessIrpRequest Acquiring IrpPoolLock lock %p EXCL %08lX\n",
1316 &pCommSrvc->IrpPoolLock,
1317 PsGetCurrentThread()));
1319 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1322 if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1325 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1327 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1330 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1333 // Is this a dedicated flush thread?
1336 if( BooleanFlagOn( pRequest->RequestFlags, AFS_REQUEST_RELEASE_THREAD))
1339 bReleaseRequestThread = TRUE;
1343 // Populate the objects array for the non release only threads
1344 // Release only workers can only process release extent events
1345 // whereas normal workers can process any kind of event.
1346 // Release only workers are present to ensure there cannot be
1347 // a deadlock due to all extents held by the redirector and
1348 // there not be a worker available to release them.
1351 Objects[0] = &pCommSrvc->IrpPoolHasReleaseEntries;
1353 Objects[1] = &pCommSrvc->IrpPoolHasEntries;
1356 // Wait on the 'have items' event until we can retrieve an item
1362 if( bReleaseRequestThread)
1365 ntStatus = KeWaitForSingleObject( &pCommSrvc->IrpPoolHasReleaseEntries,
1371 if( ntStatus != STATUS_SUCCESS)
1374 ntStatus = STATUS_DEVICE_NOT_READY;
1383 ntStatus = KeWaitForMultipleObjects( 2,
1392 if( ntStatus != STATUS_WAIT_0 &&
1393 ntStatus != STATUS_WAIT_1)
1396 ntStatus = STATUS_DEVICE_NOT_READY;
1403 // Grab the lock on the request pool
1406 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1407 AFS_TRACE_LEVEL_VERBOSE,
1408 "AFSProcessIrpRequest Acquiring IrpPoolLock (WAIT) lock %p EXCL %08lX\n",
1409 &pCommSrvc->IrpPoolLock,
1410 PsGetCurrentThread()));
1412 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1415 if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1418 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1421 // Wake up the next worker since this is a SynchronizationEvent
1424 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1428 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1432 // If this is a dedicated flush thread only look for a flush request in the queue
1435 if( bReleaseRequestThread)
1438 pEntry = pCommSrvc->RequestPoolHead;
1442 while( pEntry != NULL)
1445 if( pEntry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1448 if( pPrevEntry == NULL)
1451 pCommSrvc->RequestPoolHead = pEntry->fLink;
1453 if( pCommSrvc->RequestPoolHead == NULL)
1456 pCommSrvc->RequestPoolTail = NULL;
1462 pPrevEntry->fLink = pEntry->fLink;
1464 if( pPrevEntry->fLink == NULL)
1467 pCommSrvc->RequestPoolTail = pPrevEntry;
1474 pPrevEntry = pEntry;
1476 pEntry = pEntry->fLink;
1483 // There might be another release entry pending
1486 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1492 // And release the request pool lock
1495 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1500 pEntry = pCommSrvc->RequestPoolHead;
1505 pCommSrvc->RequestPoolHead = pEntry->fLink;
1507 pEntry->bLink = NULL;
1509 if( pCommSrvc->RequestPoolHead == NULL)
1512 pCommSrvc->RequestPoolTail = NULL;
1517 KeSetEvent( &pCommSrvc->IrpPoolHasEntries,
1524 // And release the request pool lock
1527 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1531 // Insert the entry into the result pool, if we have one
1538 // Move the request data into the passed in buffer
1541 ASSERT( sizeof( AFSCommRequest) +
1542 pEntry->FileName.Length +
1543 pEntry->DataLength <= pIrpSp->Parameters.DeviceIoControl.OutputBufferLength);
1545 RtlCopyMemory( &pRequest->AuthGroup,
1549 pRequest->FileId = pEntry->FileId;
1551 pRequest->RequestType = pEntry->RequestType;
1553 pRequest->RequestIndex = pEntry->RequestIndex;
1555 pRequest->RequestFlags = pEntry->RequestFlags;
1557 pRequest->NameLength = pEntry->FileName.Length;
1559 pRequest->QueueCount = InterlockedDecrement( &pCommSrvc->QueueCount);
1561 if( pRequest->NameLength > 0)
1564 RtlCopyMemory( pRequest->Name,
1565 pEntry->FileName.Buffer,
1566 pRequest->NameLength);
1570 // If this is an IO request then need to map the system buffer to the service process
1573 if( pEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_READ_FILE ||
1574 pEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_WRITE_FILE)
1577 AFSFileIOCB *pFileIO = (AFSFileIOCB *)pEntry->Data;
1579 ASSERT( pFileIO->SystemIOBuffer != NULL);
1581 pFileIO->MappedIOBuffer = MmMapLockedPagesSpecifyCache( (PMDL)pFileIO->SystemIOBufferMdl,
1586 NormalPagePriority);
1589 pRequest->DataOffset = 0;
1591 pRequest->DataLength = pEntry->DataLength;
1593 if( pRequest->DataLength > 0)
1596 pRequest->DataOffset = pEntry->FileName.Length;
1598 RtlCopyMemory( (void *)((char *)pRequest->Name + pRequest->DataOffset),
1600 pRequest->DataLength);
1603 pRequest->ResultBufferLength = 0;
1605 if( pEntry->ResultBufferLength != NULL)
1608 pRequest->ResultBufferLength = *(pEntry->ResultBufferLength);
1611 Irp->IoStatus.Information = sizeof( AFSCommRequest) +
1612 pEntry->FileName.Length +
1616 // If this is a synchronous request then move the request into the
1620 if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
1623 pEntry->fLink = NULL;
1624 pEntry->bLink = NULL;
1626 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1627 AFS_TRACE_LEVEL_VERBOSE,
1628 "AFSProcessIrpRequest Acquiring ResultPoolLock lock %p EXCL %08lX\n",
1629 &pCommSrvc->ResultPoolLock,
1630 PsGetCurrentThread()));
1632 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1635 if( pCommSrvc->ResultPoolHead == NULL)
1638 pCommSrvc->ResultPoolHead = pEntry;
1643 pCommSrvc->ResultPoolTail->fLink = pEntry;
1645 pEntry->bLink = pCommSrvc->ResultPoolTail;
1648 pCommSrvc->ResultPoolTail = pEntry;
1650 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1656 // Free up the pool entry
1659 ExFreePool( pEntry);
1675 AFSProcessIrpResult( IN PIRP Irp)
1678 NTSTATUS ntStatus = STATUS_SUCCESS;
1679 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1680 AFSCommSrvcCB *pCommSrvc = NULL;
1681 AFSPoolEntry *pCurrentEntry = NULL;
1682 AFSCommResult *pResult = NULL;
1683 ULONG ulCopyLen = 0;
1688 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1691 // Get the request for the incoming result
1694 pResult = (AFSCommResult *)Irp->AssociatedIrp.SystemBuffer;
1696 if( pResult == NULL)
1699 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1703 // Go look for our entry
1706 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1707 AFS_TRACE_LEVEL_VERBOSE,
1708 "AFSProcessIrpResult Acquiring ResultPoolLock lock %p EXCL %08lX\n",
1709 &pCommSrvc->ResultPoolLock,
1710 PsGetCurrentThread()));
1712 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1715 pCurrentEntry = pCommSrvc->ResultPoolHead;
1717 while( pCurrentEntry != NULL)
1720 if( pCurrentEntry->RequestIndex == pResult->RequestIndex)
1724 // Found the entry so remove it from the queue
1727 if( pCurrentEntry->bLink == NULL)
1731 // At the head of the list
1734 pCommSrvc->ResultPoolHead = pCurrentEntry->fLink;
1736 if( pCommSrvc->ResultPoolHead != NULL)
1739 pCommSrvc->ResultPoolHead->bLink = NULL;
1745 pCurrentEntry->bLink->fLink = pCurrentEntry->fLink;
1748 if( pCurrentEntry->fLink == NULL)
1751 pCommSrvc->ResultPoolTail = pCurrentEntry->bLink;
1753 if( pCommSrvc->ResultPoolTail != NULL)
1756 pCommSrvc->ResultPoolTail->fLink = NULL;
1762 pCurrentEntry->fLink->bLink = pCurrentEntry->bLink;
1768 pCurrentEntry = pCurrentEntry->fLink;
1771 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1773 if( pCurrentEntry == NULL)
1776 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1780 // If this is an IO request, unmap the user buffer
1783 if( pCurrentEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_READ_FILE ||
1784 pCurrentEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_WRITE_FILE)
1787 AFSFileIOCB *pFileIO = (AFSFileIOCB *)pCurrentEntry->Data;
1789 if( pFileIO->MappedIOBuffer != NULL)
1791 MmUnmapLockedPages( pFileIO->MappedIOBuffer,
1792 (PMDL)pFileIO->SystemIOBufferMdl);
1794 pFileIO->MappedIOBuffer = NULL;
1799 // OK, move in the result information
1802 pCurrentEntry->ResultStatus = pResult->ResultStatus;
1804 if( ( pCurrentEntry->ResultStatus == STATUS_SUCCESS ||
1805 pCurrentEntry->ResultStatus == STATUS_BUFFER_OVERFLOW) &&
1806 pCurrentEntry->ResultBufferLength != NULL &&
1807 pCurrentEntry->ResultBuffer != NULL)
1810 ASSERT( pResult->ResultBufferLength <= *(pCurrentEntry->ResultBufferLength));
1812 ulCopyLen = pResult->ResultBufferLength;
1814 if( ulCopyLen > *(pCurrentEntry->ResultBufferLength))
1816 ulCopyLen = *(pCurrentEntry->ResultBufferLength);
1819 *(pCurrentEntry->ResultBufferLength) = ulCopyLen;
1821 if( pResult->ResultBufferLength > 0)
1824 RtlCopyMemory( pCurrentEntry->ResultBuffer,
1825 pResult->ResultData,
1830 KeSetEvent( &pCurrentEntry->Event,
1836 if( !NT_SUCCESS( ntStatus))