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;
532 case IOCTL_AFS_SET_REPARSE_POLICY:
533 case IOCTL_AFS_GET_REPARSE_POLICY:
536 // Anyone can call this
539 return STATUS_SUCCESS;
544 // NOTE that for security we police all known functions here
545 // and return STATUS_NOT_IMPLEMENTED. So new ioctls need to
546 // be added both here and either below or in
547 // ..\lib\AFSDevControl.cpp
550 return STATUS_NOT_IMPLEMENTED;
554 AFSProcessControlRequest( IN PIRP Irp)
557 NTSTATUS ntStatus = STATUS_SUCCESS;
558 PIO_STACK_LOCATION pIrpSp;
559 ULONG ulIoControlCode;
560 BOOLEAN bCompleteRequest = TRUE;
561 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
566 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
568 ulIoControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
570 ntStatus = AFSCheckIoctlPermissions( ulIoControlCode);
572 if ( !NT_SUCCESS( ntStatus))
574 try_return( ntStatus);
577 switch( ulIoControlCode)
580 case IOCTL_AFS_INITIALIZE_CONTROL_DEVICE:
583 // Go intialize the pool
585 ntStatus = AFSInitIrpPool();
587 if( !NT_SUCCESS( ntStatus))
598 // Tag this instance as the one to close the irp pool when it is closed
601 pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_CONTROL_INSTANCE);
603 AFSRegisterService();
608 case IOCTL_AFS_INITIALIZE_REDIRECTOR_DEVICE:
611 AFSRedirectorInitInfo *pRedirInitInfo = (AFSRedirectorInitInfo *)Irp->AssociatedIrp.SystemBuffer;
614 // Extract off the passed in information which contains the
615 // cache file parameters
618 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSRedirectorInitInfo) ||
619 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSRedirectorInitInfo, CacheFileName) +
620 pRedirInitInfo->CacheFileNameLength)
623 ntStatus = STATUS_INVALID_PARAMETER;
629 // Initialize the Redirector device
632 ntStatus = AFSInitializeRedirector( pRedirInitInfo);
634 if( !NT_SUCCESS( ntStatus))
641 // Stash away context so we know the instance used to initialize the redirector
644 pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_REDIRECTOR_INSTANCE);
649 case IOCTL_AFS_PROCESS_IRP_REQUEST:
652 ntStatus = AFSProcessIrpRequest( Irp);
657 case IOCTL_AFS_PROCESS_IRP_RESULT:
660 ntStatus = AFSProcessIrpResult( Irp);
665 case IOCTL_AFS_SYSNAME_NOTIFICATION:
668 AFSSysNameNotificationCB *pSysNameInfo = (AFSSysNameNotificationCB *)Irp->AssociatedIrp.SystemBuffer;
670 if( pSysNameInfo == NULL ||
671 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSSysNameNotificationCB))
674 ntStatus = STATUS_INVALID_PARAMETER;
679 ntStatus = AFSSetSysNameInformation( pSysNameInfo,
680 pIrpSp->Parameters.DeviceIoControl.InputBufferLength);
685 case IOCTL_AFS_CONFIGURE_DEBUG_TRACE:
688 AFSTraceConfigCB *pTraceInfo = (AFSTraceConfigCB *)Irp->AssociatedIrp.SystemBuffer;
690 if( pTraceInfo == NULL ||
691 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSTraceConfigCB))
694 ntStatus = STATUS_INVALID_PARAMETER;
699 ntStatus = AFSConfigureTrace( pTraceInfo);
704 case IOCTL_AFS_GET_TRACE_BUFFER:
707 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0)
710 ntStatus = STATUS_INVALID_PARAMETER;
715 ntStatus = AFSGetTraceBuffer( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
716 Irp->AssociatedIrp.SystemBuffer,
717 &Irp->IoStatus.Information);
722 case IOCTL_AFS_FORCE_CRASH:
727 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_FLAG_ENABLE_FORCE_CRASH))
730 KeBugCheck( (ULONG)-1);
737 #ifdef NOT_IMPLEMENTED
738 case IOCTL_AFS_LOAD_LIBRARY:
741 AFSLoadLibraryCB *pLoadLib = (AFSLoadLibraryCB *)Irp->AssociatedIrp.SystemBuffer;
742 UNICODE_STRING uniServicePath;
744 if( pLoadLib == NULL ||
745 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSLoadLibraryCB) ||
746 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSLoadLibraryCB, LibraryServicePath) +
747 pLoadLib->LibraryServicePathLength)
750 ntStatus = STATUS_INVALID_PARAMETER;
755 uniServicePath.Length = pLoadLib->LibraryServicePathLength;
756 uniServicePath.MaximumLength = uniServicePath.Length;
758 uniServicePath.Buffer = pLoadLib->LibraryServicePath;
760 if( uniServicePath.Length == 0)
763 ntStatus = STATUS_INVALID_PARAMETER;
768 ntStatus = AFSLoadLibrary( pLoadLib->Flags,
771 if( NT_SUCCESS( ntStatus))
775 // Intialize the library
778 ntStatus = AFSInitializeLibrary( NULL,
785 case IOCTL_AFS_UNLOAD_LIBRARY:
789 // Try to unload the library we currently have in place
792 ntStatus = AFSUnloadLibrary( FALSE);
798 case IOCTL_AFS_SHUTDOWN:
801 ntStatus = AFSShutdownRedirector();
806 case IOCTL_AFS_AUTHGROUP_CREATE_AND_SET:
809 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
811 if( pAuthGroupRequestCB == NULL ||
812 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
815 ntStatus = STATUS_INVALID_PARAMETER;
820 ntStatus = AFSCreateSetProcessAuthGroup( pAuthGroupRequestCB);
825 case IOCTL_AFS_AUTHGROUP_QUERY:
828 ntStatus = AFSQueryProcessAuthGroupList( ( GUID *)Irp->AssociatedIrp.SystemBuffer,
829 pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
830 &Irp->IoStatus.Information);
835 case IOCTL_AFS_AUTHGROUP_SET:
838 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
840 if( pAuthGroupRequestCB == NULL ||
841 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
844 ntStatus = STATUS_INVALID_PARAMETER;
849 ntStatus = AFSSetActiveProcessAuthGroup( pAuthGroupRequestCB);
854 case IOCTL_AFS_AUTHGROUP_RESET:
857 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
859 if( pAuthGroupRequestCB == NULL ||
860 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
863 ntStatus = STATUS_INVALID_PARAMETER;
868 ntStatus = AFSResetActiveProcessAuthGroup( pAuthGroupRequestCB);
873 case IOCTL_AFS_AUTHGROUP_LOGON_CREATE:
874 case IOCTL_AFS_AUTHGROUP_SID_CREATE:
877 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
879 if( pAuthGroupRequestCB != NULL &&
880 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
883 ntStatus = STATUS_INVALID_PARAMETER;
888 ntStatus = AFSCreateAuthGroupForSIDorLogonSession( pAuthGroupRequestCB,
889 ulIoControlCode == IOCTL_AFS_AUTHGROUP_LOGON_CREATE);
894 case IOCTL_AFS_AUTHGROUP_SID_QUERY:
897 AFSAuthGroupRequestCB *pAuthGroupRequestCB = NULL;
899 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( GUID))
901 ntStatus = STATUS_INVALID_PARAMETER;
905 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof( AFSAuthGroupRequestCB))
907 pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
910 ntStatus = AFSQueryAuthGroup( pAuthGroupRequestCB,
911 (GUID *)Irp->AssociatedIrp.SystemBuffer,
912 &Irp->IoStatus.Information);
917 case IOCTL_AFS_SET_REPARSE_POLICY:
920 AFSSetReparsePointPolicyCB *pPolicy = (AFSSetReparsePointPolicyCB *)Irp->AssociatedIrp.SystemBuffer;
922 if( pPolicy == NULL ||
923 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSSetReparsePointPolicyCB))
925 ntStatus = STATUS_INVALID_PARAMETER;
929 ntStatus = AFSSetReparsePointPolicy( pPolicy);
934 case IOCTL_AFS_GET_REPARSE_POLICY:
937 AFSGetReparsePointPolicyCB *pPolicy = (AFSGetReparsePointPolicyCB *)Irp->AssociatedIrp.SystemBuffer;
939 if( pPolicy == NULL ||
940 pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( AFSGetReparsePointPolicyCB))
942 ntStatus = STATUS_INVALID_PARAMETER;
946 ntStatus = AFSGetReparsePointPolicy( pPolicy);
948 if ( NT_SUCCESS( ntStatus))
951 Irp->IoStatus.Information = sizeof( AFSGetReparsePointPolicyCB);
961 // Check the state of the library
964 ntStatus = AFSCheckLibraryState( Irp);
966 if( !NT_SUCCESS( ntStatus) ||
967 ntStatus == STATUS_PENDING)
970 if( ntStatus == STATUS_PENDING)
972 bCompleteRequest = FALSE;
978 bCompleteRequest = FALSE;
980 IoSkipCurrentIrpStackLocation( Irp);
982 ntStatus = IoCallDriver( pDevExt->Specific.Control.LibraryDeviceObject,
986 // Indicate the library is done with the request
989 AFSClearLibraryRequest();
996 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
999 ntStatus = STATUS_UNSUCCESSFUL;
1001 AFSDumpTraceFilesFnc();
1006 if( bCompleteRequest)
1009 Irp->IoStatus.Status = ntStatus;
1011 AFSCompleteRequest( Irp,
1022 NTSTATUS ntStatus = STATUS_SUCCESS;
1023 AFSCommSrvcCB *pCommSrvc = NULL;
1024 BOOLEAN bReleasePools = FALSE;
1025 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1030 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1033 // Whenever we change state we must grab both pool locks. On the checking of the state
1034 // within the processing routines for these respective pools, we only grab one lock to
1035 // minimize serialization. The ordering is always the Irp pool then the result pool
1036 // locks. We also do this in the tear down of the pool
1039 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1040 AFS_TRACE_LEVEL_VERBOSE,
1041 "AFSInitIrpPool Acquiring IrpPoolLock lock %p EXCL %08lX\n",
1042 &pCommSrvc->IrpPoolLock,
1043 PsGetCurrentThread()));
1045 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1048 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1049 AFS_TRACE_LEVEL_VERBOSE,
1050 "AFSInitIrpPool Acquiring ResultPoolLock lock %p EXCL %08lX\n",
1051 &pCommSrvc->ResultPoolLock,
1052 PsGetCurrentThread()));
1054 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1057 bReleasePools = TRUE;
1060 // The pool can be either ACTIVE or INACTIVE. If the pool state is INACTIVE and we
1061 // are receiving the INIT request, then activate it. If the pool is ACTIVE, then we
1062 // shouldn't be getting this request ...
1065 if( pCommSrvc->IrpPoolControlFlag == POOL_ACTIVE)
1069 // We have already been activated so just fail this request
1072 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1074 else if( pCommSrvc->IrpPoolControlFlag == POOL_INACTIVE)
1078 // The pool is currently INACTIVE so start it up and ready it to
1079 // receive irp requests
1082 pCommSrvc->IrpPoolControlFlag = POOL_ACTIVE;
1084 pDevExt->Specific.Control.ServiceProcess = (PKPROCESS)PsGetCurrentProcess();
1086 try_return( ntStatus = STATUS_SUCCESS);
1092 // The pool is in some mixed state, fail the request.
1095 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1103 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1105 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1116 AFSPoolEntry *pEntry = NULL, *pNextEntry = NULL;
1117 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1118 AFSCommSrvcCB *pCommSrvc = (AFSCommSrvcCB *)&pDevExt->Specific.Control.CommServiceCB;
1124 // When we change the state, grab both pool locks exclusive. The order is always the
1125 // Irp pool then the result pool lock
1128 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1129 AFS_TRACE_LEVEL_VERBOSE,
1130 "AFSCleanupIrpPool Acquiring IrpPoolLock lock %p EXCL %08lX\n",
1131 &pCommSrvc->IrpPoolLock,
1132 PsGetCurrentThread()));
1134 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1137 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1138 AFS_TRACE_LEVEL_VERBOSE,
1139 "AFSCleanupIrpPool Acquiring ResultPoolLock lock %p EXCL %08lX\n",
1140 &pCommSrvc->ResultPoolLock,
1141 PsGetCurrentThread()));
1143 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1147 // Indicate we are pending stop
1150 pCommSrvc->IrpPoolControlFlag = POOL_INACTIVE;
1153 // Set the event to release any waiting workers
1154 // (everyone waits on IrpPoolHasReleaseEntries)
1157 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1162 // Go through the pool entries and free up the structures.
1165 pEntry = pCommSrvc->RequestPoolHead;
1167 while( pEntry != NULL)
1170 pNextEntry = pEntry->fLink;
1172 if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
1176 // Here we need to complete the irp, cancelled, and delete the data block
1179 pEntry->ResultStatus = (ULONG) STATUS_CANCELLED;
1181 KeSetEvent( &pEntry->Event,
1188 ExFreePool( pEntry);
1191 pEntry = pNextEntry;
1195 // Cleanup the control structure for the request pool
1198 pCommSrvc->RequestPoolHead = NULL;
1200 pCommSrvc->RequestPoolTail = NULL;
1202 pCommSrvc->IrpPoolRequestIndex = 1;
1204 KeClearEvent( &pCommSrvc->IrpPoolHasEntries);
1206 KeClearEvent( &pCommSrvc->IrpPoolHasReleaseEntries);
1209 // Release the irp pool lock.
1212 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1215 // Go through the result pool entries and free up the structures.
1218 pEntry = pCommSrvc->ResultPoolHead;
1220 while( pEntry != NULL)
1223 pNextEntry = pEntry->fLink;
1225 pEntry->ResultStatus = (ULONG) STATUS_CANCELLED;
1227 if( pEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_READ_FILE ||
1228 pEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_WRITE_FILE)
1231 AFSFileIOCB *pFileIO = (AFSFileIOCB *)pEntry->Data;
1233 if( pFileIO->MappedIOBuffer != NULL)
1235 MmUnmapLockedPages( pFileIO->MappedIOBuffer,
1236 (PMDL)pFileIO->SystemIOBufferMdl);
1238 pFileIO->MappedIOBuffer = NULL;
1243 // Here we will set the event of the requestor and let the blocked thread
1244 // free the data block
1247 KeSetEvent( &pEntry->Event,
1252 // Go onto the next entry
1255 pEntry = pNextEntry;
1259 // Cleanup the control structure for the result pool
1262 pCommSrvc->ResultPoolHead = NULL;
1264 pCommSrvc->ResultPoolTail = NULL;
1267 // Release the result pool lock.
1270 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1278 AFSInsertRequest( IN AFSCommSrvcCB *CommSrvc,
1279 IN AFSPoolEntry *Entry)
1282 NTSTATUS ntStatus = STATUS_SUCCESS;
1287 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1288 AFS_TRACE_LEVEL_VERBOSE,
1289 "AFSInsertRequest Acquiring IrpPoolLock lock %p EXCL %08lX\n",
1290 &CommSrvc->IrpPoolLock,
1291 PsGetCurrentThread()));
1293 AFSAcquireExcl( &CommSrvc->IrpPoolLock,
1296 if( CommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1299 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1302 if( CommSrvc->RequestPoolHead == NULL)
1305 CommSrvc->RequestPoolHead = Entry;
1310 CommSrvc->RequestPoolTail->fLink = Entry;
1312 Entry->bLink = CommSrvc->RequestPoolTail;
1315 CommSrvc->RequestPoolTail = Entry;
1317 if( Entry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1320 KeSetEvent( &CommSrvc->IrpPoolHasReleaseEntries,
1327 KeSetEvent( &CommSrvc->IrpPoolHasEntries,
1332 InterlockedIncrement( &CommSrvc->QueueCount);
1336 AFSReleaseResource( &CommSrvc->IrpPoolLock);
1343 AFSProcessIrpRequest( IN PIRP Irp)
1346 NTSTATUS ntStatus = STATUS_SUCCESS;
1347 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1348 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1349 AFSCommSrvcCB *pCommSrvc = NULL;
1350 AFSPoolEntry *pEntry = NULL, *pPrevEntry = NULL;
1351 AFSCommRequest *pRequest = NULL;
1352 BOOLEAN bReleaseRequestThread = FALSE;
1358 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1360 pRequest = (AFSCommRequest *)Irp->AssociatedIrp.SystemBuffer;
1362 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1363 AFS_TRACE_LEVEL_VERBOSE,
1364 "AFSProcessIrpRequest Acquiring IrpPoolLock lock %p EXCL %08lX\n",
1365 &pCommSrvc->IrpPoolLock,
1366 PsGetCurrentThread()));
1368 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1371 if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1374 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1376 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1379 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1382 // Is this a dedicated flush thread?
1385 if( BooleanFlagOn( pRequest->RequestFlags, AFS_REQUEST_RELEASE_THREAD))
1388 bReleaseRequestThread = TRUE;
1392 // Populate the objects array for the non release only threads
1393 // Release only workers can only process release extent events
1394 // whereas normal workers can process any kind of event.
1395 // Release only workers are present to ensure there cannot be
1396 // a deadlock due to all extents held by the redirector and
1397 // there not be a worker available to release them.
1400 Objects[0] = &pCommSrvc->IrpPoolHasReleaseEntries;
1402 Objects[1] = &pCommSrvc->IrpPoolHasEntries;
1405 // Wait on the 'have items' event until we can retrieve an item
1411 if( bReleaseRequestThread)
1414 ntStatus = KeWaitForSingleObject( &pCommSrvc->IrpPoolHasReleaseEntries,
1420 if( ntStatus != STATUS_SUCCESS)
1423 ntStatus = STATUS_DEVICE_NOT_READY;
1432 ntStatus = KeWaitForMultipleObjects( 2,
1441 if( ntStatus != STATUS_WAIT_0 &&
1442 ntStatus != STATUS_WAIT_1)
1445 ntStatus = STATUS_DEVICE_NOT_READY;
1452 // Grab the lock on the request pool
1455 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1456 AFS_TRACE_LEVEL_VERBOSE,
1457 "AFSProcessIrpRequest Acquiring IrpPoolLock (WAIT) lock %p EXCL %08lX\n",
1458 &pCommSrvc->IrpPoolLock,
1459 PsGetCurrentThread()));
1461 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1464 if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1467 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1470 // Wake up the next worker since this is a SynchronizationEvent
1473 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1477 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1481 // If this is a dedicated flush thread only look for a flush request in the queue
1484 if( bReleaseRequestThread)
1487 pEntry = pCommSrvc->RequestPoolHead;
1491 while( pEntry != NULL)
1494 if( pEntry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1497 if( pPrevEntry == NULL)
1500 pCommSrvc->RequestPoolHead = pEntry->fLink;
1502 if( pCommSrvc->RequestPoolHead == NULL)
1505 pCommSrvc->RequestPoolTail = NULL;
1511 pPrevEntry->fLink = pEntry->fLink;
1513 if( pPrevEntry->fLink == NULL)
1516 pCommSrvc->RequestPoolTail = pPrevEntry;
1523 pPrevEntry = pEntry;
1525 pEntry = pEntry->fLink;
1532 // There might be another release entry pending
1535 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1541 // And release the request pool lock
1544 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1549 pEntry = pCommSrvc->RequestPoolHead;
1554 pCommSrvc->RequestPoolHead = pEntry->fLink;
1556 pEntry->bLink = NULL;
1558 if( pCommSrvc->RequestPoolHead == NULL)
1561 pCommSrvc->RequestPoolTail = NULL;
1566 KeSetEvent( &pCommSrvc->IrpPoolHasEntries,
1573 // And release the request pool lock
1576 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1580 // Insert the entry into the result pool, if we have one
1587 // Move the request data into the passed in buffer
1590 ASSERT( sizeof( AFSCommRequest) +
1591 pEntry->FileName.Length +
1592 pEntry->DataLength <= pIrpSp->Parameters.DeviceIoControl.OutputBufferLength);
1594 RtlCopyMemory( &pRequest->AuthGroup,
1598 pRequest->FileId = pEntry->FileId;
1600 pRequest->RequestType = pEntry->RequestType;
1602 pRequest->RequestIndex = pEntry->RequestIndex;
1604 pRequest->RequestFlags = pEntry->RequestFlags;
1606 pRequest->NameLength = pEntry->FileName.Length;
1608 pRequest->QueueCount = InterlockedDecrement( &pCommSrvc->QueueCount);
1610 if( pRequest->NameLength > 0)
1613 RtlCopyMemory( pRequest->Name,
1614 pEntry->FileName.Buffer,
1615 pRequest->NameLength);
1619 // If this is an IO request then need to map the system buffer to the service process
1622 if( pEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_READ_FILE ||
1623 pEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_WRITE_FILE)
1626 AFSFileIOCB *pFileIO = (AFSFileIOCB *)pEntry->Data;
1628 ASSERT( pFileIO->SystemIOBuffer != NULL);
1630 pFileIO->MappedIOBuffer = MmMapLockedPagesSpecifyCache( (PMDL)pFileIO->SystemIOBufferMdl,
1635 NormalPagePriority);
1638 pRequest->DataOffset = 0;
1640 pRequest->DataLength = pEntry->DataLength;
1642 if( pRequest->DataLength > 0)
1645 pRequest->DataOffset = pEntry->FileName.Length;
1647 RtlCopyMemory( (void *)((char *)pRequest->Name + pRequest->DataOffset),
1649 pRequest->DataLength);
1652 pRequest->ResultBufferLength = 0;
1654 if( pEntry->ResultBufferLength != NULL)
1657 pRequest->ResultBufferLength = *(pEntry->ResultBufferLength);
1660 Irp->IoStatus.Information = sizeof( AFSCommRequest) +
1661 pEntry->FileName.Length +
1665 // If this is a synchronous request then move the request into the
1669 if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
1672 pEntry->fLink = NULL;
1673 pEntry->bLink = NULL;
1675 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1676 AFS_TRACE_LEVEL_VERBOSE,
1677 "AFSProcessIrpRequest Acquiring ResultPoolLock lock %p EXCL %08lX\n",
1678 &pCommSrvc->ResultPoolLock,
1679 PsGetCurrentThread()));
1681 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1684 if( pCommSrvc->ResultPoolHead == NULL)
1687 pCommSrvc->ResultPoolHead = pEntry;
1692 pCommSrvc->ResultPoolTail->fLink = pEntry;
1694 pEntry->bLink = pCommSrvc->ResultPoolTail;
1697 pCommSrvc->ResultPoolTail = pEntry;
1699 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1705 // Free up the pool entry
1708 ExFreePool( pEntry);
1724 AFSProcessIrpResult( IN PIRP Irp)
1727 NTSTATUS ntStatus = STATUS_SUCCESS;
1728 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1729 AFSCommSrvcCB *pCommSrvc = NULL;
1730 AFSPoolEntry *pCurrentEntry = NULL;
1731 AFSCommResult *pResult = NULL;
1732 ULONG ulCopyLen = 0;
1737 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1740 // Get the request for the incoming result
1743 pResult = (AFSCommResult *)Irp->AssociatedIrp.SystemBuffer;
1745 if( pResult == NULL)
1748 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1752 // Go look for our entry
1755 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1756 AFS_TRACE_LEVEL_VERBOSE,
1757 "AFSProcessIrpResult Acquiring ResultPoolLock lock %p EXCL %08lX\n",
1758 &pCommSrvc->ResultPoolLock,
1759 PsGetCurrentThread()));
1761 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1764 pCurrentEntry = pCommSrvc->ResultPoolHead;
1766 while( pCurrentEntry != NULL)
1769 if( pCurrentEntry->RequestIndex == pResult->RequestIndex)
1773 // Found the entry so remove it from the queue
1776 if( pCurrentEntry->bLink == NULL)
1780 // At the head of the list
1783 pCommSrvc->ResultPoolHead = pCurrentEntry->fLink;
1785 if( pCommSrvc->ResultPoolHead != NULL)
1788 pCommSrvc->ResultPoolHead->bLink = NULL;
1794 pCurrentEntry->bLink->fLink = pCurrentEntry->fLink;
1797 if( pCurrentEntry->fLink == NULL)
1800 pCommSrvc->ResultPoolTail = pCurrentEntry->bLink;
1802 if( pCommSrvc->ResultPoolTail != NULL)
1805 pCommSrvc->ResultPoolTail->fLink = NULL;
1811 pCurrentEntry->fLink->bLink = pCurrentEntry->bLink;
1817 pCurrentEntry = pCurrentEntry->fLink;
1820 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1822 if( pCurrentEntry == NULL)
1825 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1829 // If this is an IO request, unmap the user buffer
1832 if( pCurrentEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_READ_FILE ||
1833 pCurrentEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_WRITE_FILE)
1836 AFSFileIOCB *pFileIO = (AFSFileIOCB *)pCurrentEntry->Data;
1838 if( pFileIO->MappedIOBuffer != NULL)
1840 MmUnmapLockedPages( pFileIO->MappedIOBuffer,
1841 (PMDL)pFileIO->SystemIOBufferMdl);
1843 pFileIO->MappedIOBuffer = NULL;
1848 // OK, move in the result information
1851 pCurrentEntry->ResultStatus = pResult->ResultStatus;
1853 if( ( pCurrentEntry->ResultStatus == STATUS_SUCCESS ||
1854 pCurrentEntry->ResultStatus == STATUS_BUFFER_OVERFLOW) &&
1855 pCurrentEntry->ResultBufferLength != NULL &&
1856 pCurrentEntry->ResultBuffer != NULL)
1859 ASSERT( pResult->ResultBufferLength <= *(pCurrentEntry->ResultBufferLength));
1861 ulCopyLen = pResult->ResultBufferLength;
1863 if( ulCopyLen > *(pCurrentEntry->ResultBufferLength))
1865 ulCopyLen = *(pCurrentEntry->ResultBufferLength);
1868 *(pCurrentEntry->ResultBufferLength) = ulCopyLen;
1870 if( pResult->ResultBufferLength > 0)
1873 RtlCopyMemory( pCurrentEntry->ResultBuffer,
1874 pResult->ResultData,
1879 KeSetEvent( &pCurrentEntry->Event,
1885 if( !NT_SUCCESS( ntStatus))