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;
55 RtlInitUnicodeString( &uniDeviceName,
58 RtlInitUnicodeString( &uniFsRtlRegisterUncProviderEx,
59 L"FsRtlRegisterUncProviderEx");
61 pFsRtlRegisterUncProviderEx = (FsRtlRegisterUncProviderEx_t)MmGetSystemRoutineAddress(&uniFsRtlRegisterUncProviderEx);
63 ntStatus = IoCreateDevice( AFSDriverObject,
64 sizeof( AFSDeviceExt),
65 pFsRtlRegisterUncProviderEx ? NULL : &uniDeviceName,
66 FILE_DEVICE_NETWORK_FILE_SYSTEM,
67 FILE_DEVICE_SECURE_OPEN | FILE_REMOTE_DEVICE,
71 if( !NT_SUCCESS( ntStatus))
74 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
75 AFS_TRACE_LEVEL_ERROR,
76 "AFSInitRDRDevice IoCreateDevice failure %08lX\n",
79 try_return( ntStatus);
82 pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
84 RtlZeroMemory( pDeviceExt,
85 sizeof( AFSDeviceExt));
88 // Initialize resources
91 pDeviceExt->Specific.RDR.VolumeTree.TreeLock = &pDeviceExt->Specific.RDR.VolumeTreeLock;
93 ExInitializeResourceLite( pDeviceExt->Specific.RDR.VolumeTree.TreeLock);
95 pDeviceExt->Specific.RDR.VolumeTree.TreeHead = NULL;
97 ExInitializeResourceLite( &pDeviceExt->Specific.RDR.VolumeListLock);
99 pDeviceExt->Specific.RDR.VolumeListHead = NULL;
101 pDeviceExt->Specific.RDR.VolumeListTail = NULL;
103 KeInitializeEvent( &pDeviceExt->Specific.RDR.QueuedReleaseExtentEvent,
107 ExInitializeResourceLite( &pDeviceExt->Specific.RDR.RootCellTreeLock);
109 pDeviceExt->Specific.RDR.RootCellTree.TreeLock = &pDeviceExt->Specific.RDR.RootCellTreeLock;
111 pDeviceExt->Specific.RDR.RootCellTree.TreeHead = NULL;
113 ExInitializeResourceLite( &pDeviceExt->Specific.RDR.ProviderListLock);
115 ntStatus = AFSInitRdrFcb( &pDeviceExt->Fcb);
117 if ( !NT_SUCCESS(ntStatus))
120 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
121 AFS_TRACE_LEVEL_ERROR,
122 "AFSInitRDRDevice AFSInitRdrFcb failure %08lX\n",
125 try_return( ntStatus);
129 // Clear the initializing bit
132 AFSRDRDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
135 // Increase the StackSize to support the extra stack frame required
136 // for use of IoCompletion routines.
139 AFSRDRDeviceObject->StackSize++;
142 // Register this device with MUP with FilterMgr if Vista or above
145 if( pFsRtlRegisterUncProviderEx)
148 ntStatus = pFsRtlRegisterUncProviderEx( &AFSMUPHandle,
152 if ( !NT_SUCCESS( ntStatus))
154 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
155 AFS_TRACE_LEVEL_ERROR,
156 "AFSInitRDRDevice FsRtlRegisterUncProvider failure %08lX\n",
163 ntStatus = FsRtlRegisterUncProvider( &AFSMUPHandle,
167 if ( NT_SUCCESS( ntStatus))
170 IoRegisterFileSystem( AFSRDRDeviceObject);
174 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
175 AFS_TRACE_LEVEL_ERROR,
176 "AFSInitRDRDevice FsRtlRegisterUncProvider failure %08lX\n",
182 // Good to go, all registered and ready to start receiving requests
187 if( !NT_SUCCESS( ntStatus))
191 // Delete our device and bail
194 ExDeleteResourceLite( pDeviceExt->Specific.RDR.VolumeTree.TreeLock);
196 ExDeleteResourceLite( &pDeviceExt->Specific.RDR.VolumeListLock);
198 ExDeleteResourceLite( &pDeviceExt->Specific.RDR.RootCellTreeLock);
200 ExDeleteResourceLite( &pDeviceExt->Specific.RDR.ProviderListLock);
202 IoDeleteDevice( AFSRDRDeviceObject);
204 AFSRDRDeviceObject = NULL;
206 try_return( ntStatus);
214 AFSRDRDeviceControl( IN PDEVICE_OBJECT DeviceObject,
217 UNREFERENCED_PARAMETER(DeviceObject);
219 NTSTATUS ntStatus = STATUS_SUCCESS;
220 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
221 BOOLEAN bCompleteIrp = TRUE;
226 switch( pIrpSp->Parameters.DeviceIoControl.IoControlCode)
229 case IOCTL_REDIR_QUERY_PATH:
232 QUERY_PATH_REQUEST *pPathRequest = (QUERY_PATH_REQUEST *)pIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
233 QUERY_PATH_RESPONSE *pPathResponse = (QUERY_PATH_RESPONSE *)Irp->UserBuffer;
234 UNICODE_STRING uniPathName;
236 ntStatus = STATUS_BAD_NETWORK_PATH;
238 uniPathName.Length = (USHORT)pPathRequest->PathNameLength;
239 uniPathName.MaximumLength = uniPathName.Length;
241 uniPathName.Buffer = pPathRequest->FilePathName;
243 if( uniPathName.Length >= AFSServerName.Length + sizeof( WCHAR))
246 USHORT usLength = uniPathName.Length;
248 uniPathName.Length = AFSServerName.Length;
251 // Skip over the first slash in the name
254 uniPathName.Buffer = &uniPathName.Buffer[ 1];
258 // Check to see if the first (or only) component
259 // of the path matches the server name
262 if( RtlCompareUnicodeString( &AFSServerName,
265 ( usLength == AFSServerName.Length + sizeof( WCHAR) ||
266 uniPathName.Buffer[ AFSServerName.Length / sizeof( WCHAR)] == '\\'))
269 ntStatus = STATUS_SUCCESS;
271 pPathResponse->LengthAccepted = AFSServerName.Length + sizeof( WCHAR);
278 case IOCTL_REDIR_QUERY_PATH_EX:
281 QUERY_PATH_REQUEST_EX *pPathRequest = (QUERY_PATH_REQUEST_EX *)pIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
282 QUERY_PATH_RESPONSE *pPathResponse = (QUERY_PATH_RESPONSE *)Irp->UserBuffer;
283 UNICODE_STRING uniPathName;
285 ntStatus = STATUS_BAD_NETWORK_PATH;
287 uniPathName.Length = pPathRequest->PathName.Length;
288 uniPathName.MaximumLength = uniPathName.Length;
290 uniPathName.Buffer = pPathRequest->PathName.Buffer;
292 if( uniPathName.Length >= AFSServerName.Length + sizeof( WCHAR))
295 USHORT usLength = uniPathName.Length;
297 uniPathName.Length = AFSServerName.Length;
300 // Skip over the first slash in the name
303 uniPathName.Buffer = &uniPathName.Buffer[ 1];
307 // Check to see if the first (or only) component
308 // of the path matches the server name
311 if( RtlCompareUnicodeString( &AFSServerName,
314 ( usLength == AFSServerName.Length + sizeof( WCHAR) ||
315 uniPathName.Buffer[ AFSServerName.Length / sizeof( WCHAR)] == '\\'))
318 ntStatus = STATUS_SUCCESS;
320 pPathResponse->LengthAccepted = AFSServerName.Length + sizeof( WCHAR);
329 ntStatus = STATUS_INVALID_DEVICE_REQUEST;
337 // Complete the request
340 AFSCompleteRequest( Irp,
349 AFSInitializeRedirector( IN AFSRedirectorInitInfo *RedirInitInfo)
352 NTSTATUS ntStatus = STATUS_SUCCESS;
353 LARGE_INTEGER cacheSizeBytes;
354 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
355 OBJECT_ATTRIBUTES stObjectAttribs;
356 IO_STATUS_BLOCK stIoStatus;
357 UNICODE_STRING uniServiceName;
363 // First this is to load the library
366 RtlInitUnicodeString( &uniServiceName,
367 AFS_REDIR_LIBRARY_SERVICE_ENTRY);
369 ntStatus = AFSLoadLibrary( 0,
372 if( !NT_SUCCESS( ntStatus))
375 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
376 AFS_TRACE_LEVEL_ERROR,
377 "AFSInitializeRedirector AFSLoadLibrary failure %08lX\n",
380 try_return( ntStatus);
384 // Save off the cache file information
387 pDevExt->Specific.RDR.CacheBlockSize = RedirInitInfo->CacheBlockSize;
389 pDevExt->Specific.RDR.CacheBlockCount = RedirInitInfo->ExtentCount;
391 pDevExt->Specific.RDR.MaximumRPCLength = RedirInitInfo->MaximumChunkLength;
393 cacheSizeBytes = RedirInitInfo->ExtentCount;
394 cacheSizeBytes.QuadPart *= RedirInitInfo->CacheBlockSize;
396 AFSDumpFileLocation.Length = 0;
398 AFSDumpFileLocation.MaximumLength = (USHORT)RedirInitInfo->DumpFileLocationLength + (4 * sizeof( WCHAR));
400 AFSDumpFileLocation.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
401 AFSDumpFileLocation.MaximumLength,
402 AFS_GENERIC_MEMORY_23_TAG);
404 if( AFSDumpFileLocation.Buffer == NULL)
407 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
408 AFS_TRACE_LEVEL_ERROR,
409 "AFSInitializeRedirector AFS_GENERIC_MEMORY_23_TAG allocation error\n"));
411 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
414 RtlCopyMemory( AFSDumpFileLocation.Buffer,
418 AFSDumpFileLocation.Length = 4 * sizeof( WCHAR);
420 RtlCopyMemory( &AFSDumpFileLocation.Buffer[ AFSDumpFileLocation.Length/sizeof( WCHAR)],
421 (void *)((char *)RedirInitInfo + RedirInitInfo->DumpFileLocationOffset),
422 RedirInitInfo->DumpFileLocationLength);
424 AFSDumpFileLocation.Length += (USHORT)RedirInitInfo->DumpFileLocationLength;
427 // Be sure the shutdown flag is not set
430 ClearFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN);
433 // Set up the Throttles.
435 // Max IO is 10% of the cache, or the value in the registry,
436 // with a minimum of 5Mb (and a maximum of 50% cache size)
441 // collect what the user
443 pDevExt->Specific.RDR.MaxIo.QuadPart = AFSMaxDirectIo;
444 pDevExt->Specific.RDR.MaxIo.QuadPart *= (1024 * 1024);
450 pDevExt->Specific.RDR.MaxIo.QuadPart = cacheSizeBytes.QuadPart / 2;
453 if (pDevExt->Specific.RDR.MaxIo.QuadPart < (5 * 1024 * 1204))
456 pDevExt->Specific.RDR.MaxIo.QuadPart = 5 * 1024 * 1204;
461 // For small cache configurations ...
464 if (pDevExt->Specific.RDR.MaxIo.QuadPart > cacheSizeBytes.QuadPart / 2)
467 pDevExt->Specific.RDR.MaxIo.QuadPart = cacheSizeBytes.QuadPart / 2;
471 // Maximum Dirty is 50% of the cache, or the value in the
472 // registry. No minimum, maximum of 90% of cache size.
477 pDevExt->Specific.RDR.MaxDirty.QuadPart = AFSMaxDirtyFile;
478 pDevExt->Specific.RDR.MaxDirty.QuadPart *= (1024 * 1024);
484 pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart/2;
488 cacheSizeBytes.QuadPart *= 9;
489 cacheSizeBytes.QuadPart = cacheSizeBytes.QuadPart / 10;
491 if (pDevExt->Specific.RDR.MaxDirty.QuadPart > cacheSizeBytes.QuadPart)
493 pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart;
497 // Store off any flags for the file system
500 if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_FLAG_HIDE_DOT_FILES))
504 // Hide files which begin with .
507 SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES);
510 if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_FLAG_DISABLE_SHORTNAMES))
514 // Hide files which begin with .
517 SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES);
521 // Global Reparse Point Policy
524 pDevExt->Specific.RDR.ReparsePointPolicy = RedirInitInfo->GlobalReparsePointPolicy;
527 // Are we performing direct to service IO?
530 if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_PERFORM_SERVICE_IO))
534 // Send IO requests directly to service
537 SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO);
542 if( RedirInitInfo->MemoryCacheOffset.QuadPart != 0 &&
543 RedirInitInfo->MemoryCacheLength.QuadPart != 0)
546 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
549 pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL,
550 (void *)RedirInitInfo->MemoryCacheOffset.QuadPart,
551 RedirInitInfo->MemoryCacheLength.QuadPart);
553 pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL,
554 (void *)RedirInitInfo->MemoryCacheOffset.LowPart,
555 RedirInitInfo->MemoryCacheLength.LowPart);
558 if( pDevExt->Specific.RDR.CacheMdl != NULL)
564 MmProbeAndLockPages( pDevExt->Specific.RDR.CacheMdl,
568 pDevExt->Specific.RDR.CacheBaseAddress = MmGetSystemAddressForMdlSafe( pDevExt->Specific.RDR.CacheMdl,
571 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
574 AFSDumpTraceFilesFnc();
576 IoFreeMdl( pDevExt->Specific.RDR.CacheMdl);
577 pDevExt->Specific.RDR.CacheMdl = NULL;
580 if( pDevExt->Specific.RDR.CacheMdl != NULL)
582 pDevExt->Specific.RDR.CacheLength = RedirInitInfo->MemoryCacheLength;
583 ntStatus = STATUS_SUCCESS;
589 if( !NT_SUCCESS( ntStatus) &&
590 RedirInitInfo->CacheFileNameLength == 0)
593 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
594 AFS_TRACE_LEVEL_ERROR,
595 "AFSInitializeRedirector Unable to initialize cache file %08lX\n",
598 try_return( ntStatus);
601 if( pDevExt->Specific.RDR.CacheMdl == NULL)
604 if( RedirInitInfo->CacheFileNameLength == 0)
607 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
608 AFS_TRACE_LEVEL_ERROR,
609 "AFSInitializeRedirector CacheMdl == NULL\n"));
611 try_return( ntStatus = STATUS_INVALID_PARAMETER);
615 // Go open the cache file
618 pDevExt->Specific.RDR.CacheFile.Length = 0;
619 pDevExt->Specific.RDR.CacheFile.MaximumLength = (USHORT)RedirInitInfo->CacheFileNameLength + (4 * sizeof( WCHAR));
621 pDevExt->Specific.RDR.CacheFile.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
622 pDevExt->Specific.RDR.CacheFile.MaximumLength,
623 AFS_GENERIC_MEMORY_24_TAG);
625 if( pDevExt->Specific.RDR.CacheFile.Buffer == NULL)
628 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
629 AFS_TRACE_LEVEL_ERROR,
630 "AFSInitializeRedirector AFS_GENERIC_MEMORY_24_TAG allocation failure\n"));
632 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
635 RtlCopyMemory( pDevExt->Specific.RDR.CacheFile.Buffer,
639 pDevExt->Specific.RDR.CacheFile.Length = 4 * sizeof( WCHAR);
641 RtlCopyMemory( &pDevExt->Specific.RDR.CacheFile.Buffer[ pDevExt->Specific.RDR.CacheFile.Length/sizeof( WCHAR)],
642 RedirInitInfo->CacheFileName,
643 RedirInitInfo->CacheFileNameLength);
645 pDevExt->Specific.RDR.CacheFile.Length += (USHORT)RedirInitInfo->CacheFileNameLength;
647 InitializeObjectAttributes( &stObjectAttribs,
648 &pDevExt->Specific.RDR.CacheFile,
649 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
653 ntStatus = ZwOpenFile( &pDevExt->Specific.RDR.CacheFileHandle,
654 GENERIC_READ | GENERIC_WRITE,
657 FILE_SHARE_READ | FILE_SHARE_WRITE,
658 FILE_WRITE_THROUGH | FILE_RANDOM_ACCESS);
660 if( !NT_SUCCESS( ntStatus))
663 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
664 AFS_TRACE_LEVEL_ERROR,
665 "AFSInitializeRedirector ZwOpenFile failure %08lX\n",
668 try_return( ntStatus);
672 // Map to the fileobject
675 ntStatus = ObReferenceObjectByHandle( pDevExt->Specific.RDR.CacheFileHandle,
679 (void **)&pDevExt->Specific.RDR.CacheFileObject,
682 if( !NT_SUCCESS( ntStatus))
685 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
686 AFS_TRACE_LEVEL_ERROR,
687 "AFSInitializeRedirector ObReferenceObjectByHandle failure %08lX\n",
690 try_return( ntStatus);
695 pDevExt->Specific.RDR.MaxLinkCount = RedirInitInfo->MaxPathLinkCount;
697 pDevExt->Specific.RDR.NameArrayLength = RedirInitInfo->NameArrayLength;
700 // Intialize the library
703 ntStatus = AFSInitializeLibrary( &RedirInitInfo->GlobalFileId,
706 if ( !NT_SUCCESS( ntStatus))
708 AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING,
709 AFS_TRACE_LEVEL_ERROR,
710 "AFSInitializeRedirector AFSInitializeLibrary failure %08lX\n",
716 if( !NT_SUCCESS( ntStatus))
719 if( pDevExt->Specific.RDR.CacheMdl != NULL)
722 MmUnmapLockedPages( pDevExt->Specific.RDR.CacheBaseAddress,
723 pDevExt->Specific.RDR.CacheMdl);
725 MmUnlockPages( pDevExt->Specific.RDR.CacheMdl);
727 ExFreePool( pDevExt->Specific.RDR.CacheMdl);
729 pDevExt->Specific.RDR.CacheMdl = NULL;
730 pDevExt->Specific.RDR.CacheBaseAddress = NULL;
731 pDevExt->Specific.RDR.CacheLength.QuadPart = 0;
734 if( pDevExt->Specific.RDR.CacheFileHandle != NULL)
737 ZwClose( pDevExt->Specific.RDR.CacheFileHandle);
739 pDevExt->Specific.RDR.CacheFileHandle = NULL;
742 if( pDevExt->Specific.RDR.CacheFileObject != NULL)
745 ObDereferenceObject( pDevExt->Specific.RDR.CacheFileObject);
747 pDevExt->Specific.RDR.CacheFileObject = NULL;
750 if( pDevExt->Specific.RDR.CacheFile.Buffer != NULL)
753 ExFreePool( pDevExt->Specific.RDR.CacheFile.Buffer);
755 pDevExt->Specific.RDR.CacheFile.Buffer = NULL;
758 if( AFSDumpFileLocation.Buffer != NULL)
760 ExFreePool( AFSDumpFileLocation.Buffer);
762 AFSDumpFileLocation.Buffer = NULL;
765 if ( pDevExt->Fcb != NULL)
768 AFSRemoveRdrFcb( &pDevExt->Fcb);
773 AFSUnloadLibrary( TRUE);
784 NTSTATUS ntStatus = STATUS_SUCCESS;
785 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
791 // Unload the library first so we close off any accesses to the cache or underlying
795 AFSUnloadLibrary( TRUE);
798 // Close off the cache file or mapping
801 if( pDevExt->Specific.RDR.CacheMdl != NULL)
804 MmUnmapLockedPages( pDevExt->Specific.RDR.CacheBaseAddress,
805 pDevExt->Specific.RDR.CacheMdl);
807 MmUnlockPages( pDevExt->Specific.RDR.CacheMdl);
809 ExFreePool( pDevExt->Specific.RDR.CacheMdl);
811 pDevExt->Specific.RDR.CacheMdl = NULL;
812 pDevExt->Specific.RDR.CacheBaseAddress = NULL;
813 pDevExt->Specific.RDR.CacheLength.QuadPart = 0;
816 if( pDevExt->Specific.RDR.CacheFileHandle != NULL)
819 ZwClose( pDevExt->Specific.RDR.CacheFileHandle);
821 pDevExt->Specific.RDR.CacheFileHandle = NULL;
824 if( pDevExt->Specific.RDR.CacheFileObject != NULL)
827 ObDereferenceObject( pDevExt->Specific.RDR.CacheFileObject);
829 pDevExt->Specific.RDR.CacheFileObject = NULL;
832 if( pDevExt->Specific.RDR.CacheFile.Buffer != NULL)
835 ExFreePool( pDevExt->Specific.RDR.CacheFile.Buffer);
837 pDevExt->Specific.RDR.CacheFile.Buffer = NULL;
840 if( AFSDumpFileLocation.Buffer != NULL)
842 ExFreePool( AFSDumpFileLocation.Buffer);
844 AFSDumpFileLocation.Buffer = NULL;
847 if ( pDevExt->Fcb != NULL)
850 AFSRemoveRdrFcb( &pDevExt->Fcb);
861 // Function: AFSInitRdrFcb
865 // This function performs Redirector Fcb initialization
869 // A status is returned for the function
873 AFSInitRdrFcb( OUT AFSFcb **RdrFcb)
876 NTSTATUS ntStatus = STATUS_SUCCESS;
878 AFSNonPagedFcb *pNPFcb = NULL;
884 // Initialize the root fcb
887 pFcb = (AFSFcb *)AFSExAllocatePoolWithTag( PagedPool,
889 AFS_FCB_ALLOCATION_TAG);
894 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
895 AFS_TRACE_LEVEL_ERROR,
896 "AFSInitRdrFcb Failed to allocate the root fcb\n"));
898 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
904 pFcb->Header.NodeByteSize = sizeof( AFSFcb);
905 pFcb->Header.NodeTypeCode = AFS_REDIRECTOR_FCB;
907 pNPFcb = (AFSNonPagedFcb *)AFSExAllocatePoolWithTag( NonPagedPool,
908 sizeof( AFSNonPagedFcb),
909 AFS_FCB_NP_ALLOCATION_TAG);
914 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
915 AFS_TRACE_LEVEL_ERROR,
916 "AFSInitRdrFcb Failed to allocate the non-paged fcb\n"));
918 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
921 RtlZeroMemory( pNPFcb,
922 sizeof( AFSNonPagedFcb));
924 pNPFcb->Size = sizeof( AFSNonPagedFcb);
926 pNPFcb->Type = AFS_NON_PAGED_FCB;
929 // OK, initialize the entry
932 ExInitializeFastMutex( &pNPFcb->AdvancedHdrMutex);
934 FsRtlSetupAdvancedHeader( &pFcb->Header, &pNPFcb->AdvancedHdrMutex);
936 ExInitializeResourceLite( &pNPFcb->Resource);
938 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
939 AFS_TRACE_LEVEL_VERBOSE,
940 "AFSInitRootFcb Acquiring Fcb lock %p EXCL %08lX\n",
942 PsGetCurrentThread()));
944 ExInitializeResourceLite( &pNPFcb->PagingResource);
946 pFcb->Header.Resource = &pNPFcb->Resource;
948 pFcb->Header.PagingIoResource = &pNPFcb->PagingResource;
950 pFcb->NPFcb = pNPFcb;
952 if ( InterlockedCompareExchangePointer( (PVOID *)RdrFcb, pFcb, NULL) != NULL)
955 try_return( ntStatus = STATUS_REPARSE);
960 if( ntStatus != STATUS_SUCCESS)
966 AFSRemoveRdrFcb( &pFcb);
975 // Function: AFSRemoveRdrFcb
979 // This function performs Redirector Fcb removal/deallocation
987 AFSRemoveRdrFcb( IN OUT AFSFcb **RdrFcb)
991 pFcb = (AFSFcb *) InterlockedCompareExchangePointer( (PVOID *)RdrFcb, NULL, (PVOID)(*RdrFcb));
999 if( pFcb->NPFcb != NULL)
1006 ExDeleteResourceLite( &pFcb->NPFcb->Resource);
1008 ExDeleteResourceLite( &pFcb->NPFcb->PagingResource);
1011 // The non paged region
1014 AFSExFreePoolWithTag( pFcb->NPFcb, AFS_FCB_NP_ALLOCATION_TAG);
1018 // And the Fcb itself
1021 AFSExFreePoolWithTag( pFcb, AFS_FCB_ALLOCATION_TAG);