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_DEBUG_TRACE:
439 case IOCTL_AFS_GET_TRACE_BUFFER:
440 case IOCTL_AFS_FORCE_CRASH:
444 // Any admin can call these
447 if ( !AFSIsInGroup( SeExports->SeAliasAdminsSid))
450 return STATUS_ACCESS_DENIED;
452 return STATUS_SUCCESS;
454 case IOCTL_AFS_AUTHGROUP_CREATE_AND_SET:
455 case IOCTL_AFS_AUTHGROUP_QUERY:
456 case IOCTL_AFS_AUTHGROUP_SET:
457 case IOCTL_AFS_AUTHGROUP_RESET:
458 case IOCTL_AFS_AUTHGROUP_LOGON_CREATE:
459 case IOCTL_AFS_AUTHGROUP_SID_CREATE:
460 case IOCTL_AFS_AUTHGROUP_SID_QUERY:
463 // Anyone can call these.
466 return STATUS_SUCCESS;
469 // And now the LIB ioctls
472 case IOCTL_AFS_INITIALIZE_LIBRARY_DEVICE:
473 case IOCTL_AFS_CONFIG_LIBRARY_TRACE:
476 // Only the kernel can issue this
479 return STATUS_ACCESS_DENIED;
481 case IOCTL_AFS_STATUS_REQUEST:
482 case 0x140390: // IOCTL_LMR_DISABLE_LOCAL_BUFFERING
485 // Anyone can call these.
488 return STATUS_SUCCESS;
490 case IOCTL_AFS_ADD_CONNECTION:
491 case IOCTL_AFS_CANCEL_CONNECTION:
492 case IOCTL_AFS_GET_CONNECTION:
493 case IOCTL_AFS_LIST_CONNECTIONS:
494 case IOCTL_AFS_GET_CONNECTION_INFORMATION:
497 // These must only be called by the network provider but we
498 // don't have a method of enforcing that at the moment.
501 return STATUS_SUCCESS;
503 case IOCTL_AFS_SET_FILE_EXTENTS:
504 case IOCTL_AFS_RELEASE_FILE_EXTENTS:
505 case IOCTL_AFS_SET_FILE_EXTENT_FAILURE:
506 case IOCTL_AFS_INVALIDATE_CACHE:
507 case IOCTL_AFS_NETWORK_STATUS:
508 case IOCTL_AFS_VOLUME_STATUS:
511 // Again, service only
514 if ( !AFSIsService())
517 return STATUS_ACCESS_DENIED;
519 return STATUS_SUCCESS;
521 case IOCTL_AFS_GET_OBJECT_INFORMATION:
527 if ( !AFSIsInGroup( SeExports->SeAliasAdminsSid))
530 return STATUS_ACCESS_DENIED;
532 return STATUS_SUCCESS;
534 case IOCTL_AFS_SET_REPARSE_POLICY:
535 case IOCTL_AFS_GET_REPARSE_POLICY:
538 // Anyone can call this
541 return STATUS_SUCCESS;
546 // NOTE that for security we police all known functions here
547 // and return STATUS_NOT_IMPLEMENTED. So new ioctls need to
548 // be added both here and either below or in
549 // ..\lib\AFSDevControl.cpp
552 return STATUS_NOT_IMPLEMENTED;
556 AFSProcessControlRequest( IN PIRP Irp)
559 NTSTATUS ntStatus = STATUS_SUCCESS;
560 PIO_STACK_LOCATION pIrpSp;
561 ULONG ulIoControlCode;
562 BOOLEAN bCompleteRequest = TRUE;
563 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
568 pIrpSp = IoGetCurrentIrpStackLocation( Irp);
570 ulIoControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
572 ntStatus = AFSCheckIoctlPermissions( ulIoControlCode);
574 if ( !NT_SUCCESS( ntStatus))
576 try_return( ntStatus);
579 switch( ulIoControlCode)
582 case IOCTL_AFS_INITIALIZE_CONTROL_DEVICE:
585 // Go intialize the pool
587 ntStatus = AFSInitIrpPool();
589 if( !NT_SUCCESS( ntStatus))
600 // Tag this instance as the one to close the irp pool when it is closed
603 pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_CONTROL_INSTANCE);
605 AFSRegisterService();
610 case IOCTL_AFS_INITIALIZE_REDIRECTOR_DEVICE:
613 AFSRedirectorInitInfo *pRedirInitInfo = (AFSRedirectorInitInfo *)Irp->AssociatedIrp.SystemBuffer;
616 // Extract off the passed in information which contains the
617 // cache file parameters
620 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSRedirectorInitInfo) ||
621 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSRedirectorInitInfo, CacheFileName) +
622 pRedirInitInfo->CacheFileNameLength)
625 ntStatus = STATUS_INVALID_PARAMETER;
631 // Initialize the Redirector device
634 ntStatus = AFSInitializeRedirector( pRedirInitInfo);
636 if( !NT_SUCCESS( ntStatus))
643 // Stash away context so we know the instance used to initialize the redirector
646 pIrpSp->FileObject->FsContext = (void *)((ULONG_PTR)pIrpSp->FileObject->FsContext | AFS_REDIRECTOR_INSTANCE);
651 case IOCTL_AFS_PROCESS_IRP_REQUEST:
654 ntStatus = AFSProcessIrpRequest( Irp);
659 case IOCTL_AFS_PROCESS_IRP_RESULT:
662 ntStatus = AFSProcessIrpResult( Irp);
667 case IOCTL_AFS_SYSNAME_NOTIFICATION:
670 AFSSysNameNotificationCB *pSysNameInfo = (AFSSysNameNotificationCB *)Irp->AssociatedIrp.SystemBuffer;
672 if( pSysNameInfo == NULL ||
673 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSSysNameNotificationCB))
676 ntStatus = STATUS_INVALID_PARAMETER;
681 ntStatus = AFSSetSysNameInformation( pSysNameInfo,
682 pIrpSp->Parameters.DeviceIoControl.InputBufferLength);
687 case IOCTL_AFS_CONFIGURE_DEBUG_TRACE:
690 AFSTraceConfigCB *pTraceInfo = (AFSTraceConfigCB *)Irp->AssociatedIrp.SystemBuffer;
692 if( pTraceInfo == NULL ||
693 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSTraceConfigCB))
696 ntStatus = STATUS_INVALID_PARAMETER;
701 ntStatus = AFSConfigureTrace( pTraceInfo);
706 case IOCTL_AFS_GET_DEBUG_TRACE:
709 AFSTraceConfigCB *pTraceInfo = (AFSTraceConfigCB *)Irp->AssociatedIrp.SystemBuffer;
711 if( pTraceInfo == NULL ||
712 pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( AFSTraceConfigCB))
715 ntStatus = STATUS_INVALID_PARAMETER;
720 ntStatus = AFSGetTraceConfig( pTraceInfo);
722 if ( NT_SUCCESS( ntStatus))
725 Irp->IoStatus.Information = sizeof( AFSTraceConfigCB);
731 case IOCTL_AFS_GET_TRACE_BUFFER:
734 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0)
737 ntStatus = STATUS_INVALID_PARAMETER;
742 ntStatus = AFSGetTraceBuffer( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
743 Irp->AssociatedIrp.SystemBuffer,
744 &Irp->IoStatus.Information);
749 case IOCTL_AFS_FORCE_CRASH:
754 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_FLAG_ENABLE_FORCE_CRASH))
757 KeBugCheck( (ULONG)-1);
764 #ifdef NOT_IMPLEMENTED
765 case IOCTL_AFS_LOAD_LIBRARY:
768 AFSLoadLibraryCB *pLoadLib = (AFSLoadLibraryCB *)Irp->AssociatedIrp.SystemBuffer;
769 UNICODE_STRING uniServicePath;
771 if( pLoadLib == NULL ||
772 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSLoadLibraryCB) ||
773 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSLoadLibraryCB, LibraryServicePath) +
774 pLoadLib->LibraryServicePathLength)
777 ntStatus = STATUS_INVALID_PARAMETER;
782 uniServicePath.Length = pLoadLib->LibraryServicePathLength;
783 uniServicePath.MaximumLength = uniServicePath.Length;
785 uniServicePath.Buffer = pLoadLib->LibraryServicePath;
787 if( uniServicePath.Length == 0)
790 ntStatus = STATUS_INVALID_PARAMETER;
795 ntStatus = AFSLoadLibrary( pLoadLib->Flags,
798 if( NT_SUCCESS( ntStatus))
802 // Intialize the library
805 ntStatus = AFSInitializeLibrary( NULL,
812 case IOCTL_AFS_UNLOAD_LIBRARY:
816 // Try to unload the library we currently have in place
819 ntStatus = AFSUnloadLibrary( FALSE);
825 case IOCTL_AFS_SHUTDOWN:
828 ntStatus = AFSShutdownRedirector();
833 case IOCTL_AFS_AUTHGROUP_CREATE_AND_SET:
836 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
838 if( pAuthGroupRequestCB == NULL ||
839 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
842 ntStatus = STATUS_INVALID_PARAMETER;
847 ntStatus = AFSCreateSetProcessAuthGroup( pAuthGroupRequestCB);
852 case IOCTL_AFS_AUTHGROUP_QUERY:
855 ntStatus = AFSQueryProcessAuthGroupList( ( GUID *)Irp->AssociatedIrp.SystemBuffer,
856 pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
857 &Irp->IoStatus.Information);
862 case IOCTL_AFS_AUTHGROUP_SET:
865 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
867 if( pAuthGroupRequestCB == NULL ||
868 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
871 ntStatus = STATUS_INVALID_PARAMETER;
876 ntStatus = AFSSetActiveProcessAuthGroup( pAuthGroupRequestCB);
881 case IOCTL_AFS_AUTHGROUP_RESET:
884 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
886 if( pAuthGroupRequestCB == NULL ||
887 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
890 ntStatus = STATUS_INVALID_PARAMETER;
895 ntStatus = AFSResetActiveProcessAuthGroup( pAuthGroupRequestCB);
900 case IOCTL_AFS_AUTHGROUP_LOGON_CREATE:
901 case IOCTL_AFS_AUTHGROUP_SID_CREATE:
904 AFSAuthGroupRequestCB *pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
906 if( pAuthGroupRequestCB != NULL &&
907 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSAuthGroupRequestCB))
910 ntStatus = STATUS_INVALID_PARAMETER;
915 ntStatus = AFSCreateAuthGroupForSIDorLogonSession( pAuthGroupRequestCB,
916 ulIoControlCode == IOCTL_AFS_AUTHGROUP_LOGON_CREATE);
921 case IOCTL_AFS_AUTHGROUP_SID_QUERY:
924 AFSAuthGroupRequestCB *pAuthGroupRequestCB = NULL;
926 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( GUID))
928 ntStatus = STATUS_INVALID_PARAMETER;
932 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof( AFSAuthGroupRequestCB))
934 pAuthGroupRequestCB = (AFSAuthGroupRequestCB *)Irp->AssociatedIrp.SystemBuffer;
937 ntStatus = AFSQueryAuthGroup( pAuthGroupRequestCB,
938 (GUID *)Irp->AssociatedIrp.SystemBuffer,
939 &Irp->IoStatus.Information);
944 case IOCTL_AFS_SET_REPARSE_POLICY:
947 AFSSetReparsePointPolicyCB *pPolicy = (AFSSetReparsePointPolicyCB *)Irp->AssociatedIrp.SystemBuffer;
949 if( pPolicy == NULL ||
950 pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSSetReparsePointPolicyCB))
952 ntStatus = STATUS_INVALID_PARAMETER;
956 ntStatus = AFSSetReparsePointPolicy( pPolicy);
961 case IOCTL_AFS_GET_REPARSE_POLICY:
964 AFSGetReparsePointPolicyCB *pPolicy = (AFSGetReparsePointPolicyCB *)Irp->AssociatedIrp.SystemBuffer;
966 if( pPolicy == NULL ||
967 pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( AFSGetReparsePointPolicyCB))
969 ntStatus = STATUS_INVALID_PARAMETER;
973 ntStatus = AFSGetReparsePointPolicy( pPolicy);
975 if ( NT_SUCCESS( ntStatus))
978 Irp->IoStatus.Information = sizeof( AFSGetReparsePointPolicyCB);
988 // Check the state of the library
991 ntStatus = AFSCheckLibraryState( Irp);
993 if( !NT_SUCCESS( ntStatus) ||
994 ntStatus == STATUS_PENDING)
997 if( ntStatus == STATUS_PENDING)
999 bCompleteRequest = FALSE;
1005 bCompleteRequest = FALSE;
1007 IoSkipCurrentIrpStackLocation( Irp);
1009 ntStatus = IoCallDriver( pDevExt->Specific.Control.LibraryDeviceObject,
1013 // Indicate the library is done with the request
1016 AFSClearLibraryRequest();
1023 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
1026 ntStatus = STATUS_UNSUCCESSFUL;
1028 AFSDumpTraceFilesFnc();
1033 if( bCompleteRequest)
1036 Irp->IoStatus.Status = ntStatus;
1038 AFSCompleteRequest( Irp,
1049 NTSTATUS ntStatus = STATUS_SUCCESS;
1050 AFSCommSrvcCB *pCommSrvc = NULL;
1051 BOOLEAN bReleasePools = FALSE;
1052 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1057 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1060 // Whenever we change state we must grab both pool locks. On the checking of the state
1061 // within the processing routines for these respective pools, we only grab one lock to
1062 // minimize serialization. The ordering is always the Irp pool then the result pool
1063 // locks. We also do this in the tear down of the pool
1066 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1067 AFS_TRACE_LEVEL_VERBOSE,
1068 "AFSInitIrpPool Acquiring IrpPoolLock lock %p EXCL %08lX\n",
1069 &pCommSrvc->IrpPoolLock,
1070 PsGetCurrentThread()));
1072 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1075 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1076 AFS_TRACE_LEVEL_VERBOSE,
1077 "AFSInitIrpPool Acquiring ResultPoolLock lock %p EXCL %08lX\n",
1078 &pCommSrvc->ResultPoolLock,
1079 PsGetCurrentThread()));
1081 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1084 bReleasePools = TRUE;
1087 // The pool can be either ACTIVE or INACTIVE. If the pool state is INACTIVE and we
1088 // are receiving the INIT request, then activate it. If the pool is ACTIVE, then we
1089 // shouldn't be getting this request ...
1092 if( pCommSrvc->IrpPoolControlFlag == POOL_ACTIVE)
1096 // We have already been activated so just fail this request
1099 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1101 else if( pCommSrvc->IrpPoolControlFlag == POOL_INACTIVE)
1105 // The pool is currently INACTIVE so start it up and ready it to
1106 // receive irp requests
1109 pCommSrvc->IrpPoolControlFlag = POOL_ACTIVE;
1111 pDevExt->Specific.Control.ServiceProcess = (PKPROCESS)PsGetCurrentProcess();
1113 try_return( ntStatus = STATUS_SUCCESS);
1119 // The pool is in some mixed state, fail the request.
1122 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1130 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1132 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1143 AFSPoolEntry *pEntry = NULL, *pNextEntry = NULL;
1144 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1145 AFSCommSrvcCB *pCommSrvc = (AFSCommSrvcCB *)&pDevExt->Specific.Control.CommServiceCB;
1151 // When we change the state, grab both pool locks exclusive. The order is always the
1152 // Irp pool then the result pool lock
1155 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1156 AFS_TRACE_LEVEL_VERBOSE,
1157 "AFSCleanupIrpPool Acquiring IrpPoolLock lock %p EXCL %08lX\n",
1158 &pCommSrvc->IrpPoolLock,
1159 PsGetCurrentThread()));
1161 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1164 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1165 AFS_TRACE_LEVEL_VERBOSE,
1166 "AFSCleanupIrpPool Acquiring ResultPoolLock lock %p EXCL %08lX\n",
1167 &pCommSrvc->ResultPoolLock,
1168 PsGetCurrentThread()));
1170 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1174 // Indicate we are pending stop
1177 pCommSrvc->IrpPoolControlFlag = POOL_INACTIVE;
1180 // Set the event to release any waiting workers
1181 // (everyone waits on IrpPoolHasReleaseEntries)
1184 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1189 // Go through the pool entries and free up the structures.
1192 pEntry = pCommSrvc->RequestPoolHead;
1194 while( pEntry != NULL)
1197 pNextEntry = pEntry->fLink;
1199 if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
1203 // Here we need to complete the irp, cancelled, and delete the data block
1206 pEntry->ResultStatus = (ULONG) STATUS_CANCELLED;
1208 KeSetEvent( &pEntry->Event,
1215 ExFreePool( pEntry);
1218 pEntry = pNextEntry;
1222 // Cleanup the control structure for the request pool
1225 pCommSrvc->RequestPoolHead = NULL;
1227 pCommSrvc->RequestPoolTail = NULL;
1229 pCommSrvc->IrpPoolRequestIndex = 1;
1231 KeClearEvent( &pCommSrvc->IrpPoolHasEntries);
1233 KeClearEvent( &pCommSrvc->IrpPoolHasReleaseEntries);
1236 // Release the irp pool lock.
1239 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1242 // Go through the result pool entries and free up the structures.
1245 pEntry = pCommSrvc->ResultPoolHead;
1247 while( pEntry != NULL)
1250 pNextEntry = pEntry->fLink;
1252 pEntry->ResultStatus = (ULONG) STATUS_CANCELLED;
1254 if( pEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_READ_FILE ||
1255 pEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_WRITE_FILE)
1258 AFSFileIOCB *pFileIO = (AFSFileIOCB *)pEntry->Data;
1260 if( pFileIO->MappedIOBuffer != NULL)
1262 MmUnmapLockedPages( pFileIO->MappedIOBuffer,
1263 (PMDL)pFileIO->SystemIOBufferMdl);
1265 pFileIO->MappedIOBuffer = NULL;
1270 // Here we will set the event of the requestor and let the blocked thread
1271 // free the data block
1274 KeSetEvent( &pEntry->Event,
1279 // Go onto the next entry
1282 pEntry = pNextEntry;
1286 // Cleanup the control structure for the result pool
1289 pCommSrvc->ResultPoolHead = NULL;
1291 pCommSrvc->ResultPoolTail = NULL;
1294 // Release the result pool lock.
1297 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1305 AFSInsertRequest( IN AFSCommSrvcCB *CommSrvc,
1306 IN AFSPoolEntry *Entry)
1309 NTSTATUS ntStatus = STATUS_SUCCESS;
1314 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1315 AFS_TRACE_LEVEL_VERBOSE,
1316 "AFSInsertRequest Acquiring IrpPoolLock lock %p EXCL %08lX\n",
1317 &CommSrvc->IrpPoolLock,
1318 PsGetCurrentThread()));
1320 AFSAcquireExcl( &CommSrvc->IrpPoolLock,
1323 if( CommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1326 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1329 if( CommSrvc->RequestPoolHead == NULL)
1332 CommSrvc->RequestPoolHead = Entry;
1337 CommSrvc->RequestPoolTail->fLink = Entry;
1339 Entry->bLink = CommSrvc->RequestPoolTail;
1342 CommSrvc->RequestPoolTail = Entry;
1344 if( Entry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1347 KeSetEvent( &CommSrvc->IrpPoolHasReleaseEntries,
1354 KeSetEvent( &CommSrvc->IrpPoolHasEntries,
1359 InterlockedIncrement( &CommSrvc->QueueCount);
1363 AFSReleaseResource( &CommSrvc->IrpPoolLock);
1370 AFSProcessIrpRequest( IN PIRP Irp)
1373 NTSTATUS ntStatus = STATUS_SUCCESS;
1374 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1375 IO_STACK_LOCATION *pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1376 AFSCommSrvcCB *pCommSrvc = NULL;
1377 AFSPoolEntry *pEntry = NULL, *pPrevEntry = NULL;
1378 AFSCommRequest *pRequest = NULL;
1379 BOOLEAN bReleaseRequestThread = FALSE;
1385 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1387 pRequest = (AFSCommRequest *)Irp->AssociatedIrp.SystemBuffer;
1389 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1390 AFS_TRACE_LEVEL_VERBOSE,
1391 "AFSProcessIrpRequest Acquiring IrpPoolLock lock %p EXCL %08lX\n",
1392 &pCommSrvc->IrpPoolLock,
1393 PsGetCurrentThread()));
1395 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1398 if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1401 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1403 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1406 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1409 // Is this a dedicated flush thread?
1412 if( BooleanFlagOn( pRequest->RequestFlags, AFS_REQUEST_RELEASE_THREAD))
1415 bReleaseRequestThread = TRUE;
1419 // Populate the objects array for the non release only threads
1420 // Release only workers can only process release extent events
1421 // whereas normal workers can process any kind of event.
1422 // Release only workers are present to ensure there cannot be
1423 // a deadlock due to all extents held by the redirector and
1424 // there not be a worker available to release them.
1427 Objects[0] = &pCommSrvc->IrpPoolHasReleaseEntries;
1429 Objects[1] = &pCommSrvc->IrpPoolHasEntries;
1432 // Wait on the 'have items' event until we can retrieve an item
1438 if( bReleaseRequestThread)
1441 ntStatus = KeWaitForSingleObject( &pCommSrvc->IrpPoolHasReleaseEntries,
1447 if( ntStatus != STATUS_SUCCESS)
1450 ntStatus = STATUS_DEVICE_NOT_READY;
1459 ntStatus = KeWaitForMultipleObjects( 2,
1468 if( ntStatus != STATUS_WAIT_0 &&
1469 ntStatus != STATUS_WAIT_1)
1472 ntStatus = STATUS_DEVICE_NOT_READY;
1479 // Grab the lock on the request pool
1482 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1483 AFS_TRACE_LEVEL_VERBOSE,
1484 "AFSProcessIrpRequest Acquiring IrpPoolLock (WAIT) lock %p EXCL %08lX\n",
1485 &pCommSrvc->IrpPoolLock,
1486 PsGetCurrentThread()));
1488 AFSAcquireExcl( &pCommSrvc->IrpPoolLock,
1491 if( pCommSrvc->IrpPoolControlFlag != POOL_ACTIVE)
1494 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1497 // Wake up the next worker since this is a SynchronizationEvent
1500 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1504 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
1508 // If this is a dedicated flush thread only look for a flush request in the queue
1511 if( bReleaseRequestThread)
1514 pEntry = pCommSrvc->RequestPoolHead;
1518 while( pEntry != NULL)
1521 if( pEntry->RequestType == AFS_REQUEST_TYPE_RELEASE_FILE_EXTENTS)
1524 if( pPrevEntry == NULL)
1527 pCommSrvc->RequestPoolHead = pEntry->fLink;
1529 if( pCommSrvc->RequestPoolHead == NULL)
1532 pCommSrvc->RequestPoolTail = NULL;
1538 pPrevEntry->fLink = pEntry->fLink;
1540 if( pPrevEntry->fLink == NULL)
1543 pCommSrvc->RequestPoolTail = pPrevEntry;
1550 pPrevEntry = pEntry;
1552 pEntry = pEntry->fLink;
1559 // There might be another release entry pending
1562 KeSetEvent( &pCommSrvc->IrpPoolHasReleaseEntries,
1568 // And release the request pool lock
1571 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1576 pEntry = pCommSrvc->RequestPoolHead;
1581 pCommSrvc->RequestPoolHead = pEntry->fLink;
1583 pEntry->bLink = NULL;
1585 if( pCommSrvc->RequestPoolHead == NULL)
1588 pCommSrvc->RequestPoolTail = NULL;
1593 KeSetEvent( &pCommSrvc->IrpPoolHasEntries,
1600 // And release the request pool lock
1603 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
1607 // Insert the entry into the result pool, if we have one
1614 // Move the request data into the passed in buffer
1617 ASSERT( sizeof( AFSCommRequest) +
1618 pEntry->FileName.Length +
1619 pEntry->DataLength <= pIrpSp->Parameters.DeviceIoControl.OutputBufferLength);
1621 RtlCopyMemory( &pRequest->AuthGroup,
1625 pRequest->FileId = pEntry->FileId;
1627 pRequest->RequestType = pEntry->RequestType;
1629 pRequest->RequestIndex = pEntry->RequestIndex;
1631 pRequest->RequestFlags = pEntry->RequestFlags;
1633 pRequest->NameLength = pEntry->FileName.Length;
1635 pRequest->QueueCount = InterlockedDecrement( &pCommSrvc->QueueCount);
1637 if( pRequest->NameLength > 0)
1640 RtlCopyMemory( pRequest->Name,
1641 pEntry->FileName.Buffer,
1642 pRequest->NameLength);
1646 // If this is an IO request then need to map the system buffer to the service process
1649 if( pEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_READ_FILE ||
1650 pEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_WRITE_FILE)
1653 AFSFileIOCB *pFileIO = (AFSFileIOCB *)pEntry->Data;
1655 ASSERT( pFileIO->SystemIOBuffer != NULL);
1657 pFileIO->MappedIOBuffer = MmMapLockedPagesSpecifyCache( (PMDL)pFileIO->SystemIOBufferMdl,
1662 NormalPagePriority);
1665 pRequest->DataOffset = 0;
1667 pRequest->DataLength = pEntry->DataLength;
1669 if( pRequest->DataLength > 0)
1672 pRequest->DataOffset = pEntry->FileName.Length;
1674 RtlCopyMemory( (void *)((char *)pRequest->Name + pRequest->DataOffset),
1676 pRequest->DataLength);
1679 pRequest->ResultBufferLength = 0;
1681 if( pEntry->ResultBufferLength != NULL)
1684 pRequest->ResultBufferLength = *(pEntry->ResultBufferLength);
1687 Irp->IoStatus.Information = sizeof( AFSCommRequest) +
1688 pEntry->FileName.Length +
1692 // If this is a synchronous request then move the request into the
1696 if( BooleanFlagOn( pEntry->RequestFlags, AFS_REQUEST_FLAG_SYNCHRONOUS))
1699 pEntry->fLink = NULL;
1700 pEntry->bLink = NULL;
1702 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1703 AFS_TRACE_LEVEL_VERBOSE,
1704 "AFSProcessIrpRequest Acquiring ResultPoolLock lock %p EXCL %08lX\n",
1705 &pCommSrvc->ResultPoolLock,
1706 PsGetCurrentThread()));
1708 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1711 if( pCommSrvc->ResultPoolHead == NULL)
1714 pCommSrvc->ResultPoolHead = pEntry;
1719 pCommSrvc->ResultPoolTail->fLink = pEntry;
1721 pEntry->bLink = pCommSrvc->ResultPoolTail;
1724 pCommSrvc->ResultPoolTail = pEntry;
1726 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1732 // Free up the pool entry
1735 ExFreePool( pEntry);
1751 AFSProcessIrpResult( IN PIRP Irp)
1754 NTSTATUS ntStatus = STATUS_SUCCESS;
1755 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
1756 AFSCommSrvcCB *pCommSrvc = NULL;
1757 AFSPoolEntry *pCurrentEntry = NULL;
1758 AFSCommResult *pResult = NULL;
1759 ULONG ulCopyLen = 0;
1764 pCommSrvc = &pDevExt->Specific.Control.CommServiceCB;
1767 // Get the request for the incoming result
1770 pResult = (AFSCommResult *)Irp->AssociatedIrp.SystemBuffer;
1772 if( pResult == NULL)
1775 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1779 // Go look for our entry
1782 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1783 AFS_TRACE_LEVEL_VERBOSE,
1784 "AFSProcessIrpResult Acquiring ResultPoolLock lock %p EXCL %08lX\n",
1785 &pCommSrvc->ResultPoolLock,
1786 PsGetCurrentThread()));
1788 AFSAcquireExcl( &pCommSrvc->ResultPoolLock,
1791 pCurrentEntry = pCommSrvc->ResultPoolHead;
1793 while( pCurrentEntry != NULL)
1796 if( pCurrentEntry->RequestIndex == pResult->RequestIndex)
1800 // Found the entry so remove it from the queue
1803 if( pCurrentEntry->bLink == NULL)
1807 // At the head of the list
1810 pCommSrvc->ResultPoolHead = pCurrentEntry->fLink;
1812 if( pCommSrvc->ResultPoolHead != NULL)
1815 pCommSrvc->ResultPoolHead->bLink = NULL;
1821 pCurrentEntry->bLink->fLink = pCurrentEntry->fLink;
1824 if( pCurrentEntry->fLink == NULL)
1827 pCommSrvc->ResultPoolTail = pCurrentEntry->bLink;
1829 if( pCommSrvc->ResultPoolTail != NULL)
1832 pCommSrvc->ResultPoolTail->fLink = NULL;
1838 pCurrentEntry->fLink->bLink = pCurrentEntry->bLink;
1844 pCurrentEntry = pCurrentEntry->fLink;
1847 AFSReleaseResource( &pCommSrvc->ResultPoolLock);
1849 if( pCurrentEntry == NULL)
1852 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1856 // If this is an IO request, unmap the user buffer
1859 if( pCurrentEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_READ_FILE ||
1860 pCurrentEntry->RequestType == AFS_REQUEST_TYPE_PROCESS_WRITE_FILE)
1863 AFSFileIOCB *pFileIO = (AFSFileIOCB *)pCurrentEntry->Data;
1865 if( pFileIO->MappedIOBuffer != NULL)
1867 MmUnmapLockedPages( pFileIO->MappedIOBuffer,
1868 (PMDL)pFileIO->SystemIOBufferMdl);
1870 pFileIO->MappedIOBuffer = NULL;
1875 // OK, move in the result information
1878 pCurrentEntry->ResultStatus = pResult->ResultStatus;
1880 if( ( pCurrentEntry->ResultStatus == STATUS_SUCCESS ||
1881 pCurrentEntry->ResultStatus == STATUS_BUFFER_OVERFLOW) &&
1882 pCurrentEntry->ResultBufferLength != NULL &&
1883 pCurrentEntry->ResultBuffer != NULL)
1886 ASSERT( pResult->ResultBufferLength <= *(pCurrentEntry->ResultBufferLength));
1888 ulCopyLen = pResult->ResultBufferLength;
1890 if( ulCopyLen > *(pCurrentEntry->ResultBufferLength))
1892 ulCopyLen = *(pCurrentEntry->ResultBufferLength);
1895 *(pCurrentEntry->ResultBufferLength) = ulCopyLen;
1897 if( pResult->ResultBufferLength > 0)
1900 RtlCopyMemory( pCurrentEntry->ResultBuffer,
1901 pResult->ResultData,
1906 KeSetEvent( &pCurrentEntry->Event,
1912 if( !NT_SUCCESS( ntStatus))