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: AFSRDRSupport.cpp
38 #include "AFSCommon.h"
40 typedef NTSTATUS (*FsRtlRegisterUncProviderEx_t)( PHANDLE MupHandle, PUNICODE_STRING RedirDevName, PDEVICE_OBJECT DeviceObject, ULONG Flags);
46 NTSTATUS ntStatus = STATUS_SUCCESS;
47 UNICODE_STRING uniDeviceName;
48 AFSDeviceExt *pDeviceExt = NULL;
49 UNICODE_STRING uniFsRtlRegisterUncProviderEx;
50 FsRtlRegisterUncProviderEx_t pFsRtlRegisterUncProviderEx = NULL;
51 RTL_OSVERSIONINFOW sysVersion;
52 ULONG ulDeviceCharacteristics = FILE_REMOTE_DEVICE;
57 RtlZeroMemory( &sysVersion,
58 sizeof( RTL_OSVERSIONINFOW));
60 sysVersion.dwOSVersionInfoSize = sizeof( RTL_OSVERSIONINFOW);
62 RtlGetVersion( &sysVersion);
64 RtlInitUnicodeString( &uniDeviceName,
67 RtlInitUnicodeString( &uniFsRtlRegisterUncProviderEx,
68 L"FsRtlRegisterUncProviderEx");
70 pFsRtlRegisterUncProviderEx = (FsRtlRegisterUncProviderEx_t)MmGetSystemRoutineAddress(&uniFsRtlRegisterUncProviderEx);
73 // On 32-bit Windows XP, do not set FILE_DEVICE_SECURE_OPEN
74 // flag as it interferes with initial access to \\afs from
75 // limited user accounts.
78 if(!(sysVersion.dwMajorVersion == 5 &&
79 sysVersion.dwMinorVersion == 1))
82 ulDeviceCharacteristics |= FILE_DEVICE_SECURE_OPEN;
85 ntStatus = IoCreateDevice( AFSDriverObject,
86 sizeof( AFSDeviceExt),
87 pFsRtlRegisterUncProviderEx ? NULL : &uniDeviceName,
88 FILE_DEVICE_NETWORK_FILE_SYSTEM,
89 ulDeviceCharacteristics,
93 if( !NT_SUCCESS( ntStatus))
96 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
97 AFS_TRACE_LEVEL_ERROR,
98 "AFSInitRDRDevice IoCreateDevice failure %08lX\n",
101 try_return( ntStatus);
104 pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
106 RtlZeroMemory( pDeviceExt,
107 sizeof( AFSDeviceExt));
110 // Initialize resources
113 pDeviceExt->Specific.RDR.VolumeTree.TreeLock = &pDeviceExt->Specific.RDR.VolumeTreeLock;
115 ExInitializeResourceLite( pDeviceExt->Specific.RDR.VolumeTree.TreeLock);
117 pDeviceExt->Specific.RDR.VolumeTree.TreeHead = NULL;
119 ExInitializeResourceLite( &pDeviceExt->Specific.RDR.VolumeListLock);
121 pDeviceExt->Specific.RDR.VolumeListHead = NULL;
123 pDeviceExt->Specific.RDR.VolumeListTail = NULL;
125 KeInitializeEvent( &pDeviceExt->Specific.RDR.QueuedReleaseExtentEvent,
129 ExInitializeResourceLite( &pDeviceExt->Specific.RDR.RootCellTreeLock);
131 pDeviceExt->Specific.RDR.RootCellTree.TreeLock = &pDeviceExt->Specific.RDR.RootCellTreeLock;
133 pDeviceExt->Specific.RDR.RootCellTree.TreeHead = NULL;
135 ExInitializeResourceLite( &pDeviceExt->Specific.RDR.ProviderListLock);
137 ntStatus = AFSInitRdrFcb( &pDeviceExt->Fcb);
139 if ( !NT_SUCCESS(ntStatus))
142 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
143 AFS_TRACE_LEVEL_ERROR,
144 "AFSInitRDRDevice AFSInitRdrFcb failure %08lX\n",
147 try_return( ntStatus);
151 // Clear the initializing bit
154 AFSRDRDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
157 // Increase the StackSize to support the extra stack frame required
158 // for use of IoCompletion routines.
161 AFSRDRDeviceObject->StackSize++;
164 // Register this device with MUP with FilterMgr if Vista or above
167 if( pFsRtlRegisterUncProviderEx)
170 ntStatus = pFsRtlRegisterUncProviderEx( &AFSMUPHandle,
174 if ( !NT_SUCCESS( ntStatus))
176 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
177 AFS_TRACE_LEVEL_ERROR,
178 "AFSInitRDRDevice FsRtlRegisterUncProvider failure %08lX\n",
185 ntStatus = FsRtlRegisterUncProvider( &AFSMUPHandle,
189 if ( NT_SUCCESS( ntStatus))
192 IoRegisterFileSystem( AFSRDRDeviceObject);
196 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
197 AFS_TRACE_LEVEL_ERROR,
198 "AFSInitRDRDevice FsRtlRegisterUncProvider failure %08lX\n",
204 // Good to go, all registered and ready to start receiving requests
209 if( !NT_SUCCESS( ntStatus))
213 // Delete our device and bail
216 ExDeleteResourceLite( pDeviceExt->Specific.RDR.VolumeTree.TreeLock);
218 ExDeleteResourceLite( &pDeviceExt->Specific.RDR.VolumeListLock);
220 ExDeleteResourceLite( &pDeviceExt->Specific.RDR.RootCellTreeLock);
222 ExDeleteResourceLite( &pDeviceExt->Specific.RDR.ProviderListLock);
224 IoDeleteDevice( AFSRDRDeviceObject);
226 AFSRDRDeviceObject = NULL;
228 try_return( ntStatus);
236 AFSRDRDeviceControl( IN PDEVICE_OBJECT DeviceObject,
239 UNREFERENCED_PARAMETER(DeviceObject);
241 NTSTATUS ntStatus = STATUS_SUCCESS;
242 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
243 BOOLEAN bCompleteIrp = TRUE;
248 switch( pIrpSp->Parameters.DeviceIoControl.IoControlCode)
251 case IOCTL_REDIR_QUERY_PATH:
254 QUERY_PATH_REQUEST *pPathRequest = (QUERY_PATH_REQUEST *)pIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
255 QUERY_PATH_RESPONSE *pPathResponse = (QUERY_PATH_RESPONSE *)Irp->UserBuffer;
256 UNICODE_STRING uniPathName;
258 ntStatus = STATUS_BAD_NETWORK_PATH;
260 uniPathName.Length = (USHORT)pPathRequest->PathNameLength;
261 uniPathName.MaximumLength = uniPathName.Length;
263 uniPathName.Buffer = pPathRequest->FilePathName;
265 if( uniPathName.Length >= AFSServerName.Length + sizeof( WCHAR))
268 USHORT usLength = uniPathName.Length;
270 uniPathName.Length = AFSServerName.Length;
273 // Skip over the first slash in the name
276 uniPathName.Buffer = &uniPathName.Buffer[ 1];
280 // Check to see if the first (or only) component
281 // of the path matches the server name
284 if( RtlCompareUnicodeString( &AFSServerName,
287 ( usLength == AFSServerName.Length + sizeof( WCHAR) ||
288 uniPathName.Buffer[ AFSServerName.Length / sizeof( WCHAR)] == '\\'))
291 ntStatus = STATUS_SUCCESS;
293 pPathResponse->LengthAccepted = AFSServerName.Length + sizeof( WCHAR);
300 case IOCTL_REDIR_QUERY_PATH_EX:
303 QUERY_PATH_REQUEST_EX *pPathRequest = (QUERY_PATH_REQUEST_EX *)pIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
304 QUERY_PATH_RESPONSE *pPathResponse = (QUERY_PATH_RESPONSE *)Irp->UserBuffer;
305 UNICODE_STRING uniPathName;
307 ntStatus = STATUS_BAD_NETWORK_PATH;
309 uniPathName.Length = pPathRequest->PathName.Length;
310 uniPathName.MaximumLength = uniPathName.Length;
312 uniPathName.Buffer = pPathRequest->PathName.Buffer;
314 if( uniPathName.Length >= AFSServerName.Length + sizeof( WCHAR))
317 USHORT usLength = uniPathName.Length;
319 uniPathName.Length = AFSServerName.Length;
322 // Skip over the first slash in the name
325 uniPathName.Buffer = &uniPathName.Buffer[ 1];
329 // Check to see if the first (or only) component
330 // of the path matches the server name
333 if( RtlCompareUnicodeString( &AFSServerName,
336 ( usLength == AFSServerName.Length + sizeof( WCHAR) ||
337 uniPathName.Buffer[ AFSServerName.Length / sizeof( WCHAR)] == '\\'))
340 ntStatus = STATUS_SUCCESS;
342 pPathResponse->LengthAccepted = AFSServerName.Length + sizeof( WCHAR);
351 ntStatus = STATUS_INVALID_DEVICE_REQUEST;
359 // Complete the request
362 AFSCompleteRequest( Irp,
371 AFSInitializeRedirector( IN AFSRedirectorInitInfo *RedirInitInfo)
374 NTSTATUS ntStatus = STATUS_SUCCESS;
375 LARGE_INTEGER cacheSizeBytes;
376 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
377 OBJECT_ATTRIBUTES stObjectAttribs;
378 IO_STATUS_BLOCK stIoStatus;
379 UNICODE_STRING uniServiceName;
385 // First this is to load the library
388 RtlInitUnicodeString( &uniServiceName,
389 AFS_REDIR_LIBRARY_SERVICE_ENTRY);
391 ntStatus = AFSLoadLibrary( 0,
394 if( !NT_SUCCESS( ntStatus))
397 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
398 AFS_TRACE_LEVEL_ERROR,
399 "AFSInitializeRedirector AFSLoadLibrary failure %08lX\n",
402 try_return( ntStatus);
406 // Save off the cache file information
409 pDevExt->Specific.RDR.CacheBlockSize = RedirInitInfo->CacheBlockSize;
411 pDevExt->Specific.RDR.CacheBlockCount = RedirInitInfo->ExtentCount;
413 pDevExt->Specific.RDR.MaximumRPCLength = RedirInitInfo->MaximumChunkLength;
415 cacheSizeBytes = RedirInitInfo->ExtentCount;
416 cacheSizeBytes.QuadPart *= RedirInitInfo->CacheBlockSize;
418 AFSDumpFileLocation.Length = 0;
420 AFSDumpFileLocation.MaximumLength = (USHORT)RedirInitInfo->DumpFileLocationLength + (4 * sizeof( WCHAR));
422 AFSDumpFileLocation.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
423 AFSDumpFileLocation.MaximumLength,
424 AFS_GENERIC_MEMORY_23_TAG);
426 if( AFSDumpFileLocation.Buffer == NULL)
429 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
430 AFS_TRACE_LEVEL_ERROR,
431 "AFSInitializeRedirector AFS_GENERIC_MEMORY_23_TAG allocation error\n"));
433 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
436 RtlCopyMemory( AFSDumpFileLocation.Buffer,
440 AFSDumpFileLocation.Length = 4 * sizeof( WCHAR);
442 RtlCopyMemory( &AFSDumpFileLocation.Buffer[ AFSDumpFileLocation.Length/sizeof( WCHAR)],
443 (void *)((char *)RedirInitInfo + RedirInitInfo->DumpFileLocationOffset),
444 RedirInitInfo->DumpFileLocationLength);
446 AFSDumpFileLocation.Length += (USHORT)RedirInitInfo->DumpFileLocationLength;
449 // Be sure the shutdown flag is not set
452 ClearFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN);
455 // Set up the Throttles.
457 // Max IO is 10% of the cache, or the value in the registry,
458 // with a minimum of 5Mb (and a maximum of 50% cache size)
463 // collect what the user
465 pDevExt->Specific.RDR.MaxIo.QuadPart = AFSMaxDirectIo;
466 pDevExt->Specific.RDR.MaxIo.QuadPart *= (1024 * 1024);
472 pDevExt->Specific.RDR.MaxIo.QuadPart = cacheSizeBytes.QuadPart / 2;
475 if (pDevExt->Specific.RDR.MaxIo.QuadPart < (5 * 1024 * 1204))
478 pDevExt->Specific.RDR.MaxIo.QuadPart = 5 * 1024 * 1204;
483 // For small cache configurations ...
486 if (pDevExt->Specific.RDR.MaxIo.QuadPart > cacheSizeBytes.QuadPart / 2)
489 pDevExt->Specific.RDR.MaxIo.QuadPart = cacheSizeBytes.QuadPart / 2;
493 // Maximum Dirty is 50% of the cache, or the value in the
494 // registry. No minimum, maximum of 90% of cache size.
499 pDevExt->Specific.RDR.MaxDirty.QuadPart = AFSMaxDirtyFile;
500 pDevExt->Specific.RDR.MaxDirty.QuadPart *= (1024 * 1024);
506 pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart/2;
510 cacheSizeBytes.QuadPart *= 9;
511 cacheSizeBytes.QuadPart = cacheSizeBytes.QuadPart / 10;
513 if (pDevExt->Specific.RDR.MaxDirty.QuadPart > cacheSizeBytes.QuadPart)
515 pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart;
519 // Store off any flags for the file system
522 if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_FLAG_HIDE_DOT_FILES))
526 // Hide files which begin with .
529 SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES);
532 if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_FLAG_DISABLE_SHORTNAMES))
536 // Hide files which begin with .
539 SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES);
543 // Global Reparse Point Policy
546 pDevExt->Specific.RDR.ReparsePointPolicy = RedirInitInfo->GlobalReparsePointPolicy;
549 // Are we performing direct to service IO?
552 if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_PERFORM_SERVICE_IO))
556 // Send IO requests directly to service
559 SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO);
564 if( RedirInitInfo->MemoryCacheOffset.QuadPart != 0 &&
565 RedirInitInfo->MemoryCacheLength.QuadPart != 0)
568 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
571 pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL,
572 (void *)RedirInitInfo->MemoryCacheOffset.QuadPart,
573 RedirInitInfo->MemoryCacheLength.QuadPart);
575 pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL,
576 (void *)RedirInitInfo->MemoryCacheOffset.LowPart,
577 RedirInitInfo->MemoryCacheLength.LowPart);
580 if( pDevExt->Specific.RDR.CacheMdl != NULL)
586 MmProbeAndLockPages( pDevExt->Specific.RDR.CacheMdl,
590 pDevExt->Specific.RDR.CacheBaseAddress = MmGetSystemAddressForMdlSafe( pDevExt->Specific.RDR.CacheMdl,
593 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
596 AFSDumpTraceFilesFnc();
598 IoFreeMdl( pDevExt->Specific.RDR.CacheMdl);
599 pDevExt->Specific.RDR.CacheMdl = NULL;
602 if( pDevExt->Specific.RDR.CacheMdl != NULL)
604 pDevExt->Specific.RDR.CacheLength = RedirInitInfo->MemoryCacheLength;
605 ntStatus = STATUS_SUCCESS;
611 if( !NT_SUCCESS( ntStatus) &&
612 RedirInitInfo->CacheFileNameLength == 0)
615 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
616 AFS_TRACE_LEVEL_ERROR,
617 "AFSInitializeRedirector Unable to initialize cache file %08lX\n",
620 try_return( ntStatus);
623 if( pDevExt->Specific.RDR.CacheMdl == NULL)
626 if( RedirInitInfo->CacheFileNameLength == 0)
629 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
630 AFS_TRACE_LEVEL_ERROR,
631 "AFSInitializeRedirector CacheMdl == NULL\n"));
633 try_return( ntStatus = STATUS_INVALID_PARAMETER);
637 // Go open the cache file
640 pDevExt->Specific.RDR.CacheFile.Length = 0;
641 pDevExt->Specific.RDR.CacheFile.MaximumLength = (USHORT)RedirInitInfo->CacheFileNameLength + (4 * sizeof( WCHAR));
643 pDevExt->Specific.RDR.CacheFile.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
644 pDevExt->Specific.RDR.CacheFile.MaximumLength,
645 AFS_GENERIC_MEMORY_24_TAG);
647 if( pDevExt->Specific.RDR.CacheFile.Buffer == NULL)
650 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
651 AFS_TRACE_LEVEL_ERROR,
652 "AFSInitializeRedirector AFS_GENERIC_MEMORY_24_TAG allocation failure\n"));
654 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
657 RtlCopyMemory( pDevExt->Specific.RDR.CacheFile.Buffer,
661 pDevExt->Specific.RDR.CacheFile.Length = 4 * sizeof( WCHAR);
663 RtlCopyMemory( &pDevExt->Specific.RDR.CacheFile.Buffer[ pDevExt->Specific.RDR.CacheFile.Length/sizeof( WCHAR)],
664 RedirInitInfo->CacheFileName,
665 RedirInitInfo->CacheFileNameLength);
667 pDevExt->Specific.RDR.CacheFile.Length += (USHORT)RedirInitInfo->CacheFileNameLength;
669 InitializeObjectAttributes( &stObjectAttribs,
670 &pDevExt->Specific.RDR.CacheFile,
671 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
675 ntStatus = ZwOpenFile( &pDevExt->Specific.RDR.CacheFileHandle,
676 GENERIC_READ | GENERIC_WRITE,
679 FILE_SHARE_READ | FILE_SHARE_WRITE,
680 FILE_WRITE_THROUGH | FILE_RANDOM_ACCESS);
682 if( !NT_SUCCESS( ntStatus))
685 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
686 AFS_TRACE_LEVEL_ERROR,
687 "AFSInitializeRedirector ZwOpenFile failure %08lX\n",
690 try_return( ntStatus);
694 // Map to the fileobject
697 ntStatus = ObReferenceObjectByHandle( pDevExt->Specific.RDR.CacheFileHandle,
701 (void **)&pDevExt->Specific.RDR.CacheFileObject,
704 if( !NT_SUCCESS( ntStatus))
707 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
708 AFS_TRACE_LEVEL_ERROR,
709 "AFSInitializeRedirector ObReferenceObjectByHandle failure %08lX\n",
712 try_return( ntStatus);
717 pDevExt->Specific.RDR.MaxLinkCount = RedirInitInfo->MaxPathLinkCount;
719 pDevExt->Specific.RDR.NameArrayLength = RedirInitInfo->NameArrayLength;
722 // Intialize the library
725 ntStatus = AFSInitializeLibrary( &RedirInitInfo->GlobalFileId,
728 if ( !NT_SUCCESS( ntStatus))
730 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
731 AFS_TRACE_LEVEL_ERROR,
732 "AFSInitializeRedirector AFSInitializeLibrary failure %08lX\n",
738 if( !NT_SUCCESS( ntStatus))
741 if( pDevExt->Specific.RDR.CacheMdl != NULL)
744 MmUnmapLockedPages( pDevExt->Specific.RDR.CacheBaseAddress,
745 pDevExt->Specific.RDR.CacheMdl);
747 MmUnlockPages( pDevExt->Specific.RDR.CacheMdl);
749 ExFreePool( pDevExt->Specific.RDR.CacheMdl);
751 pDevExt->Specific.RDR.CacheMdl = NULL;
752 pDevExt->Specific.RDR.CacheBaseAddress = NULL;
753 pDevExt->Specific.RDR.CacheLength.QuadPart = 0;
756 if( pDevExt->Specific.RDR.CacheFileHandle != NULL)
759 ZwClose( pDevExt->Specific.RDR.CacheFileHandle);
761 pDevExt->Specific.RDR.CacheFileHandle = NULL;
764 if( pDevExt->Specific.RDR.CacheFileObject != NULL)
767 ObDereferenceObject( pDevExt->Specific.RDR.CacheFileObject);
769 pDevExt->Specific.RDR.CacheFileObject = NULL;
772 if( pDevExt->Specific.RDR.CacheFile.Buffer != NULL)
775 ExFreePool( pDevExt->Specific.RDR.CacheFile.Buffer);
777 pDevExt->Specific.RDR.CacheFile.Buffer = NULL;
780 if( AFSDumpFileLocation.Buffer != NULL)
782 ExFreePool( AFSDumpFileLocation.Buffer);
784 AFSDumpFileLocation.Buffer = NULL;
787 if ( pDevExt->Fcb != NULL)
790 AFSRemoveRdrFcb( &pDevExt->Fcb);
795 AFSUnloadLibrary( TRUE);
806 NTSTATUS ntStatus = STATUS_SUCCESS;
807 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
813 // Unload the library first so we close off any accesses to the cache or underlying
817 AFSUnloadLibrary( TRUE);
820 // Close off the cache file or mapping
823 if( pDevExt->Specific.RDR.CacheMdl != NULL)
826 MmUnmapLockedPages( pDevExt->Specific.RDR.CacheBaseAddress,
827 pDevExt->Specific.RDR.CacheMdl);
829 MmUnlockPages( pDevExt->Specific.RDR.CacheMdl);
831 ExFreePool( pDevExt->Specific.RDR.CacheMdl);
833 pDevExt->Specific.RDR.CacheMdl = NULL;
834 pDevExt->Specific.RDR.CacheBaseAddress = NULL;
835 pDevExt->Specific.RDR.CacheLength.QuadPart = 0;
838 if( pDevExt->Specific.RDR.CacheFileHandle != NULL)
841 ZwClose( pDevExt->Specific.RDR.CacheFileHandle);
843 pDevExt->Specific.RDR.CacheFileHandle = NULL;
846 if( pDevExt->Specific.RDR.CacheFileObject != NULL)
849 ObDereferenceObject( pDevExt->Specific.RDR.CacheFileObject);
851 pDevExt->Specific.RDR.CacheFileObject = NULL;
854 if( pDevExt->Specific.RDR.CacheFile.Buffer != NULL)
857 ExFreePool( pDevExt->Specific.RDR.CacheFile.Buffer);
859 pDevExt->Specific.RDR.CacheFile.Buffer = NULL;
862 if( AFSDumpFileLocation.Buffer != NULL)
864 ExFreePool( AFSDumpFileLocation.Buffer);
866 AFSDumpFileLocation.Buffer = NULL;
869 if ( pDevExt->Fcb != NULL)
872 AFSRemoveRdrFcb( &pDevExt->Fcb);
883 // Function: AFSInitRdrFcb
887 // This function performs Redirector Fcb initialization
891 // A status is returned for the function
895 AFSInitRdrFcb( OUT AFSFcb **RdrFcb)
898 NTSTATUS ntStatus = STATUS_SUCCESS;
900 AFSNonPagedFcb *pNPFcb = NULL;
906 // Initialize the root fcb
909 pFcb = (AFSFcb *)AFSExAllocatePoolWithTag( PagedPool,
911 AFS_FCB_ALLOCATION_TAG);
916 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
917 AFS_TRACE_LEVEL_ERROR,
918 "AFSInitRdrFcb Failed to allocate the root fcb\n"));
920 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
926 pFcb->Header.NodeByteSize = sizeof( AFSFcb);
927 pFcb->Header.NodeTypeCode = AFS_REDIRECTOR_FCB;
929 pNPFcb = (AFSNonPagedFcb *)AFSExAllocatePoolWithTag( NonPagedPool,
930 sizeof( AFSNonPagedFcb),
931 AFS_FCB_NP_ALLOCATION_TAG);
936 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
937 AFS_TRACE_LEVEL_ERROR,
938 "AFSInitRdrFcb Failed to allocate the non-paged fcb\n"));
940 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
943 RtlZeroMemory( pNPFcb,
944 sizeof( AFSNonPagedFcb));
946 pNPFcb->Size = sizeof( AFSNonPagedFcb);
948 pNPFcb->Type = AFS_NON_PAGED_FCB;
951 // OK, initialize the entry
954 ExInitializeFastMutex( &pNPFcb->AdvancedHdrMutex);
956 FsRtlSetupAdvancedHeader( &pFcb->Header, &pNPFcb->AdvancedHdrMutex);
958 ExInitializeResourceLite( &pNPFcb->Resource);
960 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
961 AFS_TRACE_LEVEL_VERBOSE,
962 "AFSInitRootFcb Acquiring Fcb lock %p EXCL %08lX\n",
964 PsGetCurrentThread()));
966 ExInitializeResourceLite( &pNPFcb->PagingResource);
968 pFcb->Header.Resource = &pNPFcb->Resource;
970 pFcb->Header.PagingIoResource = &pNPFcb->PagingResource;
972 pFcb->NPFcb = pNPFcb;
974 if ( InterlockedCompareExchangePointer( (PVOID *)RdrFcb, pFcb, NULL) != NULL)
977 try_return( ntStatus = STATUS_REPARSE);
982 if( ntStatus != STATUS_SUCCESS)
988 AFSRemoveRdrFcb( &pFcb);
997 // Function: AFSRemoveRdrFcb
1001 // This function performs Redirector Fcb removal/deallocation
1009 AFSRemoveRdrFcb( IN OUT AFSFcb **RdrFcb)
1011 AFSFcb *pFcb = NULL;
1013 pFcb = (AFSFcb *) InterlockedCompareExchangePointer( (PVOID *)RdrFcb, NULL, (PVOID)(*RdrFcb));
1021 if( pFcb->NPFcb != NULL)
1028 ExDeleteResourceLite( &pFcb->NPFcb->Resource);
1030 ExDeleteResourceLite( &pFcb->NPFcb->PagingResource);
1033 // The non paged region
1036 AFSExFreePoolWithTag( pFcb->NPFcb, AFS_FCB_NP_ALLOCATION_TAG);
1040 // And the Fcb itself
1043 AFSExFreePoolWithTag( pFcb, AFS_FCB_ALLOCATION_TAG);