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: AFSGeneric.cpp
39 #include "AFSCommon.h"
42 // Function: AFSExceptionFilter
46 // This function is the exception handler
50 // A status is returned for the function
54 AFSExceptionFilter( IN CHAR *FunctionString,
56 IN PEXCEPTION_POINTERS ExceptPtrs)
59 PEXCEPTION_RECORD ExceptRec;
65 ExceptRec = ExceptPtrs->ExceptionRecord;
67 Context = ExceptPtrs->ContextRecord;
71 "AFSExceptionFilter (Library) - EXR %p CXR %p Function %s Code %08lX Address %p Routine %p\n",
75 ExceptRec->ExceptionCode,
76 ExceptRec->ExceptionAddress,
77 (void *)AFSExceptionFilter);
79 DbgPrint("**** Exception Caught in AFS Redirector Library ****\n");
81 DbgPrint("\n\nPerform the following WnDbg Cmds:\n");
82 DbgPrint("\n\t.exr %p ; .cxr %p\n\n", ExceptRec, Context);
84 DbgPrint("**** Exception Complete from AFS Redirector Library ****\n");
86 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION))
89 KeBugCheck( (ULONG)-2);
97 __except( EXCEPTION_EXECUTE_HANDLER)
103 return EXCEPTION_EXECUTE_HANDLER;
107 // Function: AFSLibExAllocatePoolWithTag()
109 // Purpose: Allocate Pool Memory. If BugCheck Exception flag
110 // is configured on, then bugcheck the system if
111 // a memory allocation fails. The routine should be
112 // used for all memory allocations that are to be freed
113 // when the library is unloaded. Memory allocations that
114 // are to survive library unload and reload should be
115 // performed using AFSExAllocatePoolWithTag() which is
116 // provided by the AFS Framework.
119 // POOL_TYPE PoolType - Paged or NonPaged
120 // SIZE_T NumberOfBytes - requested allocation size
121 // ULONG Tag - Pool Allocation Tag to be applied for tracking
124 // void * - the memory allocation
128 AFSLibExAllocatePoolWithTag( IN POOL_TYPE PoolType,
129 IN SIZE_T NumberOfBytes,
133 void *pBuffer = NULL;
135 pBuffer = ExAllocatePoolWithTag( PoolType,
142 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION))
145 KeBugCheck( (ULONG)-2);
152 "AFSLibExAllocatePoolWithTag failure Type %08lX Size %08lX Tag %08lX %08lX\n",
156 PsGetCurrentThread());
166 // Function: AFSAcquireExcl()
168 // Purpose: Called to acquire a resource exclusive with optional wait
171 // PERESOURCE Resource - Resource to acquire
172 // BOOLEAN Wait - Whether to block
175 // BOOLEAN - Whether the mask was acquired
179 AFSAcquireExcl( IN PERESOURCE Resource,
183 BOOLEAN bStatus = FALSE;
186 // Normal kernel APCs must be disabled before calling
187 // ExAcquireResourceExclusiveLite. Otherwise a bugcheck occurs.
190 KeEnterCriticalRegion();
192 bStatus = ExAcquireResourceExclusiveLite( Resource,
198 KeLeaveCriticalRegion();
205 AFSAcquireSharedStarveExclusive( IN PERESOURCE Resource,
209 BOOLEAN bStatus = FALSE;
211 KeEnterCriticalRegion();
213 bStatus = ExAcquireSharedStarveExclusive( Resource,
219 KeLeaveCriticalRegion();
226 // Function: AFSAcquireShared()
228 // Purpose: Called to acquire a resource shared with optional wait
231 // PERESOURCE Resource - Resource to acquire
232 // BOOLEAN Wait - Whether to block
235 // BOOLEAN - Whether the mask was acquired
239 AFSAcquireShared( IN PERESOURCE Resource,
243 BOOLEAN bStatus = FALSE;
245 KeEnterCriticalRegion();
247 bStatus = ExAcquireResourceSharedLite( Resource,
253 KeLeaveCriticalRegion();
260 // Function: AFSReleaseResource()
262 // Purpose: Called to release a resource
265 // PERESOURCE Resource - Resource to release
272 AFSReleaseResource( IN PERESOURCE Resource)
275 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
276 AFS_TRACE_LEVEL_VERBOSE,
277 "AFSReleaseResource Releasing lock %08lX Thread %08lX\n",
279 PsGetCurrentThread());
281 ExReleaseResourceLite( Resource);
283 KeLeaveCriticalRegion();
289 AFSConvertToShared( IN PERESOURCE Resource)
292 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
293 AFS_TRACE_LEVEL_VERBOSE,
294 "AFSConvertToShared Converting lock %08lX Thread %08lX\n",
296 PsGetCurrentThread());
298 ExConvertExclusiveToSharedLite( Resource);
304 // Function: AFSCompleteRequest
308 // This function completes irps
312 // A status is returned for the function
316 AFSCompleteRequest( IN PIRP Irp,
320 Irp->IoStatus.Status = Status;
322 IoCompleteRequest( Irp,
329 // Function: AFSGenerateCRC
333 // Given a device and filename this function generates a CRC
337 // A status is returned for the function
341 AFSGenerateCRC( IN PUNICODE_STRING FileName,
342 IN BOOLEAN UpperCaseName)
346 NTSTATUS ntStatus = STATUS_SUCCESS;
348 ntStatus = RtlHashUnicodeString( FileName,
350 HASH_STRING_ALGORITHM_DEFAULT,
353 if( !NT_SUCCESS( ntStatus))
362 AFSLockSystemBuffer( IN PIRP Irp,
366 NTSTATUS Status = STATUS_SUCCESS;
367 void *pAddress = NULL;
369 if( Irp->MdlAddress != NULL)
372 pAddress = MmGetSystemAddressForMdlSafe( Irp->MdlAddress,
375 else if( Irp->AssociatedIrp.SystemBuffer != NULL)
378 pAddress = Irp->AssociatedIrp.SystemBuffer;
380 else if( Irp->UserBuffer != NULL)
383 Irp->MdlAddress = IoAllocateMdl( Irp->UserBuffer,
389 if( Irp->MdlAddress != NULL)
393 // Lock the new Mdl in memory.
398 PIO_STACK_LOCATION pIoStack;
399 pIoStack = IoGetCurrentIrpStackLocation( Irp);
402 MmProbeAndLockPages( Irp->MdlAddress, KernelMode,
403 (pIoStack->MajorFunction == IRP_MJ_READ) ? IoWriteAccess : IoReadAccess);
405 pAddress = MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority );
408 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
411 AFSDumpTraceFilesFnc();
413 IoFreeMdl( Irp->MdlAddress );
414 Irp->MdlAddress = NULL;
424 AFSLockUserBuffer( IN void *UserBuffer,
425 IN ULONG BufferLength,
429 NTSTATUS ntStatus = STATUS_SUCCESS;
430 void *pAddress = NULL;
436 pMdl = IoAllocateMdl( UserBuffer,
445 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
449 // Lock the new Mdl in memory.
455 MmProbeAndLockPages( pMdl,
459 pAddress = MmGetSystemAddressForMdlSafe( pMdl,
462 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
465 AFSDumpTraceFilesFnc();
487 AFSMapToService( IN PIRP Irp,
491 NTSTATUS ntStatus = STATUS_SUCCESS;
492 void *pMappedBuffer = NULL;
493 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
499 if( pDevExt->Specific.Control.ServiceProcess == NULL)
502 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
505 if( Irp->MdlAddress == NULL)
508 if( AFSLockSystemBuffer( Irp,
512 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
517 // Attach to the service process for mapping
520 KeStackAttachProcess( pDevExt->Specific.Control.ServiceProcess,
521 (PRKAPC_STATE)&stApcState);
523 pMappedBuffer = MmMapLockedPagesSpecifyCache( Irp->MdlAddress,
530 KeUnstackDetachProcess( (PRKAPC_STATE)&stApcState);
537 return pMappedBuffer;
541 AFSUnmapServiceMappedBuffer( IN void *MappedBuffer,
545 NTSTATUS ntStatus = STATUS_SUCCESS;
546 void *pMappedBuffer = NULL;
547 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
553 if( pDevExt->Specific.Control.ServiceProcess == NULL)
556 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
563 // Attach to the service process for mapping
566 KeStackAttachProcess( pDevExt->Specific.Control.ServiceProcess,
567 (PRKAPC_STATE)&stApcState);
569 MmUnmapLockedPages( MappedBuffer,
572 KeUnstackDetachProcess( (PRKAPC_STATE)&stApcState);
584 AFSInitializeLibraryDevice()
587 NTSTATUS ntStatus = STATUS_SUCCESS;
588 AFSDeviceExt *pDeviceExt = NULL;
593 pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
596 // The PIOCtl file name
599 RtlInitUnicodeString( &AFSPIOCtlName,
600 AFS_PIOCTL_FILE_INTERFACE_NAME);
603 // And the global root share name
606 RtlInitUnicodeString( &AFSGlobalRootName,
607 AFS_GLOBAL_ROOT_SHARE_NAME);
615 AFSRemoveLibraryDevice()
618 NTSTATUS ntStatus = STATUS_SUCCESS;
629 AFSDefaultDispatch( IN PDEVICE_OBJECT DeviceObject,
633 NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
634 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
636 AFSCompleteRequest( Irp,
643 AFSInitializeGlobalDirectoryEntries()
646 NTSTATUS ntStatus = STATUS_SUCCESS;
647 AFSDirectoryCB *pDirNode = NULL;
648 ULONG ulEntryLength = 0;
649 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
650 AFSObjectInfoCB *pObjectInfoCB = NULL;
651 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
658 // Initialize the global . entry
661 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
664 if( pObjectInfoCB == NULL)
667 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
668 AFS_TRACE_LEVEL_ERROR,
669 "AFSInitializeGlobalDirectory AFSAllocateObjectInfo failure %08lX\n",
672 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
675 lCount = AFSObjectInfoIncrement( pObjectInfoCB);
677 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
678 AFS_TRACE_LEVEL_VERBOSE,
679 "AFSInitializeGlobalDirectoryEntries Increment count on object %08lX Cnt %d\n",
683 ntStatus = STATUS_SUCCESS;
685 ulEntryLength = sizeof( AFSDirectoryCB) +
688 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
692 if( pDirNode == NULL)
695 AFSDeleteObjectInfo( pObjectInfoCB);
697 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
698 AFS_TRACE_LEVEL_ERROR,
699 "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_TAG allocation failure\n");
701 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
704 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
705 sizeof( AFSNonPagedDirectoryCB),
706 AFS_DIR_ENTRY_NP_TAG);
708 if( pNonPagedDirEntry == NULL)
711 ExFreePool( pDirNode);
713 AFSDeleteObjectInfo( pObjectInfoCB);
715 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
716 AFS_TRACE_LEVEL_ERROR,
717 "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_NP_TAG allocation failure\n");
719 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
722 RtlZeroMemory( pDirNode,
725 RtlZeroMemory( pNonPagedDirEntry,
726 sizeof( AFSNonPagedDirectoryCB));
728 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
730 pDirNode->NonPaged = pNonPagedDirEntry;
732 pDirNode->ObjectInformation = pObjectInfoCB;
738 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE | AFS_DIR_ENTRY_FAKE | AFS_DIR_ENTRY_VALID);
740 pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_DOT_INDEX;
743 // Setup the names in the entry
746 pDirNode->NameInformation.FileName.Length = sizeof( WCHAR);
748 pDirNode->NameInformation.FileName.MaximumLength = sizeof( WCHAR);
750 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
752 pDirNode->NameInformation.FileName.Buffer[ 0] = L'.';
755 // Populate the rest of the data
758 pObjectInfoCB->FileType = AFS_FILE_TYPE_DIRECTORY;
760 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
762 AFSGlobalDotDirEntry = pDirNode;
768 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
771 if( pObjectInfoCB == NULL)
774 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
775 AFS_TRACE_LEVEL_ERROR,
776 "AFSInitializeGlobalDirectory AFSAllocateObjectInfo (2) failure %08lX\n",
779 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
782 lCount = AFSObjectInfoIncrement( pObjectInfoCB);
784 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
785 AFS_TRACE_LEVEL_VERBOSE,
786 "AFSInitializeGlobalDirectoryEntries Increment count on object %08lX Cnt %d\n",
790 ntStatus = STATUS_SUCCESS;
792 ulEntryLength = sizeof( AFSDirectoryCB) +
793 ( 2 * sizeof( WCHAR));
795 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
799 if( pDirNode == NULL)
802 AFSDeleteObjectInfo( pObjectInfoCB);
804 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
807 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
808 sizeof( AFSNonPagedDirectoryCB),
809 AFS_DIR_ENTRY_NP_TAG);
811 if( pNonPagedDirEntry == NULL)
814 ExFreePool( pDirNode);
816 AFSDeleteObjectInfo( pObjectInfoCB);
818 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
821 RtlZeroMemory( pDirNode,
824 RtlZeroMemory( pNonPagedDirEntry,
825 sizeof( AFSNonPagedDirectoryCB));
827 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
829 pDirNode->NonPaged = pNonPagedDirEntry;
831 pDirNode->ObjectInformation = pObjectInfoCB;
837 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE | AFS_DIR_ENTRY_FAKE | AFS_DIR_ENTRY_VALID);
839 pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX;
842 // Setup the names in the entry
845 pDirNode->NameInformation.FileName.Length = 2 * sizeof( WCHAR);
847 pDirNode->NameInformation.FileName.MaximumLength = 2 * sizeof( WCHAR);
849 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
851 pDirNode->NameInformation.FileName.Buffer[ 0] = L'.';
853 pDirNode->NameInformation.FileName.Buffer[ 1] = L'.';
856 // Populate the rest of the data
859 pObjectInfoCB->FileType = AFS_FILE_TYPE_DIRECTORY;
861 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
863 AFSGlobalDotDotDirEntry = pDirNode;
867 if( !NT_SUCCESS( ntStatus))
870 if( AFSGlobalDotDirEntry != NULL)
873 AFSDeleteObjectInfo( AFSGlobalDotDirEntry->ObjectInformation);
875 ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
877 ExFreePool( AFSGlobalDotDirEntry->NonPaged);
879 ExFreePool( AFSGlobalDotDirEntry);
881 AFSGlobalDotDirEntry = NULL;
884 if( AFSGlobalDotDotDirEntry != NULL)
887 AFSDeleteObjectInfo( AFSGlobalDotDotDirEntry->ObjectInformation);
889 ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
891 ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
893 ExFreePool( AFSGlobalDotDotDirEntry);
895 AFSGlobalDotDotDirEntry = NULL;
904 AFSInitDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
905 IN PUNICODE_STRING FileName,
906 IN PUNICODE_STRING TargetName,
907 IN AFSDirEnumEntry *DirEnumEntry,
911 AFSDirectoryCB *pDirNode = NULL;
912 NTSTATUS ntStatus = STATUS_SUCCESS;
913 ULONG ulEntryLength = 0;
914 AFSDirEnumEntry *pDirEnumCB = NULL;
915 AFSFileID stTargetFileID;
917 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
918 AFSObjectInfoCB *pObjectInfoCB = NULL;
919 BOOLEAN bAllocatedObjectCB = FALSE;
920 ULONGLONG ullIndex = 0;
921 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
927 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
928 AFS_TRACE_LEVEL_VERBOSE,
929 "AFSInitDirEntry Initializing entry %wZ parent FID %08lX-%08lX-%08lX-%08lX\n",
931 ParentObjectInfo->FileId.Cell,
932 ParentObjectInfo->FileId.Volume,
933 ParentObjectInfo->FileId.Vnode,
934 ParentObjectInfo->FileId.Unique);
937 // First thing is to locate/create our object information block
941 AFSAcquireExcl( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
944 ullIndex = AFSCreateLowIndex( &DirEnumEntry->FileId);
946 ntStatus = AFSLocateHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
948 (AFSBTreeEntry **)&pObjectInfoCB);
950 if( !NT_SUCCESS( ntStatus) ||
951 pObjectInfoCB == NULL)
955 // Allocate our object info cb
958 pObjectInfoCB = AFSAllocateObjectInfo( ParentObjectInfo,
961 if( pObjectInfoCB == NULL)
964 AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
966 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
969 bAllocatedObjectCB = TRUE;
971 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
972 AFS_TRACE_LEVEL_VERBOSE,
973 "AFSInitDirEntry initialized object %08lX Parent Object %08lX for %wZ\n",
979 lCount = AFSObjectInfoIncrement( pObjectInfoCB);
981 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
982 AFS_TRACE_LEVEL_VERBOSE,
983 "AFSInitDirEntry Increment count on object %08lX Cnt %d\n",
987 AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
989 ntStatus = STATUS_SUCCESS;
991 ulEntryLength = sizeof( AFSDirectoryCB) +
994 if( TargetName != NULL)
997 ulEntryLength += TargetName->Length;
1000 pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
1004 if( pDirNode == NULL)
1007 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1010 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
1011 sizeof( AFSNonPagedDirectoryCB),
1012 AFS_DIR_ENTRY_NP_TAG);
1014 if( pNonPagedDirEntry == NULL)
1017 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1020 RtlZeroMemory( pDirNode,
1023 RtlZeroMemory( pNonPagedDirEntry,
1024 sizeof( AFSNonPagedDirectoryCB));
1026 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
1028 pDirNode->NonPaged = pNonPagedDirEntry;
1030 pDirNode->ObjectInformation = pObjectInfoCB;
1033 // Set valid entry and NOT_IN_PARENT flag
1036 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1038 pDirNode->FileIndex = FileIndex;
1041 // Setup the names in the entry
1044 if( FileName->Length > 0)
1047 pDirNode->NameInformation.FileName.Length = FileName->Length;
1049 pDirNode->NameInformation.FileName.MaximumLength = FileName->Length;
1051 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
1053 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
1055 pDirNode->NameInformation.FileName.Length);
1058 // Create a CRC for the file
1061 pDirNode->CaseSensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1064 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1068 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1069 AFS_TRACE_LEVEL_VERBOSE,
1070 "AFSInitDirEntry Initialized DE %p for %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1073 ParentObjectInfo->FileId.Cell,
1074 ParentObjectInfo->FileId.Volume,
1075 ParentObjectInfo->FileId.Vnode,
1076 ParentObjectInfo->FileId.Unique);
1078 if( TargetName != NULL &&
1079 TargetName->Length > 0)
1082 pDirNode->NameInformation.TargetName.Length = TargetName->Length;
1084 pDirNode->NameInformation.TargetName.MaximumLength = pDirNode->NameInformation.TargetName.Length;
1086 pDirNode->NameInformation.TargetName.Buffer = (WCHAR *)((char *)pDirNode +
1087 sizeof( AFSDirectoryCB) +
1088 pDirNode->NameInformation.FileName.Length);
1090 RtlCopyMemory( pDirNode->NameInformation.TargetName.Buffer,
1092 pDirNode->NameInformation.TargetName.Length);
1096 // If we allocated the object information cb then update the information
1099 if( bAllocatedObjectCB)
1103 // Populate the rest of the data
1106 pObjectInfoCB->FileId = DirEnumEntry->FileId;
1108 pObjectInfoCB->TargetFileId = DirEnumEntry->TargetFileId;
1110 pObjectInfoCB->FileType = DirEnumEntry->FileType;
1112 pObjectInfoCB->CreationTime = DirEnumEntry->CreationTime;
1114 pObjectInfoCB->LastAccessTime = DirEnumEntry->LastAccessTime;
1116 pObjectInfoCB->LastWriteTime = DirEnumEntry->LastWriteTime;
1118 pObjectInfoCB->ChangeTime = DirEnumEntry->ChangeTime;
1120 pObjectInfoCB->EndOfFile = DirEnumEntry->EndOfFile;
1122 pObjectInfoCB->AllocationSize = DirEnumEntry->AllocationSize;
1124 pObjectInfoCB->FileAttributes = DirEnumEntry->FileAttributes;
1126 if( pObjectInfoCB->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1129 pObjectInfoCB->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1132 if (pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK ||
1133 pObjectInfoCB->FileType == AFS_FILE_TYPE_DFSLINK)
1136 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1139 pObjectInfoCB->EaSize = DirEnumEntry->EaSize;
1142 // Check for the case where we have a filetype of SymLink but both the TargetFid and the
1143 // TargetName are empty. In this case set the filetype to zero so we evaluate it later in
1147 if( pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK &&
1148 pObjectInfoCB->TargetFileId.Vnode == 0 &&
1149 pObjectInfoCB->TargetFileId.Unique == 0 &&
1150 pDirNode->NameInformation.TargetName.Length == 0)
1154 // This will ensure we perform a validation on the node
1157 pObjectInfoCB->FileType = AFS_FILE_TYPE_UNKNOWN;
1160 if( pObjectInfoCB->FileType == AFS_FILE_TYPE_UNKNOWN)
1163 SetFlag( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
1168 // Object specific information
1171 pObjectInfoCB->Links = DirEnumEntry->Links;
1173 pObjectInfoCB->Expiration = DirEnumEntry->Expiration;
1175 pObjectInfoCB->DataVersion = DirEnumEntry->DataVersion;
1179 if( !NT_SUCCESS( ntStatus))
1182 if( pNonPagedDirEntry != NULL)
1185 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
1187 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
1190 if( pDirNode != NULL)
1193 AFSExFreePoolWithTag( pDirNode, AFS_DIR_ENTRY_TAG);
1199 // Dereference our object info block if we have one
1202 if( pObjectInfoCB != NULL)
1205 lCount = AFSObjectInfoDecrement( pObjectInfoCB);
1207 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1208 AFS_TRACE_LEVEL_VERBOSE,
1209 "AFSInitDirEntry Decrement count on object %08lX Cnt %d\n",
1213 if( bAllocatedObjectCB)
1216 ASSERT( pObjectInfoCB->ObjectReferenceCount == 0);
1218 AFSDeleteObjectInfo( pObjectInfoCB);
1228 AFSCheckForReadOnlyAccess( IN ACCESS_MASK DesiredAccess,
1229 IN BOOLEAN DirectoryEntry)
1232 BOOLEAN bReturn = TRUE;
1233 ACCESS_MASK stAccessMask = 0;
1236 // Get rid of anything we don't know about
1239 DesiredAccess = (DesiredAccess &
1245 ACCESS_SYSTEM_SECURITY |
1249 FILE_READ_ATTRIBUTES |
1250 FILE_WRITE_ATTRIBUTES |
1251 FILE_LIST_DIRECTORY |
1257 // Our 'read only' access mask. These are the accesses we will
1258 // allow for a read only file
1261 stAccessMask = DELETE |
1266 ACCESS_SYSTEM_SECURITY |
1270 FILE_READ_ATTRIBUTES |
1271 FILE_WRITE_ATTRIBUTES |
1273 FILE_LIST_DIRECTORY |
1277 // For a directory, add in the directory specific accesses
1283 stAccessMask |= FILE_ADD_SUBDIRECTORY |
1288 if( FlagOn( DesiredAccess, ~stAccessMask))
1292 // A write access is set ...
1302 AFSEvaluateNode( IN GUID *AuthGroup,
1303 IN AFSDirectoryCB *DirEntry)
1306 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1307 NTSTATUS ntStatus = STATUS_SUCCESS;
1308 AFSDirEnumEntry *pDirEntry = NULL;
1309 UNICODE_STRING uniTargetName;
1314 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1319 if( !NT_SUCCESS( ntStatus))
1322 try_return( ntStatus);
1325 DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1327 DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1329 DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1331 DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1333 DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1335 DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1337 DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1339 DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1341 DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1343 DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1345 DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1347 if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1350 DirEntry->ObjectInformation->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1353 if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK ||
1354 pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1357 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1360 DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1362 DirEntry->ObjectInformation->Links = pDirEntry->Links;
1365 // If we have a target name then see if it needs updating ...
1368 if( pDirEntry->TargetNameLength > 0)
1372 // Update the target name information if needed
1375 uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1377 uniTargetName.MaximumLength = uniTargetName.Length;
1379 uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1381 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1384 if( DirEntry->NameInformation.TargetName.Length == 0 ||
1385 RtlCompareUnicodeString( &uniTargetName,
1386 &DirEntry->NameInformation.TargetName,
1391 // Update the target name
1394 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1396 uniTargetName.Buffer,
1397 uniTargetName.Length);
1399 if( !NT_SUCCESS( ntStatus))
1402 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1404 try_return( ntStatus);
1408 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1413 if( pDirEntry != NULL)
1416 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
1424 AFSValidateSymLink( IN GUID *AuthGroup,
1425 IN AFSDirectoryCB *DirEntry)
1428 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1429 NTSTATUS ntStatus = STATUS_SUCCESS;
1430 AFSDirEnumEntry *pDirEntry = NULL;
1431 UNICODE_STRING uniTargetName;
1436 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1441 if( !NT_SUCCESS( ntStatus))
1444 try_return( ntStatus);
1447 if( pDirEntry->FileType == AFS_FILE_TYPE_UNKNOWN ||
1448 pDirEntry->FileType == AFS_FILE_TYPE_INVALID)
1451 try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
1454 DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1456 DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1458 DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1461 // Update the target name information if needed
1464 uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1466 uniTargetName.MaximumLength = uniTargetName.Length;
1468 uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1470 if( uniTargetName.Length > 0)
1473 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1476 if( DirEntry->NameInformation.TargetName.Length == 0 ||
1477 RtlCompareUnicodeString( &uniTargetName,
1478 &DirEntry->NameInformation.TargetName,
1483 // Update the target name
1486 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1488 uniTargetName.Buffer,
1489 uniTargetName.Length);
1491 if( !NT_SUCCESS( ntStatus))
1494 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1496 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1500 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1504 // If the FileType is the same then nothing to do since it IS
1508 if( pDirEntry->FileType == DirEntry->ObjectInformation->FileType)
1511 ASSERT( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK);
1513 try_return( ntStatus = STATUS_SUCCESS);
1516 DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1518 DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1520 DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1522 DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1524 DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1526 DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1528 DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1530 DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1532 if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1535 DirEntry->ObjectInformation->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1538 if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK ||
1539 pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1542 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1545 DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1547 DirEntry->ObjectInformation->Links = pDirEntry->Links;
1551 if( pDirEntry != NULL)
1554 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
1562 AFSInvalidateObject( IN OUT AFSObjectInfoCB **ppObjectInfo,
1566 NTSTATUS ntStatus = STATUS_SUCCESS;
1567 IO_STATUS_BLOCK stIoStatus;
1570 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1571 AFS_TRACE_LEVEL_VERBOSE,
1572 "AFSInvalidateObject Invalidation on node type %d for fid %08lX-%08lX-%08lX-%08lX Reason %d\n",
1573 (*ppObjectInfo)->FileType,
1574 (*ppObjectInfo)->FileId.Cell,
1575 (*ppObjectInfo)->FileId.Volume,
1576 (*ppObjectInfo)->FileId.Vnode,
1577 (*ppObjectInfo)->FileId.Unique,
1580 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_SYMLINK ||
1581 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DFSLINK ||
1582 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1585 // We only act on the mount point itself, not the target. If the
1586 // node has been deleted then mark it as such otherwise indicate
1587 // it requires verification
1590 if( Reason == AFS_INVALIDATE_DELETED)
1592 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
1597 if( Reason == AFS_INVALIDATE_FLUSHED)
1600 (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1602 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1605 (*ppObjectInfo)->Expiration.QuadPart = 0;
1607 (*ppObjectInfo)->TargetFileId.Vnode = 0;
1609 (*ppObjectInfo)->TargetFileId.Unique = 0;
1611 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1612 AFS_TRACE_LEVEL_VERBOSE,
1613 "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1614 (*ppObjectInfo)->FileId.Cell,
1615 (*ppObjectInfo)->FileId.Volume,
1616 (*ppObjectInfo)->FileId.Vnode,
1617 (*ppObjectInfo)->FileId.Unique);
1619 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1622 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1624 if( Reason == AFS_INVALIDATE_CREDS)
1626 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1629 if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1630 Reason == AFS_INVALIDATE_FLUSHED)
1632 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1636 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1639 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
1642 FILE_ACTION_MODIFIED);
1644 try_return( ntStatus);
1648 // Depending on the reason for invalidation then perform work on the node
1654 case AFS_INVALIDATE_DELETED:
1658 // Mark this node as invalid
1661 (*ppObjectInfo)->Links = 0;
1663 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_DELETED);
1665 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1666 AFS_TRACE_LEVEL_VERBOSE,
1667 "AFSInvalidateObject Set DELETE flag on fid %08lX-%08lX-%08lX-%08lX\n",
1668 (*ppObjectInfo)->FileId.Cell,
1669 (*ppObjectInfo)->FileId.Volume,
1670 (*ppObjectInfo)->FileId.Vnode,
1671 (*ppObjectInfo)->FileId.Unique);
1673 if( (*ppObjectInfo)->ParentObjectInformation != NULL)
1676 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1677 AFS_TRACE_LEVEL_VERBOSE,
1678 "AFSInvalidateObject Set VERIFY flag on parent fid %08lX-%08lX-%08lX-%08lX\n",
1679 (*ppObjectInfo)->ParentObjectInformation->FileId.Cell,
1680 (*ppObjectInfo)->ParentObjectInformation->FileId.Volume,
1681 (*ppObjectInfo)->ParentObjectInformation->FileId.Vnode,
1682 (*ppObjectInfo)->ParentObjectInformation->FileId.Unique);
1684 SetFlag( (*ppObjectInfo)->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1686 (*ppObjectInfo)->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1688 (*ppObjectInfo)->ParentObjectInformation->Expiration.QuadPart = 0;
1691 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1693 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1697 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1700 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
1703 FILE_ACTION_REMOVED);
1705 if( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1708 (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1714 case AFS_INVALIDATE_FLUSHED:
1717 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1718 (*ppObjectInfo)->Fcb != NULL)
1721 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1722 AFS_TRACE_LEVEL_VERBOSE,
1723 "AFSInvalidateObject Flush/purge file fid %08lX-%08lX-%08lX-%08lX\n",
1724 (*ppObjectInfo)->FileId.Cell,
1725 (*ppObjectInfo)->FileId.Volume,
1726 (*ppObjectInfo)->FileId.Vnode,
1727 (*ppObjectInfo)->FileId.Unique);
1729 AFSAcquireExcl( &(*ppObjectInfo)->Fcb->NPFcb->Resource,
1735 CcFlushCache( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1740 if( !NT_SUCCESS( stIoStatus.Status))
1743 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1744 AFS_TRACE_LEVEL_ERROR,
1745 "AFSInvalidateObject CcFlushCache failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1746 (*ppObjectInfo)->FileId.Cell,
1747 (*ppObjectInfo)->FileId.Volume,
1748 (*ppObjectInfo)->FileId.Vnode,
1749 (*ppObjectInfo)->FileId.Unique,
1751 stIoStatus.Information);
1753 ntStatus = stIoStatus.Status;
1757 if ( (*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
1760 if ( !CcPurgeCacheSection( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1766 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1767 AFS_TRACE_LEVEL_WARNING,
1768 "AFSInvalidateObject CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
1769 (*ppObjectInfo)->FileId.Cell,
1770 (*ppObjectInfo)->FileId.Volume,
1771 (*ppObjectInfo)->FileId.Vnode,
1772 (*ppObjectInfo)->FileId.Unique);
1774 SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1778 __except( EXCEPTION_EXECUTE_HANDLER)
1781 ntStatus = GetExceptionCode();
1785 "EXCEPTION - AFSInvalidateObject Cc FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
1786 (*ppObjectInfo)->FileId.Cell,
1787 (*ppObjectInfo)->FileId.Volume,
1788 (*ppObjectInfo)->FileId.Vnode,
1789 (*ppObjectInfo)->FileId.Unique,
1792 SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1795 AFSReleaseResource( &(*ppObjectInfo)->Fcb->NPFcb->Resource);
1798 // Clear out the extents
1799 // Get rid of them (note this involves waiting
1800 // for any writes or reads to the cache to complete)
1803 AFSTearDownFcbExtents( (*ppObjectInfo)->Fcb,
1807 (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1810 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE)
1813 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1814 AFS_TRACE_LEVEL_VERBOSE,
1815 "AFSInvalidateObject Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
1816 (*ppObjectInfo)->FileId.Cell,
1817 (*ppObjectInfo)->FileId.Volume,
1818 (*ppObjectInfo)->FileId.Vnode,
1819 (*ppObjectInfo)->FileId.Unique);
1821 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1824 // Fall through to the default processing
1830 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1832 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1836 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1839 if( Reason == AFS_INVALIDATE_CREDS)
1841 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1844 if( Reason == AFS_INVALIDATE_DATA_VERSION)
1846 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1850 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1853 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1856 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo),
1859 FILE_ACTION_MODIFIED);
1864 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
1867 FILE_ACTION_MODIFIED);
1871 // Indicate this node requires re-evaluation for the remaining reasons
1874 (*ppObjectInfo)->Expiration.QuadPart = 0;
1876 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1877 AFS_TRACE_LEVEL_VERBOSE,
1878 "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1879 (*ppObjectInfo)->FileId.Cell,
1880 (*ppObjectInfo)->FileId.Volume,
1881 (*ppObjectInfo)->FileId.Vnode,
1882 (*ppObjectInfo)->FileId.Unique);
1884 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1886 if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1887 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1888 ( Reason == AFS_INVALIDATE_CALLBACK ||
1889 Reason == AFS_INVALIDATE_EXPIRED))
1891 if ( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1892 AFS_INVALIDATE_DATA_VERSION)))
1895 (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1909 AFSInvalidateCache( IN AFSInvalidateCacheCB *InvalidateCB)
1912 NTSTATUS ntStatus = STATUS_SUCCESS;
1913 AFSFcb *pDcb = NULL, *pFcb = NULL, *pNextFcb = NULL;
1914 AFSVolumeCB *pVolumeCB = NULL;
1915 AFSFcb *pTargetDcb = NULL;
1916 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1917 AFSDirectoryCB *pCurrentDirEntry = NULL;
1918 BOOLEAN bIsChild = FALSE;
1919 ULONGLONG ullIndex = 0;
1920 AFSObjectInfoCB *pObjectInfo = NULL;
1926 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1927 AFS_TRACE_LEVEL_VERBOSE,
1928 "AFSInvalidateCache Invalidation FID %08lX-%08lX-%08lX-%08lX Type %d WholeVolume %d Reason %d\n",
1929 InvalidateCB->FileID.Cell,
1930 InvalidateCB->FileID.Volume,
1931 InvalidateCB->FileID.Vnode,
1932 InvalidateCB->FileID.Unique,
1933 InvalidateCB->FileType,
1934 InvalidateCB->WholeVolume,
1935 InvalidateCB->Reason);
1938 // Need to locate the Fcb for the directory to purge
1941 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1942 AFS_TRACE_LEVEL_VERBOSE,
1943 "AFSInvalidateCache Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1944 &pDevExt->Specific.RDR.VolumeTreeLock,
1945 PsGetCurrentThread());
1948 // Starve any exclusive waiters on this paticular call
1951 AFSAcquireSharedStarveExclusive( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1954 // Locate the volume node
1957 ullIndex = AFSCreateHighIndex( &InvalidateCB->FileID);
1959 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1961 (AFSBTreeEntry **)&pVolumeCB);
1963 if( pVolumeCB != NULL)
1966 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1968 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1969 AFS_TRACE_LEVEL_VERBOSE,
1970 "AFSInvalidateCache Increment count on volume %08lX Cnt %d\n",
1975 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1977 if( !NT_SUCCESS( ntStatus) ||
1981 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1982 AFS_TRACE_LEVEL_WARNING,
1983 "AFSInvalidateCache Invalidation FAILURE Unable to locate volume node FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1984 InvalidateCB->FileID.Cell,
1985 InvalidateCB->FileID.Volume,
1986 InvalidateCB->FileID.Vnode,
1987 InvalidateCB->FileID.Unique,
1990 try_return( ntStatus = STATUS_SUCCESS);
1994 // If this is a whole volume invalidation then go do it now
1997 if( InvalidateCB->WholeVolume)
2000 ntStatus = AFSInvalidateVolume( pVolumeCB,
2001 InvalidateCB->Reason);
2003 try_return( ntStatus);
2006 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2009 if ( AFSIsVolumeFID( &InvalidateCB->FileID))
2012 pObjectInfo = &pVolumeCB->ObjectInformation;
2017 ullIndex = AFSCreateLowIndex( &InvalidateCB->FileID);
2019 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2021 (AFSBTreeEntry **)&pObjectInfo);
2024 if( pObjectInfo != NULL)
2028 // Reference the node so it won't be torn down
2031 lCount = AFSObjectInfoIncrement( pObjectInfo);
2033 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2034 AFS_TRACE_LEVEL_VERBOSE,
2035 "AFSInvalidateCache Increment count on object %08lX Cnt %d\n",
2040 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2042 if( !NT_SUCCESS( ntStatus) ||
2043 pObjectInfo == NULL)
2046 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2047 AFS_TRACE_LEVEL_VERBOSE,
2048 "AFSInvalidateCache Invalidation FAILURE Unable to locate object FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2049 InvalidateCB->FileID.Cell,
2050 InvalidateCB->FileID.Volume,
2051 InvalidateCB->FileID.Vnode,
2052 InvalidateCB->FileID.Unique,
2055 try_return( ntStatus = STATUS_SUCCESS);
2058 AFSInvalidateObject( &pObjectInfo,
2059 InvalidateCB->Reason);
2063 if( pObjectInfo != NULL)
2066 lCount = AFSObjectInfoDecrement( pObjectInfo);
2068 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2069 AFS_TRACE_LEVEL_VERBOSE,
2070 "AFSInvalidateCache Decrement count on object %08lX Cnt %d\n",
2075 if ( pVolumeCB != NULL)
2078 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2080 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2081 AFS_TRACE_LEVEL_VERBOSE,
2082 "AFSInvalidateCache Decrement count on volume %08lX Cnt %d\n",
2092 AFSIsChildOfParent( IN AFSFcb *Dcb,
2096 BOOLEAN bIsChild = FALSE;
2097 AFSFcb *pCurrentFcb = Fcb;
2099 while( pCurrentFcb != NULL)
2102 if( pCurrentFcb->ObjectInformation->ParentObjectInformation == Dcb->ObjectInformation)
2110 pCurrentFcb = pCurrentFcb->ObjectInformation->ParentObjectInformation->Fcb;
2118 AFSCreateHighIndex( IN AFSFileID *FileID)
2121 ULONGLONG ullIndex = 0;
2123 ullIndex = (((ULONGLONG)FileID->Cell << 32) | FileID->Volume);
2130 AFSCreateLowIndex( IN AFSFileID *FileID)
2133 ULONGLONG ullIndex = 0;
2135 ullIndex = (((ULONGLONG)FileID->Vnode << 32) | FileID->Unique);
2141 AFSCheckAccess( IN ACCESS_MASK DesiredAccess,
2142 IN ACCESS_MASK GrantedAccess,
2143 IN BOOLEAN DirectoryEntry)
2146 BOOLEAN bAccessGranted = TRUE;
2149 // Check if we are asking for read/write and granted only read only
2150 // NOTE: There will be more checks here
2153 if( !AFSCheckForReadOnlyAccess( DesiredAccess,
2155 AFSCheckForReadOnlyAccess( GrantedAccess,
2159 bAccessGranted = FALSE;
2162 return bAccessGranted;
2166 AFSGetDriverStatus( IN AFSDriverStatusRespCB *DriverStatus)
2169 NTSTATUS ntStatus = STATUS_SUCCESS;
2170 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2176 DriverStatus->Status = AFS_DRIVER_STATUS_READY;
2178 if( AFSGlobalRoot == NULL)
2185 DriverStatus->Status = AFS_DRIVER_STATUS_NOT_READY;
2188 if( pControlDevExt->Specific.Control.CommServiceCB.IrpPoolControlFlag != POOL_ACTIVE)
2195 DriverStatus->Status = AFS_DRIVER_STATUS_NO_SERVICE;
2202 AFSSubstituteSysName( IN UNICODE_STRING *ComponentName,
2203 IN UNICODE_STRING *SubstituteName,
2204 IN ULONG StringIndex)
2207 NTSTATUS ntStatus = STATUS_SUCCESS;
2208 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2209 AFSSysNameCB *pSysName = NULL;
2210 ERESOURCE *pSysNameLock = NULL;
2213 UNICODE_STRING uniSysName;
2220 if( IoIs32bitProcess( NULL))
2223 pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2225 pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2230 pSysNameLock = &pControlDevExt->Specific.Control.SysName64ListLock;
2232 pSysName = pControlDevExt->Specific.Control.SysName64ListHead;
2236 pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2238 pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2242 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2243 AFS_TRACE_LEVEL_VERBOSE,
2244 "AFSSubstituteSysName Acquiring SysName lock %08lX SHARED %08lX\n",
2246 PsGetCurrentThread());
2248 AFSAcquireShared( pSysNameLock,
2252 // Find where we are in the list
2255 while( pSysName != NULL &&
2256 ulIndex < StringIndex)
2259 pSysName = pSysName->fLink;
2264 if( pSysName == NULL)
2267 try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
2270 RtlInitUnicodeString( &uniSysName,
2273 // If it is a full component of @SYS then just substitue the
2277 if( RtlCompareUnicodeString( &uniSysName,
2282 SubstituteName->Length = pSysName->SysName.Length;
2283 SubstituteName->MaximumLength = SubstituteName->Length;
2285 SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2286 SubstituteName->Length,
2287 AFS_SUBST_BUFFER_TAG);
2289 if( SubstituteName->Buffer == NULL)
2292 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2295 RtlCopyMemory( SubstituteName->Buffer,
2296 pSysName->SysName.Buffer,
2297 pSysName->SysName.Length);
2304 while( ComponentName->Buffer[ usIndex] != L'@')
2310 SubstituteName->Length = (usIndex * sizeof( WCHAR)) + pSysName->SysName.Length;
2311 SubstituteName->MaximumLength = SubstituteName->Length;
2313 SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2314 SubstituteName->Length,
2315 AFS_SUBST_BUFFER_TAG);
2317 if( SubstituteName->Buffer == NULL)
2320 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2323 RtlCopyMemory( SubstituteName->Buffer,
2324 ComponentName->Buffer,
2325 usIndex * sizeof( WCHAR));
2327 RtlCopyMemory( &SubstituteName->Buffer[ usIndex],
2328 pSysName->SysName.Buffer,
2329 pSysName->SysName.Length);
2334 AFSReleaseResource( pSysNameLock);
2341 AFSSubstituteNameInPath( IN OUT UNICODE_STRING *FullPathName,
2342 IN OUT UNICODE_STRING *ComponentName,
2343 IN UNICODE_STRING *SubstituteName,
2344 IN OUT UNICODE_STRING *RemainingPath,
2345 IN BOOLEAN FreePathName)
2348 NTSTATUS ntStatus = STATUS_SUCCESS;
2349 UNICODE_STRING uniPathName;
2350 USHORT usPrefixNameLen = 0;
2351 SHORT sNameLenDelta = 0;
2357 // If the passed in name can handle the additional length
2358 // then just moves things around
2361 sNameLenDelta = SubstituteName->Length - ComponentName->Length;
2363 usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2365 if( FullPathName->MaximumLength > FullPathName->Length + sNameLenDelta)
2368 if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2371 RtlMoveMemory( &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + SubstituteName->Length)/sizeof( WCHAR))],
2372 &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + ComponentName->Length)/sizeof( WCHAR))],
2373 FullPathName->Length - usPrefixNameLen*sizeof( WCHAR) - ComponentName->Length);
2376 RtlCopyMemory( &FullPathName->Buffer[ usPrefixNameLen],
2377 SubstituteName->Buffer,
2378 SubstituteName->Length);
2380 FullPathName->Length += sNameLenDelta;
2382 ComponentName->Length += sNameLenDelta;
2384 ComponentName->MaximumLength = ComponentName->Length;
2386 if ( RemainingPath->Buffer)
2389 RemainingPath->Buffer += sNameLenDelta/sizeof( WCHAR);
2392 try_return( ntStatus);
2396 // Need to re-allocate the buffer
2399 uniPathName.Length = FullPathName->Length -
2400 ComponentName->Length +
2401 SubstituteName->Length;
2403 uniPathName.MaximumLength = FullPathName->MaximumLength + PAGE_SIZE;
2405 uniPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2406 uniPathName.MaximumLength,
2407 AFS_NAME_BUFFER_FOUR_TAG);
2409 if( uniPathName.Buffer == NULL)
2412 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2415 usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2417 usPrefixNameLen *= sizeof( WCHAR);
2419 RtlZeroMemory( uniPathName.Buffer,
2420 uniPathName.MaximumLength);
2422 RtlCopyMemory( uniPathName.Buffer,
2423 FullPathName->Buffer,
2426 RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen/sizeof( WCHAR))],
2427 SubstituteName->Buffer,
2428 SubstituteName->Length);
2430 if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2433 RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen + SubstituteName->Length)/sizeof( WCHAR)],
2434 &FullPathName->Buffer[ (usPrefixNameLen + ComponentName->Length)/sizeof( WCHAR)],
2435 FullPathName->Length - usPrefixNameLen - ComponentName->Length);
2438 ComponentName->Buffer = uniPathName.Buffer + (ComponentName->Buffer - FullPathName->Buffer);
2440 ComponentName->Length += sNameLenDelta;
2442 ComponentName->MaximumLength = ComponentName->Length;
2444 if ( RemainingPath->Buffer)
2447 RemainingPath->Buffer = uniPathName.Buffer
2448 + (RemainingPath->Buffer - FullPathName->Buffer)
2449 + sNameLenDelta/sizeof( WCHAR);
2454 AFSExFreePoolWithTag( FullPathName->Buffer, 0);
2457 *FullPathName = uniPathName;
2468 AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
2472 NTSTATUS ntStatus = STATUS_SUCCESS;
2473 AFSObjectInfoCB *pCurrentObject = NULL;
2474 AFSObjectInfoCB *pNextObject = NULL;
2476 AFSFcb *pFcb = NULL;
2482 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2483 AFS_TRACE_LEVEL_VERBOSE,
2484 "AFSInvalidateVolume Invalidate volume fid %08lX-%08lX-%08lX-%08lX Reason %08lX\n",
2485 VolumeCB->ObjectInformation.FileId.Cell,
2486 VolumeCB->ObjectInformation.FileId.Volume,
2487 VolumeCB->ObjectInformation.FileId.Vnode,
2488 VolumeCB->ObjectInformation.FileId.Unique,
2492 // Depending on the reason for invalidation then perform work on the node
2498 case AFS_INVALIDATE_DELETED:
2502 // Mark this volume as invalid
2505 SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
2507 SetFlag( VolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE);
2514 // Invalidate the volume root directory
2517 pCurrentObject = &VolumeCB->ObjectInformation;
2519 if ( pCurrentObject )
2522 lCount = AFSObjectInfoIncrement( pCurrentObject);
2524 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2525 AFS_TRACE_LEVEL_VERBOSE,
2526 "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2530 AFSInvalidateObject( &pCurrentObject,
2533 if ( pCurrentObject)
2536 lCount = AFSObjectInfoDecrement( pCurrentObject);
2538 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2539 AFS_TRACE_LEVEL_VERBOSE,
2540 "AFSInvalidateVolumeObjects Decrement count on object %08lX Cnt %d\n",
2547 // Apply invalidation to all other volume objects
2550 AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2553 pCurrentObject = VolumeCB->ObjectInfoListHead;
2555 if ( pCurrentObject)
2559 // Reference the node so it won't be torn down
2562 lCount = AFSObjectInfoIncrement( pCurrentObject);
2564 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2565 AFS_TRACE_LEVEL_VERBOSE,
2566 "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2571 while( pCurrentObject != NULL)
2574 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2580 // Reference the node so it won't be torn down
2583 lCount = AFSObjectInfoIncrement( pNextObject);
2585 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2586 AFS_TRACE_LEVEL_VERBOSE,
2587 "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2592 AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2594 AFSInvalidateObject( &pCurrentObject,
2597 if ( pCurrentObject )
2600 lCount = AFSObjectInfoDecrement( pCurrentObject);
2602 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2603 AFS_TRACE_LEVEL_VERBOSE,
2604 "AFSInvalidateVolumeObjects Decrement count on object %08lX Cnt %d\n",
2609 AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2612 pCurrentObject = pNextObject;
2615 AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2622 AFSInvalidateAllVolumes( VOID)
2624 AFSVolumeCB *pVolumeCB = NULL;
2625 AFSVolumeCB *pNextVolumeCB = NULL;
2626 AFSDeviceExt *pRDRDeviceExt = NULL;
2629 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2631 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2632 AFS_TRACE_LEVEL_VERBOSE,
2633 "AFSInvalidateAllVolumes Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
2634 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2635 PsGetCurrentThread());
2637 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2640 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
2645 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2646 AFS_TRACE_LEVEL_VERBOSE,
2647 "AFSInvalidateAllVolumes Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
2648 pVolumeCB->ObjectInfoTree.TreeLock,
2649 PsGetCurrentThread());
2651 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2653 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2654 AFS_TRACE_LEVEL_VERBOSE,
2655 "AFSInvalidateAllVolumes Increment count on volume %08lX Cnt %d\n",
2660 while( pVolumeCB != NULL)
2663 pNextVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2668 lCount = InterlockedIncrement( &pNextVolumeCB->VolumeReferenceCount);
2670 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2671 AFS_TRACE_LEVEL_VERBOSE,
2672 "AFSInvalidateAllVolumes Increment count on volume %08lX Cnt %d\n",
2677 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2679 // do I need to hold the volume lock here?
2681 AFSInvalidateVolume( pVolumeCB, AFS_INVALIDATE_EXPIRED);
2683 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2686 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2688 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2689 AFS_TRACE_LEVEL_VERBOSE,
2690 "AFSInvalidateAllVolumes Decrement count on volume %08lX Cnt %d\n",
2694 pVolumeCB = pNextVolumeCB;
2697 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2701 AFSVerifyEntry( IN GUID *AuthGroup,
2702 IN AFSDirectoryCB *DirEntry)
2705 NTSTATUS ntStatus = STATUS_SUCCESS;
2706 AFSDirEnumEntry *pDirEnumEntry = NULL;
2707 AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
2708 IO_STATUS_BLOCK stIoStatus;
2713 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2714 AFS_TRACE_LEVEL_VERBOSE_2,
2715 "AFSVerifyEntry Verifying entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2716 &DirEntry->NameInformation.FileName,
2717 pObjectInfo->FileId.Cell,
2718 pObjectInfo->FileId.Volume,
2719 pObjectInfo->FileId.Vnode,
2720 pObjectInfo->FileId.Unique);
2722 ntStatus = AFSEvaluateTargetByID( pObjectInfo,
2727 if( !NT_SUCCESS( ntStatus))
2730 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2731 AFS_TRACE_LEVEL_ERROR,
2732 "AFSVerifyEntry Evaluate Target failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2733 &DirEntry->NameInformation.FileName,
2734 pObjectInfo->FileId.Cell,
2735 pObjectInfo->FileId.Volume,
2736 pObjectInfo->FileId.Vnode,
2737 pObjectInfo->FileId.Unique,
2740 try_return( ntStatus);
2744 // Check the data version of the file
2747 if( pObjectInfo->DataVersion.QuadPart == pDirEnumEntry->DataVersion.QuadPart)
2749 if ( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2752 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2753 AFS_TRACE_LEVEL_VERBOSE,
2754 "AFSVerifyEntry No DV change %I64X for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2755 pObjectInfo->DataVersion.QuadPart,
2756 &DirEntry->NameInformation.FileName,
2757 pObjectInfo->FileId.Cell,
2758 pObjectInfo->FileId.Volume,
2759 pObjectInfo->FileId.Vnode,
2760 pObjectInfo->FileId.Unique);
2763 // We are ok, just get out
2766 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2768 try_return( ntStatus = STATUS_SUCCESS);
2773 // New data version so we will need to process the node based on the type
2776 switch( pDirEnumEntry->FileType)
2779 case AFS_FILE_TYPE_MOUNTPOINT:
2783 // For a mount point we need to ensure the target is the same
2786 if( !AFSIsEqualFID( &pObjectInfo->TargetFileId,
2787 &pDirEnumEntry->TargetFileId))
2793 // Update the metadata for the entry
2796 ntStatus = AFSUpdateMetaData( DirEntry,
2799 if( NT_SUCCESS( ntStatus))
2802 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2808 case AFS_FILE_TYPE_SYMLINK:
2812 // Update the metadata for the entry
2815 ntStatus = AFSUpdateMetaData( DirEntry,
2818 if( NT_SUCCESS( ntStatus))
2821 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2827 case AFS_FILE_TYPE_FILE:
2829 FILE_OBJECT * pCCFileObject = NULL;
2830 BOOLEAN bPurgeExtents = FALSE;
2832 if ( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
2835 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2836 AFS_TRACE_LEVEL_VERBOSE,
2837 "AFSVerifyEntry DV Change %wZ FID %08lX-%08lX-%08lX-%08lX (%08lX != %08lX)\n",
2838 &DirEntry->NameInformation.FileName,
2839 pObjectInfo->FileId.Cell,
2840 pObjectInfo->FileId.Volume,
2841 pObjectInfo->FileId.Vnode,
2842 pObjectInfo->FileId.Unique,
2843 pObjectInfo->DataVersion.LowPart,
2844 pDirEnumEntry->DataVersion.LowPart
2847 bPurgeExtents = TRUE;
2850 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2853 bPurgeExtents = TRUE;
2855 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2856 AFS_TRACE_LEVEL_VERBOSE,
2857 "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2858 &DirEntry->NameInformation.FileName,
2859 pObjectInfo->FileId.Cell,
2860 pObjectInfo->FileId.Volume,
2861 pObjectInfo->FileId.Vnode,
2862 pObjectInfo->FileId.Unique);
2864 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
2867 if( pObjectInfo->Fcb != NULL)
2870 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2871 AFS_TRACE_LEVEL_VERBOSE,
2872 "AFSVerifyEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2873 &DirEntry->NameInformation.FileName,
2874 pObjectInfo->FileId.Cell,
2875 pObjectInfo->FileId.Volume,
2876 pObjectInfo->FileId.Vnode,
2877 pObjectInfo->FileId.Unique);
2879 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
2885 CcFlushCache( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2890 if( !NT_SUCCESS( stIoStatus.Status))
2893 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2894 AFS_TRACE_LEVEL_ERROR,
2895 "AFSVerifyEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
2896 &DirEntry->NameInformation.FileName,
2897 pObjectInfo->FileId.Cell,
2898 pObjectInfo->FileId.Volume,
2899 pObjectInfo->FileId.Vnode,
2900 pObjectInfo->FileId.Unique,
2902 stIoStatus.Information);
2904 ntStatus = stIoStatus.Status;
2907 if ( bPurgeExtents &&
2908 pObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
2911 if ( !CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2917 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2918 AFS_TRACE_LEVEL_WARNING,
2919 "AFSVerifyEntry CcPurgeCacheSection failure %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2920 &DirEntry->NameInformation.FileName,
2921 pObjectInfo->FileId.Cell,
2922 pObjectInfo->FileId.Volume,
2923 pObjectInfo->FileId.Vnode,
2924 pObjectInfo->FileId.Unique);
2926 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
2930 __except( EXCEPTION_EXECUTE_HANDLER)
2932 ntStatus = GetExceptionCode();
2936 "EXCEPTION - AFSVerifyEntry CcFlushCache or CcPurgeCacheSection %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2937 &DirEntry->NameInformation.FileName,
2938 pObjectInfo->FileId.Cell,
2939 pObjectInfo->FileId.Volume,
2940 pObjectInfo->FileId.Vnode,
2941 pObjectInfo->FileId.Unique,
2944 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
2947 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
2951 AFSFlushExtents( pObjectInfo->Fcb,
2956 // Reacquire the Fcb to purge the cache
2959 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2960 AFS_TRACE_LEVEL_VERBOSE,
2961 "AFSVerifyEntry Acquiring Fcb lock %08lX EXCL %08lX\n",
2962 &pObjectInfo->Fcb->NPFcb->Resource,
2963 PsGetCurrentThread());
2965 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
2969 // Update the metadata for the entry
2972 ntStatus = AFSUpdateMetaData( DirEntry,
2975 if( !NT_SUCCESS( ntStatus))
2978 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2979 AFS_TRACE_LEVEL_ERROR,
2980 "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
2981 &DirEntry->NameInformation.FileName,
2982 pObjectInfo->FileId.Cell,
2983 pObjectInfo->FileId.Volume,
2984 pObjectInfo->FileId.Vnode,
2985 pObjectInfo->FileId.Unique,
2992 // Update file sizes
2995 pObjectInfo->Fcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart;
2996 pObjectInfo->Fcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart;
2997 pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
2999 pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
3001 if ( pCCFileObject != NULL)
3003 CcSetFileSizes( pCCFileObject,
3004 (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
3007 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
3013 // Update the metadata for the entry
3016 ntStatus = AFSUpdateMetaData( DirEntry,
3019 if( !NT_SUCCESS( ntStatus))
3022 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3023 AFS_TRACE_LEVEL_ERROR,
3024 "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
3025 &DirEntry->NameInformation.FileName,
3026 pObjectInfo->FileId.Cell,
3027 pObjectInfo->FileId.Volume,
3028 pObjectInfo->FileId.Vnode,
3029 pObjectInfo->FileId.Unique,
3035 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3036 AFS_TRACE_LEVEL_WARNING,
3037 "AFSVerifyEntry Fcb NULL %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3038 &DirEntry->NameInformation.FileName,
3039 pObjectInfo->FileId.Cell,
3040 pObjectInfo->FileId.Volume,
3041 pObjectInfo->FileId.Vnode,
3042 pObjectInfo->FileId.Unique);
3045 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3050 case AFS_FILE_TYPE_DIRECTORY:
3053 AFSFcb *pCurrentFcb = NULL;
3054 AFSDirectoryCB *pCurrentDirEntry = NULL;
3057 // For a directory or root entry flush the content of
3058 // the directory enumeration.
3061 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3064 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3065 AFS_TRACE_LEVEL_VERBOSE_2,
3066 "AFSVerifyEntry Validating directory content for entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3067 &DirEntry->NameInformation.FileName,
3068 pObjectInfo->FileId.Cell,
3069 pObjectInfo->FileId.Volume,
3070 pObjectInfo->FileId.Vnode,
3071 pObjectInfo->FileId.Unique);
3073 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3076 ntStatus = AFSValidateDirectoryCache( pObjectInfo,
3079 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3081 if ( !NT_SUCCESS( ntStatus))
3084 try_return( ntStatus);
3089 // Update the metadata for the entry
3092 ntStatus = AFSUpdateMetaData( DirEntry,
3095 if( NT_SUCCESS( ntStatus))
3098 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3104 case AFS_FILE_TYPE_DFSLINK:
3107 UNICODE_STRING uniTargetName;
3110 // For a DFS link need to check the target name has not changed
3113 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
3115 uniTargetName.MaximumLength = uniTargetName.Length;
3117 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
3119 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3122 if( DirEntry->NameInformation.TargetName.Length == 0 ||
3123 RtlCompareUnicodeString( &uniTargetName,
3124 &DirEntry->NameInformation.TargetName,
3129 // Update the target name
3132 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3134 uniTargetName.Buffer,
3135 uniTargetName.Length);
3137 if( !NT_SUCCESS( ntStatus))
3140 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3146 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3149 // Update the metadata for the entry
3152 ntStatus = AFSUpdateMetaData( DirEntry,
3155 if( NT_SUCCESS( ntStatus))
3158 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3166 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3167 AFS_TRACE_LEVEL_WARNING,
3168 "AFSVerifyEntry Attempt to verify node of type %d %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3169 pObjectInfo->FileType,
3170 &DirEntry->NameInformation.FileName,
3171 pObjectInfo->FileId.Cell,
3172 pObjectInfo->FileId.Volume,
3173 pObjectInfo->FileId.Vnode,
3174 pObjectInfo->FileId.Unique);
3181 if( pDirEnumEntry != NULL)
3184 AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_2_TAG);
3192 AFSSetVolumeState( IN AFSVolumeStatusCB *VolumeStatus)
3195 NTSTATUS ntStatus = STATUS_SUCCESS;
3196 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
3197 ULONGLONG ullIndex = 0;
3198 AFSVolumeCB *pVolumeCB = NULL;
3199 AFSFcb *pFcb = NULL;
3200 AFSObjectInfoCB *pCurrentObject = NULL;
3206 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3207 AFS_TRACE_LEVEL_VERBOSE,
3208 "AFSSetVolumeState Marking volume state %d Volume Cell %08lX Volume %08lX\n",
3209 VolumeStatus->Online,
3210 VolumeStatus->FileID.Cell,
3211 VolumeStatus->FileID.Volume);
3214 // Need to locate the Fcb for the directory to purge
3217 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3218 AFS_TRACE_LEVEL_VERBOSE,
3219 "AFSSetVolumeState Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
3220 &pDevExt->Specific.RDR.VolumeTreeLock,
3221 PsGetCurrentThread());
3223 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
3226 // Locate the volume node
3229 ullIndex = AFSCreateHighIndex( &VolumeStatus->FileID);
3231 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
3233 (AFSBTreeEntry **)&pVolumeCB);
3235 if( pVolumeCB != NULL)
3238 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
3240 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3241 AFS_TRACE_LEVEL_VERBOSE,
3242 "AFSSetVolumeState Increment count on volume %08lX Cnt %d\n",
3246 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3249 // Set the volume state accordingly
3252 if( VolumeStatus->Online)
3255 InterlockedAnd( (LONG *)&(pVolumeCB->Flags), ~AFS_VOLUME_FLAGS_OFFLINE);
3260 InterlockedOr( (LONG *)&(pVolumeCB->Flags), AFS_VOLUME_FLAGS_OFFLINE);
3263 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
3266 pCurrentObject = pVolumeCB->ObjectInfoListHead;;
3268 while( pCurrentObject != NULL)
3271 if( VolumeStatus->Online)
3274 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
3276 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
3278 pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
3283 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
3286 pFcb = pCurrentObject->Fcb;
3289 !(VolumeStatus->Online) &&
3290 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
3293 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3294 AFS_TRACE_LEVEL_ERROR,
3295 "AFSSetVolumeState Marking volume offline and canceling extents Volume Cell %08lX Volume %08lX\n",
3296 VolumeStatus->FileID.Cell,
3297 VolumeStatus->FileID.Volume);
3300 // Clear out the extents
3303 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3304 AFS_TRACE_LEVEL_VERBOSE,
3305 "AFSSetVolumeState Acquiring Fcb extents lock %08lX EXCL %08lX\n",
3306 &pFcb->NPFcb->Specific.File.ExtentsResource,
3307 PsGetCurrentThread());
3309 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
3312 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
3314 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
3318 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3319 AFS_TRACE_LEVEL_VERBOSE,
3320 "AFSSetVolumeState Releasing Fcb extents lock %08lX EXCL %08lX\n",
3321 &pFcb->NPFcb->Specific.File.ExtentsResource,
3322 PsGetCurrentThread());
3324 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
3327 // And get rid of them (note this involves waiting
3328 // for any writes or reads to the cache to complete)
3331 AFSTearDownFcbExtents( pFcb,
3335 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
3338 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
3340 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
3342 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3343 AFS_TRACE_LEVEL_VERBOSE,
3344 "AFSSetVolumeState Decrement count on volume %08lX Cnt %d\n",
3351 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3359 AFSSetNetworkState( IN AFSNetworkStatusCB *NetworkStatus)
3362 NTSTATUS ntStatus = STATUS_SUCCESS;
3367 if( AFSGlobalRoot == NULL)
3370 try_return( ntStatus);
3373 AFSAcquireExcl( AFSGlobalRoot->VolumeLock,
3377 // Set the network state according to the information
3380 if( NetworkStatus->Online)
3383 ClearFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3388 SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3391 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3402 AFSValidateDirectoryCache( IN AFSObjectInfoCB *ObjectInfo,
3406 NTSTATUS ntStatus = STATUS_SUCCESS;
3407 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3408 BOOLEAN bAcquiredLock = FALSE;
3409 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
3410 AFSFcb *pFcb = NULL;
3415 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3416 AFS_TRACE_LEVEL_VERBOSE,
3417 "AFSValidateDirectoryCache Validating content for FID %08lX-%08lX-%08lX-%08lX\n",
3418 ObjectInfo->FileId.Cell,
3419 ObjectInfo->FileId.Volume,
3420 ObjectInfo->FileId.Vnode,
3421 ObjectInfo->FileId.Unique);
3423 if( !ExIsResourceAcquiredLite( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock))
3426 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3427 AFS_TRACE_LEVEL_VERBOSE,
3428 "AFSValidateDirectoryCache Acquiring DirectoryNodeHdr.TreeLock lock %08lX EXCL %08lX\n",
3429 ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3430 PsGetCurrentThread());
3432 AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3435 bAcquiredLock = TRUE;
3439 // Check for inconsistency between DirectoryNodeList and DirectoryNodeCount
3442 if ( ObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL &&
3443 ObjectInfo->Specific.Directory.DirectoryNodeCount > 0)
3446 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3447 AFS_TRACE_LEVEL_ERROR,
3448 "AFSValidateDirectoryCache Empty Node List but Non-Zero Node Count %08lX for dir FID %08lX-%08lX-%08lX-%08lX\n",
3449 ObjectInfo->Specific.Directory.DirectoryNodeCount,
3450 ObjectInfo->FileId.Cell,
3451 ObjectInfo->FileId.Volume,
3452 ObjectInfo->FileId.Vnode,
3453 ObjectInfo->FileId.Unique);
3457 // Reset the directory list information by clearing all valid entries
3460 pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3462 while( pCurrentDirEntry != NULL)
3465 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3467 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
3471 // If this entry has been deleted then process it here
3474 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
3475 pCurrentDirEntry->DirOpenReferenceCount <= 0)
3478 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3479 AFS_TRACE_LEVEL_VERBOSE,
3480 "AFSValidateDirectoryCache Deleting dir entry %p name %wZ\n",
3482 &pCurrentDirEntry->NameInformation.FileName);
3484 AFSDeleteDirEntry( ObjectInfo,
3490 ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID);
3492 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3493 AFS_TRACE_LEVEL_VERBOSE,
3494 "AFSValidateDirectoryCache Clear VALID flag on DE %p Reference count %08lX\n",
3496 pCurrentDirEntry->DirOpenReferenceCount);
3499 // We pull the short name from the parent tree since it could change below
3502 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
3505 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3506 AFS_TRACE_LEVEL_VERBOSE,
3507 "AFSValidateDirectoryCache Removing DE %p (%08lX) from shortname tree for %wZ\n",
3509 pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3510 &pCurrentDirEntry->NameInformation.FileName);
3512 AFSRemoveShortNameDirEntry( &ObjectInfo->Specific.Directory.ShortNameTree,
3515 ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3520 pCurrentDirEntry = pNextDirEntry;
3524 // Reget the directory contents
3527 ntStatus = AFSVerifyDirectoryContent( ObjectInfo,
3530 if ( !NT_SUCCESS( ntStatus))
3532 try_return( ntStatus);
3536 // Now start again and tear down any entries not valid
3539 pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3541 while( pCurrentDirEntry != NULL)
3544 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3546 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID))
3549 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3550 !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME) &&
3551 pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex > 0)
3554 if( ObjectInfo->Specific.Directory.ShortNameTree == NULL)
3557 ObjectInfo->Specific.Directory.ShortNameTree = pCurrentDirEntry;
3559 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3560 AFS_TRACE_LEVEL_VERBOSE,
3561 "AFSValidateDirectoryCache Insert DE %p to head of shortname tree for %wZ\n",
3563 &pCurrentDirEntry->NameInformation.FileName);
3565 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3570 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfo->Specific.Directory.ShortNameTree,
3573 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3574 AFS_TRACE_LEVEL_VERBOSE,
3575 "AFSValidateDirectoryCache Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
3577 pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3578 &pCurrentDirEntry->NameInformation.FileName);
3582 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3584 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3585 AFS_TRACE_LEVEL_VERBOSE,
3586 "AFSValidateDirectoryCache Insert DE %p to shortname tree for %wZ\n",
3588 &pCurrentDirEntry->NameInformation.FileName);
3593 pCurrentDirEntry = pNextDirEntry;
3598 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3599 AFS_TRACE_LEVEL_VERBOSE,
3600 "AFSValidateDirectoryCache Processing INVALID DE %p Reference count %08lX\n",
3602 pCurrentDirEntry->DirOpenReferenceCount);
3604 if( pCurrentDirEntry->DirOpenReferenceCount <= 0)
3607 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3608 AFS_TRACE_LEVEL_VERBOSE,
3609 "AFSValidateDirectoryCache Deleting dir entry %wZ from parent FID %08lX-%08lX-%08lX-%08lX\n",
3610 &pCurrentDirEntry->NameInformation.FileName,
3611 ObjectInfo->FileId.Cell,
3612 ObjectInfo->FileId.Volume,
3613 ObjectInfo->FileId.Vnode,
3614 ObjectInfo->FileId.Unique);
3616 AFSDeleteDirEntry( ObjectInfo,
3622 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3623 AFS_TRACE_LEVEL_VERBOSE,
3624 "AFSValidateDirectoryCache Setting dir entry %p Name %wZ DELETED in parent FID %08lX-%08lX-%08lX-%08lX\n",
3626 &pCurrentDirEntry->NameInformation.FileName,
3627 ObjectInfo->FileId.Cell,
3628 ObjectInfo->FileId.Volume,
3629 ObjectInfo->FileId.Vnode,
3630 ObjectInfo->FileId.Unique);
3632 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
3634 AFSRemoveNameEntry( ObjectInfo,
3638 pCurrentDirEntry = pNextDirEntry;
3642 if( !AFSValidateDirList( ObjectInfo))
3645 AFSPrint("AFSValidateDirectoryCache Invalid count ...\n");
3654 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3662 AFSIsVolumeFID( IN AFSFileID *FileID)
3665 BOOLEAN bIsVolume = FALSE;
3667 if( FileID->Vnode == 1 &&
3668 FileID->Unique == 1)
3678 AFSIsFinalNode( IN AFSFcb *Fcb)
3681 BOOLEAN bIsFinalNode = FALSE;
3683 if( Fcb->Header.NodeTypeCode == AFS_ROOT_FCB ||
3684 Fcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB ||
3685 Fcb->Header.NodeTypeCode == AFS_FILE_FCB ||
3686 Fcb->Header.NodeTypeCode == AFS_DFS_LINK_FCB ||
3687 Fcb->Header.NodeTypeCode == AFS_INVALID_FCB )
3690 bIsFinalNode = TRUE;
3695 ASSERT( Fcb->Header.NodeTypeCode == AFS_MOUNT_POINT_FCB ||
3696 Fcb->Header.NodeTypeCode == AFS_SYMBOLIC_LINK_FCB);
3699 return bIsFinalNode;
3703 AFSUpdateMetaData( IN AFSDirectoryCB *DirEntry,
3704 IN AFSDirEnumEntry *DirEnumEntry)
3707 NTSTATUS ntStatus = STATUS_SUCCESS;
3708 UNICODE_STRING uniTargetName;
3709 AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
3714 pObjectInfo->TargetFileId = DirEnumEntry->TargetFileId;
3716 pObjectInfo->Expiration = DirEnumEntry->Expiration;
3718 pObjectInfo->DataVersion = DirEnumEntry->DataVersion;
3720 pObjectInfo->FileType = DirEnumEntry->FileType;
3722 pObjectInfo->CreationTime = DirEnumEntry->CreationTime;
3724 pObjectInfo->LastAccessTime = DirEnumEntry->LastAccessTime;
3726 pObjectInfo->LastWriteTime = DirEnumEntry->LastWriteTime;
3728 pObjectInfo->ChangeTime = DirEnumEntry->ChangeTime;
3730 pObjectInfo->EndOfFile = DirEnumEntry->EndOfFile;
3732 pObjectInfo->AllocationSize = DirEnumEntry->AllocationSize;
3734 pObjectInfo->FileAttributes = DirEnumEntry->FileAttributes;
3736 if( pObjectInfo->FileType == AFS_FILE_TYPE_MOUNTPOINT)
3739 pObjectInfo->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
3742 if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK ||
3743 pObjectInfo->FileType == AFS_FILE_TYPE_DFSLINK)
3746 pObjectInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
3749 pObjectInfo->EaSize = DirEnumEntry->EaSize;
3751 pObjectInfo->Links = DirEnumEntry->Links;
3753 if( DirEnumEntry->TargetNameLength > 0 &&
3754 ( DirEntry->NameInformation.TargetName.Length != DirEnumEntry->TargetNameLength ||
3755 DirEntry->ObjectInformation->DataVersion.QuadPart != DirEnumEntry->DataVersion.QuadPart))
3759 // Update the target name information if needed
3762 uniTargetName.Length = (USHORT)DirEnumEntry->TargetNameLength;
3764 uniTargetName.MaximumLength = uniTargetName.Length;
3766 uniTargetName.Buffer = (WCHAR *)((char *)DirEnumEntry + DirEnumEntry->TargetNameOffset);
3768 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3771 if( DirEntry->NameInformation.TargetName.Length == 0 ||
3772 RtlCompareUnicodeString( &uniTargetName,
3773 &DirEntry->NameInformation.TargetName,
3778 // Update the target name
3781 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3783 uniTargetName.Buffer,
3784 uniTargetName.Length);
3786 if( !NT_SUCCESS( ntStatus))
3789 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3791 try_return( ntStatus);
3795 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3797 else if( DirEntry->NameInformation.TargetName.Length > 0 &&
3798 DirEntry->ObjectInformation->DataVersion.QuadPart != DirEnumEntry->DataVersion.QuadPart)
3801 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3804 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER) &&
3805 DirEntry->NameInformation.TargetName.Buffer != NULL)
3807 AFSExFreePoolWithTag( DirEntry->NameInformation.TargetName.Buffer, AFS_NAME_BUFFER_FIVE_TAG);
3810 ClearFlag( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER);
3812 DirEntry->NameInformation.TargetName.Length = 0;
3813 DirEntry->NameInformation.TargetName.MaximumLength = 0;
3814 DirEntry->NameInformation.TargetName.Buffer = NULL;
3816 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3828 AFSValidateEntry( IN AFSDirectoryCB *DirEntry,
3830 IN BOOLEAN FastCall,
3831 IN BOOLEAN bSafeToPurge)
3834 NTSTATUS ntStatus = STATUS_SUCCESS;
3835 LARGE_INTEGER liSystemTime;
3836 AFSDirEnumEntry *pDirEnumEntry = NULL;
3837 AFSFcb *pCurrentFcb = NULL;
3838 BOOLEAN bReleaseFcb = FALSE;
3839 AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
3845 // If we have an Fcb hanging off the directory entry then be sure to acquire the locks in the
3849 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3850 AFS_TRACE_LEVEL_VERBOSE_2,
3851 "AFSValidateEntry Validating entry %wZ FID %08lX-%08lX-%08lX-%08lX FastCall %u\n",
3852 &DirEntry->NameInformation.FileName,
3853 pObjectInfo->FileId.Cell,
3854 pObjectInfo->FileId.Volume,
3855 pObjectInfo->FileId.Vnode,
3856 pObjectInfo->FileId.Unique,
3860 // If this is a fake node then bail since the service knows nothing about it
3863 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_FAKE))
3866 try_return( ntStatus);
3870 // This routine ensures that the current entry is valid by:
3872 // 1) Checking that the expiration time is non-zero and after where we
3876 KeQuerySystemTime( &liSystemTime);
3878 if( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) &&
3879 !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
3880 !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA) &&
3881 pObjectInfo->Expiration.QuadPart >= liSystemTime.QuadPart)
3884 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3885 AFS_TRACE_LEVEL_VERBOSE_2,
3886 "AFSValidateEntry Directory entry %wZ FID %08lX-%08lX-%08lX-%08lX VALID\n",
3887 &DirEntry->NameInformation.FileName,
3888 pObjectInfo->FileId.Cell,
3889 pObjectInfo->FileId.Volume,
3890 pObjectInfo->FileId.Vnode,
3891 pObjectInfo->FileId.Unique);
3893 try_return( ntStatus);
3897 // This node requires updating
3900 ntStatus = AFSEvaluateTargetByID( pObjectInfo,
3905 if( !NT_SUCCESS( ntStatus))
3908 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3909 AFS_TRACE_LEVEL_ERROR,
3910 "AFSValidateEntry Failed to evaluate entry FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3912 &DirEntry->NameInformation.FileName,
3913 pObjectInfo->FileId.Cell,
3914 pObjectInfo->FileId.Volume,
3915 pObjectInfo->FileId.Vnode,
3916 pObjectInfo->FileId.Unique,
3920 // Failed validation of node so return access-denied
3923 try_return( ntStatus);
3926 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3927 AFS_TRACE_LEVEL_VERBOSE,
3928 "AFSValidateEntry Validating entry FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX DV %I64X returned DV %I64X FT %d\n",
3930 &DirEntry->NameInformation.FileName,
3931 pObjectInfo->FileId.Cell,
3932 pObjectInfo->FileId.Volume,
3933 pObjectInfo->FileId.Vnode,
3934 pObjectInfo->FileId.Unique,
3935 pObjectInfo->DataVersion.QuadPart,
3936 pDirEnumEntry->DataVersion.QuadPart,
3937 pDirEnumEntry->FileType);
3941 // Based on the file type, process the node
3944 switch( pDirEnumEntry->FileType)
3947 case AFS_FILE_TYPE_MOUNTPOINT:
3951 // Update the metadata for the entry
3954 ntStatus = AFSUpdateMetaData( DirEntry,
3957 if( NT_SUCCESS( ntStatus))
3960 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
3966 case AFS_FILE_TYPE_SYMLINK:
3967 case AFS_FILE_TYPE_DFSLINK:
3971 // Update the metadata for the entry
3974 ntStatus = AFSUpdateMetaData( DirEntry,
3977 if( NT_SUCCESS( ntStatus))
3980 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
3986 case AFS_FILE_TYPE_FILE:
3989 BOOLEAN bPurgeExtents = FALSE;
3992 // For a file where the data version has become invalid we need to
3993 // fail any current extent requests and purge the cache for the file
3994 // Can't hold the Fcb resource while doing this
3997 if( pObjectInfo->Fcb != NULL &&
3998 (pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart ||
3999 BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA)))
4002 pCurrentFcb = pObjectInfo->Fcb;
4004 if( !ExIsResourceAcquiredLite( &pCurrentFcb->NPFcb->Resource))
4007 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4008 AFS_TRACE_LEVEL_VERBOSE,
4009 "AFSValidateEntry Acquiring Fcb lock %08lX EXCL %08lX\n",
4010 &pCurrentFcb->NPFcb->Resource,
4011 PsGetCurrentThread());
4013 AFSAcquireExcl( &pCurrentFcb->NPFcb->Resource,
4019 if( pCurrentFcb != NULL)
4022 IO_STATUS_BLOCK stIoStatus;
4024 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4025 AFS_TRACE_LEVEL_VERBOSE_2,
4026 "AFSValidateEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4027 &DirEntry->NameInformation.FileName,
4028 pObjectInfo->FileId.Cell,
4029 pObjectInfo->FileId.Volume,
4030 pObjectInfo->FileId.Vnode,
4031 pObjectInfo->FileId.Unique);
4033 if ( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
4036 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4037 AFS_TRACE_LEVEL_VERBOSE,
4038 "AFSValidateEntry DV Change %wZ FID %08lX-%08lX-%08lX-%08lX (%08lX != %08lX)\n",
4039 &DirEntry->NameInformation.FileName,
4040 pObjectInfo->FileId.Cell,
4041 pObjectInfo->FileId.Volume,
4042 pObjectInfo->FileId.Vnode,
4043 pObjectInfo->FileId.Unique,
4044 pObjectInfo->DataVersion.LowPart,
4045 pDirEnumEntry->DataVersion.LowPart
4048 bPurgeExtents = TRUE;
4054 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
4056 bPurgeExtents = TRUE;
4058 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4059 AFS_TRACE_LEVEL_VERBOSE,
4060 "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4061 &DirEntry->NameInformation.FileName,
4062 pObjectInfo->FileId.Cell,
4063 pObjectInfo->FileId.Volume,
4064 pObjectInfo->FileId.Vnode,
4065 pObjectInfo->FileId.Unique);
4067 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
4073 CcFlushCache( &pCurrentFcb->NPFcb->SectionObjectPointers,
4078 if( !NT_SUCCESS( stIoStatus.Status))
4081 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
4082 AFS_TRACE_LEVEL_ERROR,
4083 "AFSValidateEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
4084 &DirEntry->NameInformation.FileName,
4085 pObjectInfo->FileId.Cell,
4086 pObjectInfo->FileId.Volume,
4087 pObjectInfo->FileId.Vnode,
4088 pObjectInfo->FileId.Unique,
4090 stIoStatus.Information);
4092 ntStatus = stIoStatus.Status;
4095 if ( bPurgeExtents &&
4096 pObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
4099 if ( !CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
4105 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
4106 AFS_TRACE_LEVEL_WARNING,
4107 "AFSValidateEntry CcPurgeCacheSection failure %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4108 &DirEntry->NameInformation.FileName,
4109 pObjectInfo->FileId.Cell,
4110 pObjectInfo->FileId.Volume,
4111 pObjectInfo->FileId.Vnode,
4112 pObjectInfo->FileId.Unique);
4114 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
4118 __except( EXCEPTION_EXECUTE_HANDLER)
4120 ntStatus = GetExceptionCode();
4124 "EXCEPTION - AFSValidateEntry CcFlushCache or CcPurgeCacheSection %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
4125 &DirEntry->NameInformation.FileName,
4126 pObjectInfo->FileId.Cell,
4127 pObjectInfo->FileId.Volume,
4128 pObjectInfo->FileId.Vnode,
4129 pObjectInfo->FileId.Unique,
4132 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
4141 SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
4146 AFSReleaseResource( &pCurrentFcb->NPFcb->Resource);
4148 bReleaseFcb = FALSE;
4150 if ( bPurgeExtents &&
4153 AFSFlushExtents( pCurrentFcb,
4160 // Update the metadata for the entry but only if it is safe to do so.
4161 // If it was determined that a data version change has occurred or
4162 // that a pending data verification was required, do not update the
4163 // ObjectInfo meta data or the FileObject size information. That
4164 // way it is consistent for the next time that the data is verified
4168 if ( !(bPurgeExtents && bSafeToPurge))
4171 ntStatus = AFSUpdateMetaData( DirEntry,
4174 if( !NT_SUCCESS( ntStatus))
4177 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4178 AFS_TRACE_LEVEL_ERROR,
4179 "AFSValidateEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
4180 &DirEntry->NameInformation.FileName,
4181 pObjectInfo->FileId.Cell,
4182 pObjectInfo->FileId.Volume,
4183 pObjectInfo->FileId.Vnode,
4184 pObjectInfo->FileId.Unique,
4190 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
4193 // Update file sizes
4196 if( pObjectInfo->Fcb != NULL)
4198 FILE_OBJECT *pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
4200 pObjectInfo->Fcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart;
4201 pObjectInfo->Fcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart;
4202 pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
4204 if ( pCCFileObject != NULL)
4206 CcSetFileSizes( pCCFileObject,
4207 (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
4214 case AFS_FILE_TYPE_DIRECTORY:
4217 AFSDirectoryCB *pCurrentDirEntry = NULL;
4219 if( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
4223 // For a directory or root entry flush the content of
4224 // the directory enumeration.
4227 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4228 AFS_TRACE_LEVEL_VERBOSE,
4229 "AFSValidateEntry Acquiring DirectoryNodeHdr.TreeLock lock %08lX EXCL %08lX\n",
4230 pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
4231 PsGetCurrentThread());
4233 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
4236 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4237 AFS_TRACE_LEVEL_VERBOSE_2,
4238 "AFSValidateEntry Validating directory content for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4239 &DirEntry->NameInformation.FileName,
4240 pObjectInfo->FileId.Cell,
4241 pObjectInfo->FileId.Volume,
4242 pObjectInfo->FileId.Vnode,
4243 pObjectInfo->FileId.Unique);
4245 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
4248 ntStatus = AFSValidateDirectoryCache( pObjectInfo,
4251 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
4254 if( !NT_SUCCESS( ntStatus))
4257 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4258 AFS_TRACE_LEVEL_ERROR,
4259 "AFSValidateEntry Failed to re-enumerate %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4260 &DirEntry->NameInformation.FileName,
4261 pObjectInfo->FileId.Cell,
4262 pObjectInfo->FileId.Volume,
4263 pObjectInfo->FileId.Vnode,
4264 pObjectInfo->FileId.Unique,
4272 // Update the metadata for the entry
4275 ntStatus = AFSUpdateMetaData( DirEntry,
4278 if( NT_SUCCESS( ntStatus))
4281 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
4289 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4290 AFS_TRACE_LEVEL_WARNING,
4291 "AFSValidateEntry Attempt to verify node of type %d FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4292 pObjectInfo->FileType,
4294 &DirEntry->NameInformation.FileName,
4295 pObjectInfo->FileId.Cell,
4296 pObjectInfo->FileId.Volume,
4297 pObjectInfo->FileId.Vnode,
4298 pObjectInfo->FileId.Unique);
4308 AFSReleaseResource( &pCurrentFcb->NPFcb->Resource);
4311 if( pDirEnumEntry != NULL)
4314 AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_2_TAG);
4322 AFSInitializeSpecialShareNameList()
4325 NTSTATUS ntStatus = STATUS_SUCCESS;
4326 AFSDirectoryCB *pDirNode = NULL, *pLastDirNode = NULL;
4327 AFSObjectInfoCB *pObjectInfoCB = NULL;
4328 UNICODE_STRING uniShareName;
4329 ULONG ulEntryLength = 0;
4330 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
4335 RtlInitUnicodeString( &uniShareName,
4338 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
4341 if( pObjectInfoCB == NULL)
4344 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4347 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4348 AFS_TRACE_LEVEL_VERBOSE,
4349 "AFSInitializeSpecialShareNameList (srvsvc) Initializing count (1) on object %08lX\n",
4352 pObjectInfoCB->ObjectReferenceCount = 1;
4354 pObjectInfoCB->FileType = AFS_FILE_TYPE_SPECIAL_SHARE_NAME;
4356 ulEntryLength = sizeof( AFSDirectoryCB) +
4357 uniShareName.Length;
4359 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
4363 if( pDirNode == NULL)
4366 AFSDeleteObjectInfo( pObjectInfoCB);
4368 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4371 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
4372 sizeof( AFSNonPagedDirectoryCB),
4373 AFS_DIR_ENTRY_NP_TAG);
4375 if( pNonPagedDirEntry == NULL)
4378 ExFreePool( pDirNode);
4380 AFSDeleteObjectInfo( pObjectInfoCB);
4382 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4385 RtlZeroMemory( pDirNode,
4388 RtlZeroMemory( pNonPagedDirEntry,
4389 sizeof( AFSNonPagedDirectoryCB));
4391 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
4393 pDirNode->NonPaged = pNonPagedDirEntry;
4395 pDirNode->ObjectInformation = pObjectInfoCB;
4401 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_PIPE_SERVICE);
4403 pDirNode->NameInformation.FileName.Length = uniShareName.Length;
4405 pDirNode->NameInformation.FileName.MaximumLength = uniShareName.Length;
4407 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
4409 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
4410 uniShareName.Buffer,
4411 pDirNode->NameInformation.FileName.Length);
4413 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
4416 AFSSpecialShareNames = pDirNode;
4418 pLastDirNode = pDirNode;
4421 RtlInitUnicodeString( &uniShareName,
4424 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
4427 if( pObjectInfoCB == NULL)
4430 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4433 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4434 AFS_TRACE_LEVEL_VERBOSE,
4435 "AFSInitializeSpecialShareNameList (ipc$) Initializing count (1) on object %08lX\n",
4438 pObjectInfoCB->ObjectReferenceCount = 1;
4440 pObjectInfoCB->FileType = AFS_FILE_TYPE_SPECIAL_SHARE_NAME;
4442 ulEntryLength = sizeof( AFSDirectoryCB) +
4443 uniShareName.Length;
4445 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
4449 if( pDirNode == NULL)
4452 AFSDeleteObjectInfo( pObjectInfoCB);
4454 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4457 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
4458 sizeof( AFSNonPagedDirectoryCB),
4459 AFS_DIR_ENTRY_NP_TAG);
4461 if( pNonPagedDirEntry == NULL)
4464 ExFreePool( pDirNode);
4466 AFSDeleteObjectInfo( pObjectInfoCB);
4468 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4471 RtlZeroMemory( pDirNode,
4474 RtlZeroMemory( pNonPagedDirEntry,
4475 sizeof( AFSNonPagedDirectoryCB));
4477 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
4479 pDirNode->NonPaged = pNonPagedDirEntry;
4481 pDirNode->ObjectInformation = pObjectInfoCB;
4487 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_IPC);
4489 pDirNode->NameInformation.FileName.Length = uniShareName.Length;
4491 pDirNode->NameInformation.FileName.MaximumLength = uniShareName.Length;
4493 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
4495 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
4496 uniShareName.Buffer,
4497 pDirNode->NameInformation.FileName.Length);
4499 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
4502 pLastDirNode->ListEntry.fLink = pDirNode;
4504 pDirNode->ListEntry.bLink = pLastDirNode;
4508 if( !NT_SUCCESS( ntStatus))
4511 if( AFSSpecialShareNames != NULL)
4514 pDirNode = AFSSpecialShareNames;
4516 while( pDirNode != NULL)
4519 pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
4521 AFSDeleteObjectInfo( pDirNode->ObjectInformation);
4523 ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
4525 ExFreePool( pDirNode->NonPaged);
4527 ExFreePool( pDirNode);
4529 pDirNode = pLastDirNode;
4532 AFSSpecialShareNames = NULL;
4541 AFSGetSpecialShareNameEntry( IN UNICODE_STRING *ShareName,
4542 IN UNICODE_STRING *SecondaryName)
4545 AFSDirectoryCB *pDirectoryCB = NULL;
4546 ULONGLONG ullHash = 0;
4547 UNICODE_STRING uniFullShareName;
4553 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4554 AFS_TRACE_LEVEL_VERBOSE_2,
4555 "AFSGetSpecialShareNameEntry share name %wZ secondary name %wZ\n",
4559 uniFullShareName = *ShareName;
4562 // Generate our hash value
4565 ullHash = AFSGenerateCRC( &uniFullShareName,
4569 // Loop through our special share names to see if this is one of them
4572 pDirectoryCB = AFSSpecialShareNames;
4574 while( pDirectoryCB != NULL)
4577 if( ullHash == pDirectoryCB->CaseInsensitiveTreeEntry.HashIndex)
4583 pDirectoryCB = (AFSDirectoryCB *)pDirectoryCB->ListEntry.fLink;
4587 return pDirectoryCB;
4591 AFSWaitOnQueuedFlushes( IN AFSFcb *Fcb)
4595 // Block on the queue flush event
4598 KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
4608 AFSWaitOnQueuedReleases()
4611 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
4614 // Block on the queue flush event
4617 KeWaitForSingleObject( &pRDRDeviceExt->Specific.RDR.QueuedReleaseExtentEvent,
4627 AFSIsEqualFID( IN AFSFileID *FileId1,
4628 IN AFSFileID *FileId2)
4631 BOOLEAN bIsEqual = FALSE;
4633 if( FileId1->Hash == FileId2->Hash &&
4634 FileId1->Unique == FileId2->Unique &&
4635 FileId1->Vnode == FileId2->Vnode &&
4636 FileId1->Volume == FileId2->Volume &&
4637 FileId1->Cell == FileId2->Cell)
4647 AFSResetDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB)
4650 NTSTATUS ntStatus = STATUS_SUCCESS;
4651 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
4656 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
4659 // Reset the directory list information
4662 pCurrentDirEntry = ObjectInfoCB->Specific.Directory.DirectoryNodeListHead;
4664 while( pCurrentDirEntry != NULL)
4667 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
4669 if( pCurrentDirEntry->DirOpenReferenceCount <= 0)
4672 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
4673 AFS_TRACE_LEVEL_VERBOSE,
4674 "AFSResetDirectoryContent Deleting dir entry %p for %wZ\n",
4676 &pCurrentDirEntry->NameInformation.FileName);
4678 AFSDeleteDirEntry( ObjectInfoCB,
4684 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
4685 AFS_TRACE_LEVEL_VERBOSE,
4686 "AFSResetDirectoryContent Setting DELETE flag in dir entry %p for %wZ\n",
4688 &pCurrentDirEntry->NameInformation.FileName);
4690 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
4692 AFSRemoveNameEntry( ObjectInfoCB,
4696 pCurrentDirEntry = pNextDirEntry;
4699 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = NULL;
4701 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = NULL;
4703 ObjectInfoCB->Specific.Directory.ShortNameTree = NULL;
4705 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = NULL;
4707 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = NULL;
4709 ObjectInfoCB->Specific.Directory.DirectoryNodeCount = 0;
4711 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
4712 AFS_TRACE_LEVEL_VERBOSE,
4713 "AFSResetDirectoryContent Reset count to 0 on parent FID %08lX-%08lX-%08lX-%08lX\n",
4714 ObjectInfoCB->FileId.Cell,
4715 ObjectInfoCB->FileId.Volume,
4716 ObjectInfoCB->FileId.Vnode,
4717 ObjectInfoCB->FileId.Unique);
4724 AFSEnumerateGlobalRoot( IN GUID *AuthGroup)
4727 NTSTATUS ntStatus = STATUS_SUCCESS;
4728 AFSDirectoryCB *pDirGlobalDirNode = NULL;
4729 UNICODE_STRING uniFullName;
4734 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4735 AFS_TRACE_LEVEL_VERBOSE,
4736 "AFSEnumerateGlobalRoot Acquiring GlobalRoot DirectoryNodeHdr.TreeLock lock %08lX EXCL %08lX\n",
4737 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4738 PsGetCurrentThread());
4740 AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4743 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
4746 try_return( ntStatus);
4750 // Initialize the root information
4753 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.ContentIndex = 1;
4756 // Enumerate the shares in the volume
4759 ntStatus = AFSEnumerateDirectory( AuthGroup,
4760 &AFSGlobalRoot->ObjectInformation,
4763 if( !NT_SUCCESS( ntStatus))
4766 try_return( ntStatus);
4769 pDirGlobalDirNode = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead;
4772 // Indicate the node is initialized
4775 SetFlag( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
4777 uniFullName.MaximumLength = PAGE_SIZE;
4778 uniFullName.Length = 0;
4780 uniFullName.Buffer = (WCHAR *)AFSLibExAllocatePoolWithTag( PagedPool,
4781 uniFullName.MaximumLength,
4782 AFS_GENERIC_MEMORY_12_TAG);
4784 if( uniFullName.Buffer == NULL)
4788 // Reset the directory content
4791 AFSResetDirectoryContent( &AFSGlobalRoot->ObjectInformation);
4793 ClearFlag( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
4795 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4799 // Populate our list of entries in the NP enumeration list
4802 while( pDirGlobalDirNode != NULL)
4805 uniFullName.Buffer[ 0] = L'\\';
4806 uniFullName.Buffer[ 1] = L'\\';
4808 uniFullName.Length = 2 * sizeof( WCHAR);
4810 RtlCopyMemory( &uniFullName.Buffer[ 2],
4811 AFSServerName.Buffer,
4812 AFSServerName.Length);
4814 uniFullName.Length += AFSServerName.Length;
4816 uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)] = L'\\';
4818 uniFullName.Length += sizeof( WCHAR);
4820 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
4821 pDirGlobalDirNode->NameInformation.FileName.Buffer,
4822 pDirGlobalDirNode->NameInformation.FileName.Length);
4824 uniFullName.Length += pDirGlobalDirNode->NameInformation.FileName.Length;
4826 AFSAddConnectionEx( &uniFullName,
4827 RESOURCEDISPLAYTYPE_SHARE,
4830 pDirGlobalDirNode = (AFSDirectoryCB *)pDirGlobalDirNode->ListEntry.fLink;
4833 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
4837 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4844 AFSIsRelativeName( IN UNICODE_STRING *Name)
4847 BOOLEAN bIsRelative = FALSE;
4849 if( Name->Length > 0 &&
4850 Name->Buffer[ 0] != L'\\')
4860 AFSIsAbsoluteAFSName( IN UNICODE_STRING *Name)
4862 UNICODE_STRING uniTempName;
4863 BOOLEAN bIsAbsolute = FALSE;
4866 // An absolute AFS path must begin with \afs\... or equivalent
4869 if ( Name->Length == 0 ||
4870 Name->Length <= AFSMountRootName.Length + sizeof( WCHAR) ||
4871 Name->Buffer[ 0] != L'\\' ||
4872 Name->Buffer[ AFSMountRootName.Length/sizeof( WCHAR)] != L'\\')
4878 uniTempName.Length = AFSMountRootName.Length;
4879 uniTempName.MaximumLength = AFSMountRootName.Length;
4881 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4882 uniTempName.MaximumLength,
4883 AFS_NAME_BUFFER_TWO_TAG);
4885 if( uniTempName.Buffer == NULL)
4891 RtlCopyMemory( uniTempName.Buffer,
4893 AFSMountRootName.Length);
4895 bIsAbsolute = (0 == RtlCompareUnicodeString( &uniTempName,
4899 AFSExFreePoolWithTag( uniTempName.Buffer,
4900 AFS_NAME_BUFFER_TWO_TAG);
4907 AFSUpdateName( IN UNICODE_STRING *Name)
4912 while( usIndex < Name->Length/sizeof( WCHAR))
4915 if( Name->Buffer[ usIndex] == L'/')
4918 Name->Buffer[ usIndex] = L'\\';
4928 AFSUpdateTargetName( IN OUT UNICODE_STRING *TargetName,
4929 IN OUT ULONG *Flags,
4930 IN WCHAR *NameBuffer,
4931 IN USHORT NameLength)
4934 NTSTATUS ntStatus = STATUS_SUCCESS;
4935 WCHAR *pTmpBuffer = NULL;
4941 // If we have enough space then just move in the name otherwise
4942 // allocate a new buffer
4945 if( TargetName->Length < NameLength)
4948 pTmpBuffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4950 AFS_NAME_BUFFER_FIVE_TAG);
4952 if( pTmpBuffer == NULL)
4955 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4958 if( BooleanFlagOn( *Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
4961 AFSExFreePoolWithTag( TargetName->Buffer, AFS_NAME_BUFFER_FIVE_TAG);
4964 TargetName->MaximumLength = NameLength;
4966 TargetName->Buffer = pTmpBuffer;
4968 SetFlag( *Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER);
4971 TargetName->Length = NameLength;
4973 RtlCopyMemory( TargetName->Buffer,
4975 TargetName->Length);
4978 // Update the name in the buffer
4981 AFSUpdateName( TargetName);
4992 AFSInitNameArray( IN AFSDirectoryCB *DirectoryCB,
4993 IN ULONG InitialElementCount)
4996 AFSNameArrayHdr *pNameArray = NULL;
4997 AFSNameArrayCB *pCurrentElement = NULL;
4998 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
5004 if( InitialElementCount == 0)
5007 InitialElementCount = pDevExt->Specific.RDR.NameArrayLength;
5010 pNameArray = (AFSNameArrayHdr *)AFSExAllocatePoolWithTag( PagedPool,
5011 sizeof( AFSNameArrayHdr) +
5012 (InitialElementCount * sizeof( AFSNameArrayCB)),
5013 AFS_NAME_ARRAY_TAG);
5015 if( pNameArray == NULL)
5018 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5019 AFS_TRACE_LEVEL_ERROR,
5020 "AFSInitNameArray Failed to allocate name array\n");
5022 try_return( pNameArray);
5025 RtlZeroMemory( pNameArray,
5026 sizeof( AFSNameArrayHdr) +
5027 (InitialElementCount * sizeof( AFSNameArrayCB)));
5029 pNameArray->MaxElementCount = InitialElementCount;
5031 if( DirectoryCB != NULL)
5034 pCurrentElement = &pNameArray->ElementArray[ 0];
5036 pNameArray->CurrentEntry = pCurrentElement;
5038 pNameArray->Count = 1;
5040 pNameArray->LinkCount = 0;
5042 lCount = InterlockedIncrement( &DirectoryCB->DirOpenReferenceCount);
5044 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5045 AFS_TRACE_LEVEL_VERBOSE,
5046 "AFSInitNameArray Increment count on %wZ DE %p Cnt %d\n",
5047 &DirectoryCB->NameInformation.FileName,
5051 pCurrentElement->DirectoryCB = DirectoryCB;
5053 pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
5055 pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
5057 if( pCurrentElement->FileId.Vnode == 1)
5060 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5063 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5064 AFS_TRACE_LEVEL_VERBOSE,
5065 "AFSInitNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5067 pCurrentElement->DirectoryCB,
5068 pCurrentElement->FileId.Cell,
5069 pCurrentElement->FileId.Volume,
5070 pCurrentElement->FileId.Vnode,
5071 pCurrentElement->FileId.Unique,
5072 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5073 pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5085 AFSPopulateNameArray( IN AFSNameArrayHdr *NameArray,
5086 IN UNICODE_STRING *Path,
5087 IN AFSDirectoryCB *DirectoryCB)
5090 NTSTATUS ntStatus = STATUS_SUCCESS;
5091 AFSNameArrayCB *pCurrentElement = NULL;
5092 UNICODE_STRING uniComponentName, uniRemainingPath;
5093 AFSObjectInfoCB *pCurrentObject = NULL;
5094 ULONG ulTotalCount = 0;
5096 USHORT usLength = 0;
5102 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5103 AFS_TRACE_LEVEL_VERBOSE,
5104 "AFSPopulateNameArray [NA:%p] passed Path %wZ DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5108 DirectoryCB->ObjectInformation->FileId.Cell,
5109 DirectoryCB->ObjectInformation->FileId.Volume,
5110 DirectoryCB->ObjectInformation->FileId.Vnode,
5111 DirectoryCB->ObjectInformation->FileId.Unique,
5112 &DirectoryCB->NameInformation.FileName,
5113 DirectoryCB->ObjectInformation->FileType);
5116 // Init some info in the header
5119 pCurrentElement = &NameArray->ElementArray[ 0];
5121 NameArray->CurrentEntry = pCurrentElement;
5124 // The first entry points at the root
5127 pCurrentElement->DirectoryCB = DirectoryCB->ObjectInformation->VolumeCB->DirectoryCB;
5129 lCount = InterlockedIncrement( &pCurrentElement->DirectoryCB->DirOpenReferenceCount);
5131 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5132 AFS_TRACE_LEVEL_VERBOSE,
5133 "AFSPopulateNameArray Increment count on volume %wZ DE %p Cnt %d\n",
5134 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5135 pCurrentElement->DirectoryCB,
5138 pCurrentElement->Component = DirectoryCB->ObjectInformation->VolumeCB->DirectoryCB->NameInformation.FileName;
5140 pCurrentElement->FileId = DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
5142 pCurrentElement->Flags = 0;
5144 if( pCurrentElement->FileId.Vnode == 1)
5147 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5150 NameArray->Count = 1;
5152 NameArray->LinkCount = 0;
5154 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5155 AFS_TRACE_LEVEL_VERBOSE,
5156 "AFSPopulateNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5158 pCurrentElement->DirectoryCB,
5159 pCurrentElement->FileId.Cell,
5160 pCurrentElement->FileId.Volume,
5161 pCurrentElement->FileId.Vnode,
5162 pCurrentElement->FileId.Unique,
5163 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5164 pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5167 // If the root is the parent then we are done ...
5170 if( &DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation == DirectoryCB->ObjectInformation)
5172 try_return( ntStatus);
5184 AFSPopulateNameArrayFromRelatedArray( IN AFSNameArrayHdr *NameArray,
5185 IN AFSNameArrayHdr *RelatedNameArray,
5186 IN AFSDirectoryCB *DirectoryCB)
5189 NTSTATUS ntStatus = STATUS_SUCCESS;
5190 AFSNameArrayCB *pCurrentElement = NULL, *pCurrentRelatedElement = NULL;
5191 UNICODE_STRING uniComponentName, uniRemainingPath;
5192 AFSObjectInfoCB *pObjectInfo = NULL;
5193 ULONG ulTotalCount = 0;
5195 USHORT usLength = 0;
5201 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5202 AFS_TRACE_LEVEL_VERBOSE,
5203 "AFSPopulateNameArray [NA:%p] passed RelatedNameArray %p DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5207 DirectoryCB->ObjectInformation->FileId.Cell,
5208 DirectoryCB->ObjectInformation->FileId.Volume,
5209 DirectoryCB->ObjectInformation->FileId.Vnode,
5210 DirectoryCB->ObjectInformation->FileId.Unique,
5211 &DirectoryCB->NameInformation.FileName,
5212 DirectoryCB->ObjectInformation->FileType);
5215 // Init some info in the header
5218 pCurrentElement = &NameArray->ElementArray[ 0];
5220 pCurrentRelatedElement = &RelatedNameArray->ElementArray[ 0];
5222 NameArray->Count = 0;
5224 NameArray->LinkCount = RelatedNameArray->LinkCount;
5227 // Populate the name array with the data from the related array
5233 pCurrentElement->DirectoryCB = pCurrentRelatedElement->DirectoryCB;
5235 pCurrentElement->Component = pCurrentRelatedElement->DirectoryCB->NameInformation.FileName;
5237 pCurrentElement->FileId = pCurrentElement->DirectoryCB->ObjectInformation->FileId;
5239 pCurrentElement->Flags = 0;
5241 if( pCurrentElement->FileId.Vnode == 1)
5244 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5247 lCount = InterlockedIncrement( &pCurrentElement->DirectoryCB->DirOpenReferenceCount);
5249 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5250 AFS_TRACE_LEVEL_VERBOSE,
5251 "AFSPopulateNameArrayFromRelatedArray Increment count on %wZ DE %p Cnt %d\n",
5252 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5253 pCurrentElement->DirectoryCB,
5256 lCount = InterlockedIncrement( &NameArray->Count);
5258 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5259 AFS_TRACE_LEVEL_VERBOSE,
5260 "AFSPopulateNameArrayFromRelatedArray [NA:%p] Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5263 pCurrentElement->DirectoryCB,
5264 pCurrentElement->FileId.Cell,
5265 pCurrentElement->FileId.Volume,
5266 pCurrentElement->FileId.Vnode,
5267 pCurrentElement->FileId.Unique,
5268 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5269 pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5271 if( pCurrentElement->DirectoryCB == DirectoryCB ||
5272 NameArray->Count == RelatedNameArray->Count)
5284 pCurrentRelatedElement++;
5287 NameArray->CurrentEntry = NameArray->Count > 0 ? pCurrentElement : NULL;
5294 AFSFreeNameArray( IN AFSNameArrayHdr *NameArray)
5297 NTSTATUS ntStatus = STATUS_SUCCESS;
5298 AFSNameArrayCB *pCurrentElement = NULL;
5299 LONG lCount, lElement;
5304 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5305 AFS_TRACE_LEVEL_VERBOSE,
5306 "AFSFreeNameArray [NA:%p]\n",
5309 for ( lElement = 0; lElement < NameArray->Count; lElement++)
5312 pCurrentElement = &NameArray->ElementArray[ lElement];
5314 lCount = InterlockedDecrement( &pCurrentElement->DirectoryCB->DirOpenReferenceCount);
5316 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5317 AFS_TRACE_LEVEL_VERBOSE,
5318 "AFSFreeNameArray Decrement count on %wZ DE %p Cnt %d\n",
5319 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5320 pCurrentElement->DirectoryCB,
5323 ASSERT( lCount >= 0);
5326 AFSExFreePoolWithTag( NameArray, AFS_NAME_ARRAY_TAG);
5333 AFSInsertNextElement( IN AFSNameArrayHdr *NameArray,
5334 IN AFSDirectoryCB *DirectoryCB)
5337 NTSTATUS ntStatus = STATUS_SUCCESS;
5338 AFSNameArrayCB *pCurrentElement = NULL;
5344 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5345 AFS_TRACE_LEVEL_VERBOSE,
5346 "AFSInsertNextElement [NA:%p] passed DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5349 DirectoryCB->ObjectInformation->FileId.Cell,
5350 DirectoryCB->ObjectInformation->FileId.Volume,
5351 DirectoryCB->ObjectInformation->FileId.Vnode,
5352 DirectoryCB->ObjectInformation->FileId.Unique,
5353 &DirectoryCB->NameInformation.FileName,
5354 DirectoryCB->ObjectInformation->FileType);
5356 if( NameArray->Count == NameArray->MaxElementCount)
5359 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5360 AFS_TRACE_LEVEL_ERROR,
5361 "AFSInsertNextElement [NA:%p] Name has reached Maximum Size\n",
5364 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5367 for ( lCount = 0; lCount < NameArray->Count; lCount++)
5370 if ( AFSIsEqualFID( &NameArray->ElementArray[ lCount].FileId,
5371 &DirectoryCB->ObjectInformation->FileId) )
5374 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5375 AFS_TRACE_LEVEL_WARNING,
5376 "AFSInsertNextElement [NA:%p] DE %p recursion Status %08X\n",
5379 STATUS_ACCESS_DENIED);
5381 try_return( ntStatus = STATUS_ACCESS_DENIED);
5385 if( NameArray->Count > 0)
5388 NameArray->CurrentEntry++;
5392 NameArray->CurrentEntry = &NameArray->ElementArray[ 0];
5395 pCurrentElement = NameArray->CurrentEntry;
5397 lCount = InterlockedIncrement( &NameArray->Count);
5399 lCount = InterlockedIncrement( &DirectoryCB->DirOpenReferenceCount);
5401 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5402 AFS_TRACE_LEVEL_VERBOSE,
5403 "AFSInsertNextElement Increment count on %wZ DE %p Cnt %d\n",
5404 &DirectoryCB->NameInformation.FileName,
5408 ASSERT( lCount >= 2);
5410 pCurrentElement->DirectoryCB = DirectoryCB;
5412 pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
5414 pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
5416 pCurrentElement->Flags = 0;
5418 if( pCurrentElement->FileId.Vnode == 1)
5421 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5424 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5425 AFS_TRACE_LEVEL_VERBOSE,
5426 "AFSInsertNextElement [NA:%p] Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5428 NameArray->Count - 1,
5429 pCurrentElement->DirectoryCB,
5430 pCurrentElement->FileId.Cell,
5431 pCurrentElement->FileId.Volume,
5432 pCurrentElement->FileId.Vnode,
5433 pCurrentElement->FileId.Unique,
5434 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5435 pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5446 AFSBackupEntry( IN AFSNameArrayHdr *NameArray)
5449 AFSDirectoryCB *pDirectoryCB = NULL;
5450 AFSNameArrayCB *pCurrentElement = NULL;
5451 BOOLEAN bVolumeRoot = FALSE;
5457 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5458 AFS_TRACE_LEVEL_VERBOSE,
5459 "AFSBackupEntry [NA:%p]\n",
5462 if( NameArray->Count == 0)
5465 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5466 AFS_TRACE_LEVEL_ERROR,
5467 "AFSBackupEntry [NA:%p] No more entries\n",
5470 try_return( pCurrentElement);
5473 lCount = InterlockedDecrement( &NameArray->CurrentEntry->DirectoryCB->DirOpenReferenceCount);
5475 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5476 AFS_TRACE_LEVEL_VERBOSE,
5477 "AFSBackupEntry Decrement count on %wZ DE %p Cnt %d\n",
5478 &NameArray->CurrentEntry->DirectoryCB->NameInformation.FileName,
5479 NameArray->CurrentEntry->DirectoryCB,
5482 ASSERT( lCount >= 0);
5484 NameArray->CurrentEntry->DirectoryCB = NULL;
5486 lCount = InterlockedDecrement( &NameArray->Count);
5490 NameArray->CurrentEntry = NULL;
5492 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5493 AFS_TRACE_LEVEL_ERROR,
5494 "AFSBackupEntry [NA:%p] No more entries\n",
5500 bVolumeRoot = BooleanFlagOn( NameArray->CurrentEntry->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5502 NameArray->CurrentEntry--;
5504 pCurrentElement = NameArray->CurrentEntry;
5506 pDirectoryCB = pCurrentElement->DirectoryCB;
5508 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5509 AFS_TRACE_LEVEL_VERBOSE,
5510 "AFSBackupEntry [NA:%p] Returning Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5512 NameArray->Count - 1,
5513 pCurrentElement->DirectoryCB,
5514 pCurrentElement->FileId.Cell,
5515 pCurrentElement->FileId.Volume,
5516 pCurrentElement->FileId.Vnode,
5517 pCurrentElement->FileId.Unique,
5518 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5519 pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5522 // If the entry we are removing is a volume root,
5523 // we must remove the mount point entry as well.
5524 // If the NameArray was constructed by checking the
5525 // share name via the service, the name array can
5526 // contain two volume roots in sequence without a
5527 // mount point separating them.
5531 !BooleanFlagOn( NameArray->CurrentEntry->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT))
5534 pDirectoryCB = AFSBackupEntry( NameArray);
5544 return pDirectoryCB;
5548 AFSGetParentEntry( IN AFSNameArrayHdr *NameArray)
5551 AFSDirectoryCB *pDirEntry = NULL;
5552 AFSNameArrayCB *pElement = NULL;
5557 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5558 AFS_TRACE_LEVEL_VERBOSE,
5559 "AFSGetParentEntry [NA:%p]\n",
5562 if( NameArray->Count == 0 ||
5563 NameArray->Count == 1)
5566 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5567 AFS_TRACE_LEVEL_ERROR,
5568 "AFSGetParentEntry [NA:%p] No more entries\n",
5571 try_return( pDirEntry = NULL);
5574 pElement = &NameArray->ElementArray[ NameArray->Count - 2];
5576 pDirEntry = pElement->DirectoryCB;
5578 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5579 AFS_TRACE_LEVEL_VERBOSE,
5580 "AFSGetParentEntry [NA:%p] Returning Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5582 NameArray->Count - 2,
5583 pElement->DirectoryCB,
5584 pElement->FileId.Cell,
5585 pElement->FileId.Volume,
5586 pElement->FileId.Vnode,
5587 pElement->FileId.Unique,
5588 &pElement->DirectoryCB->NameInformation.FileName,
5589 pElement->DirectoryCB->ObjectInformation->FileType);
5600 AFSResetNameArray( IN AFSNameArrayHdr *NameArray,
5601 IN AFSDirectoryCB *DirectoryCB)
5604 AFSNameArrayCB *pCurrentElement = NULL;
5605 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
5606 LONG lCount, lElement;
5611 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5612 AFS_TRACE_LEVEL_VERBOSE,
5613 "AFSResetNameArray [NA:%p] passed DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5616 DirectoryCB->ObjectInformation->FileId.Cell,
5617 DirectoryCB->ObjectInformation->FileId.Volume,
5618 DirectoryCB->ObjectInformation->FileId.Vnode,
5619 DirectoryCB->ObjectInformation->FileId.Unique,
5620 &DirectoryCB->NameInformation.FileName,
5621 DirectoryCB->ObjectInformation->FileType);
5623 // Dereference previous name array contents
5626 for ( lElement = 0; lElement < NameArray->Count; lElement++)
5629 pCurrentElement = &NameArray->ElementArray[ lElement];
5631 lCount = InterlockedDecrement( &pCurrentElement->DirectoryCB->DirOpenReferenceCount);
5633 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5634 AFS_TRACE_LEVEL_VERBOSE,
5635 "AFSResetNameArray Decrement count on %wZ DE %p Cnt %d\n",
5636 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5637 pCurrentElement->DirectoryCB,
5640 ASSERT( lCount >= 0);
5643 RtlZeroMemory( NameArray,
5644 sizeof( AFSNameArrayHdr) +
5645 ((pDevExt->Specific.RDR.NameArrayLength - 1) * sizeof( AFSNameArrayCB)));
5647 NameArray->MaxElementCount = pDevExt->Specific.RDR.NameArrayLength;
5649 if( DirectoryCB != NULL)
5652 pCurrentElement = &NameArray->ElementArray[ 0];
5654 NameArray->CurrentEntry = pCurrentElement;
5656 NameArray->Count = 1;
5658 NameArray->LinkCount = 0;
5660 lCount = InterlockedIncrement( &DirectoryCB->DirOpenReferenceCount);
5662 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5663 AFS_TRACE_LEVEL_VERBOSE,
5664 "AFSResetNameArray Increment count on %wZ DE %p Cnt %d\n",
5665 &DirectoryCB->NameInformation.FileName,
5669 pCurrentElement->DirectoryCB = DirectoryCB;
5671 pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
5673 pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
5675 pCurrentElement->Flags = 0;
5677 if( pCurrentElement->FileId.Vnode == 1)
5680 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5683 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5684 AFS_TRACE_LEVEL_VERBOSE,
5685 "AFSResetNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5687 pCurrentElement->DirectoryCB,
5688 pCurrentElement->FileId.Cell,
5689 pCurrentElement->FileId.Volume,
5690 pCurrentElement->FileId.Vnode,
5691 pCurrentElement->FileId.Unique,
5692 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5693 pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5701 AFSDumpNameArray( IN AFSNameArrayHdr *NameArray)
5704 AFSNameArrayCB *pCurrentElement = NULL;
5706 pCurrentElement = &NameArray->ElementArray[ 0];
5708 AFSPrint("AFSDumpNameArray Start (%d)\n", NameArray->Count);
5710 while( pCurrentElement->DirectoryCB != NULL)
5713 AFSPrint("FID %08lX-%08lX-%08lX-%08lX %wZ\n",
5714 pCurrentElement->FileId.Cell,
5715 pCurrentElement->FileId.Volume,
5716 pCurrentElement->FileId.Vnode,
5717 pCurrentElement->FileId.Unique,
5718 &pCurrentElement->DirectoryCB->NameInformation.FileName);
5723 AFSPrint("AFSDumpNameArray End\n\n");
5729 AFSSetEnumerationEvent( IN AFSFcb *Fcb)
5734 // Depending on the type of node, set the event
5737 switch( Fcb->Header.NodeTypeCode)
5740 case AFS_DIRECTORY_FCB:
5745 lCount = InterlockedIncrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
5755 AFSClearEnumerationEvent( IN AFSFcb *Fcb)
5761 // Depending on the type of node, set the event
5764 switch( Fcb->Header.NodeTypeCode)
5767 case AFS_DIRECTORY_FCB:
5772 ASSERT( Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0);
5774 lCount = InterlockedDecrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
5784 AFSIsEnumerationInProcess( IN AFSObjectInfoCB *ObjectInfo)
5787 BOOLEAN bIsInProcess = FALSE;
5792 if( ObjectInfo->Fcb == NULL)
5795 try_return( bIsInProcess);
5798 switch( ObjectInfo->Fcb->Header.NodeTypeCode)
5801 case AFS_DIRECTORY_FCB:
5806 if( ObjectInfo->Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0)
5809 bIsInProcess = TRUE;
5821 return bIsInProcess;
5825 AFSVerifyVolume( IN ULONGLONG ProcessId,
5826 IN AFSVolumeCB *VolumeCB)
5829 NTSTATUS ntStatus = STATUS_SUCCESS;
5836 AFSInitPIOCtlDirectoryCB( IN AFSObjectInfoCB *ObjectInfo)
5839 NTSTATUS ntStatus = STATUS_SUCCESS;
5840 AFSObjectInfoCB *pObjectInfoCB = NULL;
5841 AFSDirectoryCB *pDirNode = NULL;
5842 ULONG ulEntryLength = 0;
5843 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
5849 pObjectInfoCB = AFSAllocateObjectInfo( ObjectInfo,
5852 if( pObjectInfoCB == NULL)
5855 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5858 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
5859 AFS_TRACE_LEVEL_VERBOSE,
5860 "AFSInitPIOCtlDirectoryCB Initializing count (1) on object %08lX\n",
5863 pObjectInfoCB->ObjectReferenceCount = 1;
5865 pObjectInfoCB->FileType = AFS_FILE_TYPE_PIOCTL;
5867 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
5869 ulEntryLength = sizeof( AFSDirectoryCB) + AFSPIOCtlName.Length;
5871 pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
5875 if( pDirNode == NULL)
5878 AFSDeleteObjectInfo( pObjectInfoCB);
5880 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5883 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
5884 sizeof( AFSNonPagedDirectoryCB),
5885 AFS_DIR_ENTRY_NP_TAG);
5887 if( pNonPagedDirEntry == NULL)
5890 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5893 RtlZeroMemory( pDirNode,
5896 RtlZeroMemory( pNonPagedDirEntry,
5897 sizeof( AFSNonPagedDirectoryCB));
5899 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
5901 pDirNode->NonPaged = pNonPagedDirEntry;
5903 pDirNode->ObjectInformation = pObjectInfoCB;
5905 pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_PIOCTL_INDEX;
5911 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_FAKE);
5913 pDirNode->NameInformation.FileName.Length = AFSPIOCtlName.Length;
5915 pDirNode->NameInformation.FileName.MaximumLength = AFSPIOCtlName.Length;
5917 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
5919 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
5920 AFSPIOCtlName.Buffer,
5921 pDirNode->NameInformation.FileName.Length);
5923 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
5926 if ( InterlockedCompareExchangePointer( (PVOID *)&ObjectInfo->Specific.Directory.PIOCtlDirectoryCB, pDirNode, NULL) != NULL)
5929 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
5930 AFS_TRACE_LEVEL_WARNING,
5931 "AFSInitPIOCtlDirectoryCB Raced PIOCtlDirectoryCB %08lX pFcb %08lX\n",
5932 ObjectInfo->Specific.Directory.PIOCtlDirectoryCB,
5936 // Increment the open reference and handle on the node
5939 lCount = AFSObjectInfoIncrement( pDirNode->ObjectInformation);
5941 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
5942 AFS_TRACE_LEVEL_VERBOSE,
5943 "AFSInitPIOCtlDirectoryCB Increment count on Object %08lX Cnt %d\n",
5944 pDirNode->ObjectInformation,
5947 try_return( ntStatus = STATUS_REPARSE);
5952 if ( ntStatus != STATUS_SUCCESS)
5955 if ( pDirNode != NULL)
5958 AFSExFreePoolWithTag( pDirNode, AFS_DIR_ENTRY_TAG);
5961 if( pNonPagedDirEntry != NULL)
5964 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
5966 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
5969 if ( pObjectInfoCB != NULL)
5972 AFSDeleteObjectInfo( pObjectInfoCB);
5981 AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB,
5982 IN AFSDirectoryCB *DirectoryCB,
5983 IN UNICODE_STRING *ParentPathName,
5984 IN AFSNameArrayHdr *RelatedNameArray,
5986 OUT AFSFileInfoCB *FileInfo)
5989 NTSTATUS ntStatus = STATUS_SUCCESS;
5990 AFSDirEnumEntry *pDirEntry = NULL, *pLastDirEntry = NULL;
5991 UNICODE_STRING uniFullPathName;
5992 AFSNameArrayHdr *pNameArray = NULL;
5993 AFSVolumeCB *pVolumeCB = NULL;
5994 AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
5995 WCHAR *pwchBuffer = NULL;
5996 UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
5997 ULONG ulNameDifference = 0;
6004 // Retrieve a target name for the entry
6007 AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
6010 if( DirectoryCB->NameInformation.TargetName.Length == 0)
6013 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6015 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
6020 if( !NT_SUCCESS( ntStatus) ||
6021 pDirEntry->TargetNameLength == 0)
6024 if( pDirEntry != NULL)
6027 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
6030 try_return( ntStatus);
6033 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
6036 if( DirectoryCB->NameInformation.TargetName.Length == 0)
6040 // Update the target name
6043 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
6044 &DirectoryCB->Flags,
6045 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
6046 (USHORT)pDirEntry->TargetNameLength);
6048 if( !NT_SUCCESS( ntStatus))
6051 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6053 try_return( ntStatus);
6057 AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
6061 // Need to pass the full path in for parsing.
6064 if( AFSIsRelativeName( &DirectoryCB->NameInformation.TargetName))
6067 uniFullPathName.Length = 0;
6068 uniFullPathName.MaximumLength = ParentPathName->Length +
6070 DirectoryCB->NameInformation.TargetName.Length;
6072 uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6073 uniFullPathName.MaximumLength,
6074 AFS_NAME_BUFFER_SIX_TAG);
6076 if( uniFullPathName.Buffer == NULL)
6079 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6081 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6084 pwchBuffer = uniFullPathName.Buffer;
6086 RtlZeroMemory( uniFullPathName.Buffer,
6087 uniFullPathName.MaximumLength);
6089 RtlCopyMemory( uniFullPathName.Buffer,
6090 ParentPathName->Buffer,
6091 ParentPathName->Length);
6093 uniFullPathName.Length = ParentPathName->Length;
6095 if( uniFullPathName.Buffer[ (uniFullPathName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
6096 DirectoryCB->NameInformation.TargetName.Buffer[ 0] != L'\\')
6099 uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)] = L'\\';
6101 uniFullPathName.Length += sizeof( WCHAR);
6104 RtlCopyMemory( &uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)],
6105 DirectoryCB->NameInformation.TargetName.Buffer,
6106 DirectoryCB->NameInformation.TargetName.Length);
6108 uniFullPathName.Length += DirectoryCB->NameInformation.TargetName.Length;
6110 uniParsedName.Length = uniFullPathName.Length - ParentPathName->Length;
6111 uniParsedName.MaximumLength = uniParsedName.Length;
6113 uniParsedName.Buffer = &uniFullPathName.Buffer[ ParentPathName->Length/sizeof( WCHAR)];
6115 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6118 // We populate up to the current parent
6121 if( RelatedNameArray != NULL)
6124 pNameArray = AFSInitNameArray( NULL,
6125 RelatedNameArray->MaxElementCount);
6127 if( pNameArray == NULL)
6130 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6133 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
6140 pNameArray = AFSInitNameArray( NULL,
6143 if( pNameArray == NULL)
6146 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6149 ntStatus = AFSPopulateNameArray( pNameArray,
6154 if( !NT_SUCCESS( ntStatus))
6157 try_return( ntStatus);
6160 pVolumeCB = ParentDirectoryCB->ObjectInformation->VolumeCB;
6162 pParentDirEntry = ParentDirectoryCB;
6167 uniFullPathName.Length = 0;
6168 uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
6170 uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6171 uniFullPathName.MaximumLength,
6172 AFS_NAME_BUFFER_SEVEN_TAG);
6174 if( uniFullPathName.Buffer == NULL)
6177 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6179 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6182 pwchBuffer = uniFullPathName.Buffer;
6184 RtlZeroMemory( uniFullPathName.Buffer,
6185 uniFullPathName.MaximumLength);
6187 RtlCopyMemory( uniFullPathName.Buffer,
6188 DirectoryCB->NameInformation.TargetName.Buffer,
6189 DirectoryCB->NameInformation.TargetName.Length);
6191 uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6194 // This name should begin with the \afs server so parse it off and check it
6197 FsRtlDissectName( uniFullPathName,
6201 if( RtlCompareUnicodeString( &uniComponentName,
6206 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6208 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
6209 AFS_TRACE_LEVEL_ERROR,
6210 "AFSRetrieveFileAttributes Name %wZ contains invalid server name\n",
6213 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
6216 uniFullPathName = uniRemainingPath;
6218 uniParsedName = uniFullPathName;
6220 ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
6222 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6228 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
6231 if( pNameArray == NULL)
6234 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6237 pVolumeCB = AFSGlobalRoot;
6239 pParentDirEntry = AFSGlobalRoot->DirectoryCB;
6243 // Increment the ref count on the volume and dir entry for correct processing below
6246 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
6248 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6249 AFS_TRACE_LEVEL_VERBOSE,
6250 "AFSRetrieveFileAttributes Increment count on volume %08lX Cnt %d\n",
6254 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
6256 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6257 AFS_TRACE_LEVEL_VERBOSE,
6258 "AFSRetrieveFileAttributes Increment count on %wZ DE %p Ccb %p Cnt %d\n",
6259 &pParentDirEntry->NameInformation.FileName,
6264 ntStatus = AFSLocateNameEntry( NULL,
6269 AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL,
6275 if( !NT_SUCCESS( ntStatus))
6279 // The volume lock was released on failure above
6280 // Except for STATUS_OBJECT_NAME_NOT_FOUND
6283 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
6286 if( pVolumeCB != NULL)
6289 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6291 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6292 AFS_TRACE_LEVEL_VERBOSE,
6293 "AFSRetrieveFileAttributes Decrement count on volume %08lX Cnt %d\n",
6298 if( pDirectoryEntry != NULL)
6301 lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
6303 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6304 AFS_TRACE_LEVEL_VERBOSE,
6305 "AFSRetrieveFileAttributes Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6306 &pDirectoryEntry->NameInformation.FileName,
6311 ASSERT( lCount >= 0);
6316 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
6318 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6319 AFS_TRACE_LEVEL_VERBOSE,
6320 "AFSRetrieveFileAttributes Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
6321 &pParentDirEntry->NameInformation.FileName,
6326 ASSERT( lCount >= 0);
6332 try_return( ntStatus);
6336 // Store off the information
6339 FileInfo->FileAttributes = pDirectoryEntry->ObjectInformation->FileAttributes;
6342 // Check for the mount point being returned
6345 if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT)
6348 FileInfo->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
6350 else if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK ||
6351 pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DFSLINK)
6354 if ( FileInfo->FileAttributes == FILE_ATTRIBUTE_NORMAL)
6357 FileInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
6362 FileInfo->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
6366 FileInfo->AllocationSize = pDirectoryEntry->ObjectInformation->AllocationSize;
6368 FileInfo->EndOfFile = pDirectoryEntry->ObjectInformation->EndOfFile;
6370 FileInfo->CreationTime = pDirectoryEntry->ObjectInformation->CreationTime;
6372 FileInfo->LastAccessTime = pDirectoryEntry->ObjectInformation->LastAccessTime;
6374 FileInfo->LastWriteTime = pDirectoryEntry->ObjectInformation->LastWriteTime;
6376 FileInfo->ChangeTime = pDirectoryEntry->ObjectInformation->ChangeTime;
6379 // Remove the reference made above
6382 lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
6384 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6385 AFS_TRACE_LEVEL_VERBOSE,
6386 "AFSRetrieveFileAttributes Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
6387 &pDirectoryEntry->NameInformation.FileName,
6392 ASSERT( lCount >= 0);
6396 if( pDirEntry != NULL)
6399 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
6402 if( pVolumeCB != NULL)
6405 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6407 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6408 AFS_TRACE_LEVEL_VERBOSE,
6409 "AFSRetrieveFileAttributes Decrement2 count on volume %08lX Cnt %d\n",
6414 if( pNameArray != NULL)
6417 AFSFreeNameArray( pNameArray);
6420 if( pwchBuffer != NULL)
6424 // Always free the buffer that we allocated as AFSLocateNameEntry
6425 // will not free it. If uniFullPathName.Buffer was allocated by
6426 // AFSLocateNameEntry, then we must free that as well.
6427 // Check that the uniFullPathName.Buffer in the string is not the same
6428 // offset by the length of the server name
6431 if( uniFullPathName.Length > 0 &&
6432 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
6435 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
6438 AFSExFreePoolWithTag( pwchBuffer, 0);
6446 AFSAllocateObjectInfo( IN AFSObjectInfoCB *ParentObjectInfo,
6447 IN ULONGLONG HashIndex)
6450 NTSTATUS ntStatus = STATUS_SUCCESS;
6451 AFSObjectInfoCB *pObjectInfo = NULL;
6457 pObjectInfo = (AFSObjectInfoCB *)AFSExAllocatePoolWithTag( PagedPool,
6458 sizeof( AFSObjectInfoCB),
6459 AFS_OBJECT_INFO_TAG);
6461 if( pObjectInfo == NULL)
6464 try_return( pObjectInfo);
6467 RtlZeroMemory( pObjectInfo,
6468 sizeof( AFSObjectInfoCB));
6470 pObjectInfo->NonPagedInfo = (AFSNonPagedObjectInfoCB *)AFSExAllocatePoolWithTag( NonPagedPool,
6471 sizeof( AFSNonPagedObjectInfoCB),
6472 AFS_NP_OBJECT_INFO_TAG);
6474 if( pObjectInfo->NonPagedInfo == NULL)
6477 AFSExFreePoolWithTag( pObjectInfo, AFS_OBJECT_INFO_TAG);
6479 try_return( pObjectInfo = NULL);
6482 ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6484 ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
6486 pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock = &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock;
6488 pObjectInfo->VolumeCB = ParentObjectInfo->VolumeCB;
6490 pObjectInfo->ParentObjectInformation = ParentObjectInfo;
6492 if( ParentObjectInfo != NULL)
6494 lCount = AFSObjectInfoIncrement( ParentObjectInfo);
6498 // Initialize the access time
6501 KeQueryTickCount( &pObjectInfo->LastAccessCount);
6507 // Insert the entry into the object tree and list
6510 pObjectInfo->TreeEntry.HashIndex = HashIndex;
6512 if( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead == NULL)
6515 ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead = &pObjectInfo->TreeEntry;
6520 ntStatus = AFSInsertHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
6521 &pObjectInfo->TreeEntry);
6523 ASSERT( NT_SUCCESS( ntStatus));
6527 // And the object list in the volume
6530 if( ParentObjectInfo->VolumeCB->ObjectInfoListHead == NULL)
6533 ParentObjectInfo->VolumeCB->ObjectInfoListHead = pObjectInfo;
6538 ParentObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = (void *)pObjectInfo;
6540 pObjectInfo->ListEntry.bLink = (void *)ParentObjectInfo->VolumeCB->ObjectInfoListTail;
6543 ParentObjectInfo->VolumeCB->ObjectInfoListTail = pObjectInfo;
6546 // Indicate the object is in the hash tree and linked list in the volume
6549 SetFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE | AFS_OBJECT_INSERTED_VOLUME_LIST);
6561 AFSObjectInfoIncrement( IN AFSObjectInfoCB *ObjectInfo)
6566 if ( ObjectInfo->ObjectReferenceCount == 0)
6569 AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6572 lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6577 AFSAcquireShared( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6580 lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6585 AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6587 AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6592 AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6598 AFSObjectInfoDecrement( IN AFSObjectInfoCB *ObjectInfo)
6603 AFSAcquireShared( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6606 lCount = InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);
6611 lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6613 AFSReleaseResource(&ObjectInfo->NonPagedInfo->ObjectInfoLock);
6615 AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6618 lCount = InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);
6621 AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6629 AFSDeleteObjectInfo( IN AFSObjectInfoCB *ObjectInfo)
6632 BOOLEAN bAcquiredTreeLock = FALSE;
6635 if ( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_ROOT_VOLUME))
6639 // AFSDeleteObjectInfo should never be called on the ObjectInformationCB
6640 // embedded in the VolumeCB.
6648 if( !ExIsResourceAcquiredExclusiveLite( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock))
6651 ASSERT( !ExIsResourceAcquiredLite( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock));
6653 AFSAcquireExcl( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
6656 bAcquiredTreeLock = TRUE;
6660 // Remove it from the tree and list if it was inserted
6663 if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
6666 AFSRemoveHashEntry( &ObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
6667 &ObjectInfo->TreeEntry);
6670 if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_INSERTED_VOLUME_LIST))
6673 if( ObjectInfo->ListEntry.fLink == NULL)
6676 ObjectInfo->VolumeCB->ObjectInfoListTail = (AFSObjectInfoCB *)ObjectInfo->ListEntry.bLink;
6678 if( ObjectInfo->VolumeCB->ObjectInfoListTail != NULL)
6681 ObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = NULL;
6687 ((AFSObjectInfoCB *)(ObjectInfo->ListEntry.fLink))->ListEntry.bLink = ObjectInfo->ListEntry.bLink;
6690 if( ObjectInfo->ListEntry.bLink == NULL)
6693 ObjectInfo->VolumeCB->ObjectInfoListHead = (AFSObjectInfoCB *)ObjectInfo->ListEntry.fLink;
6695 if( ObjectInfo->VolumeCB->ObjectInfoListHead != NULL)
6698 ObjectInfo->VolumeCB->ObjectInfoListHead->ListEntry.bLink = NULL;
6704 ((AFSObjectInfoCB *)(ObjectInfo->ListEntry.bLink))->ListEntry.fLink = ObjectInfo->ListEntry.fLink;
6708 if( ObjectInfo->ParentObjectInformation != NULL)
6711 lCount = AFSObjectInfoDecrement( ObjectInfo->ParentObjectInformation);
6714 if( bAcquiredTreeLock)
6717 AFSReleaseResource( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
6721 // Release the fid in the service
6724 if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_HELD_IN_SERVICE))
6727 AFSReleaseFid( &ObjectInfo->FileId);
6730 ExDeleteResourceLite( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6732 ExDeleteResourceLite( &ObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6734 AFSExFreePoolWithTag( ObjectInfo->NonPagedInfo, AFS_NP_OBJECT_INFO_TAG);
6736 AFSExFreePoolWithTag( ObjectInfo, AFS_OBJECT_INFO_TAG);
6742 AFSEvaluateRootEntry( IN AFSDirectoryCB *DirectoryCB,
6743 OUT AFSDirectoryCB **TargetDirEntry)
6746 NTSTATUS ntStatus = STATUS_SUCCESS;
6747 AFSDirEnumEntry *pDirEntry = NULL, *pLastDirEntry = NULL;
6748 UNICODE_STRING uniFullPathName;
6749 AFSNameArrayHdr *pNameArray = NULL;
6750 AFSVolumeCB *pVolumeCB = NULL;
6751 AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
6752 WCHAR *pwchBuffer = NULL;
6753 UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
6754 ULONG ulNameDifference = 0;
6761 ntStatus = AFSRetrieveValidAuthGroup( NULL,
6762 DirectoryCB->ObjectInformation,
6766 if( !NT_SUCCESS( ntStatus))
6768 try_return( ntStatus);
6772 // Retrieve a target name for the entry
6775 AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
6778 if( DirectoryCB->NameInformation.TargetName.Length == 0)
6781 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6783 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
6788 if( !NT_SUCCESS( ntStatus) ||
6789 pDirEntry->TargetNameLength == 0)
6792 if( pDirEntry != NULL)
6795 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
6798 try_return( ntStatus);
6801 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
6804 if( DirectoryCB->NameInformation.TargetName.Length == 0)
6808 // Update the target name
6811 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
6812 &DirectoryCB->Flags,
6813 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
6814 (USHORT)pDirEntry->TargetNameLength);
6816 if( !NT_SUCCESS( ntStatus))
6819 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6821 try_return( ntStatus);
6825 AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
6829 // Need to pass the full path in for parsing.
6832 uniFullPathName.Length = 0;
6833 uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
6835 uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6836 uniFullPathName.MaximumLength,
6837 AFS_NAME_BUFFER_EIGHT_TAG);
6839 if( uniFullPathName.Buffer == NULL)
6842 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6844 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6847 pwchBuffer = uniFullPathName.Buffer;
6849 RtlZeroMemory( uniFullPathName.Buffer,
6850 uniFullPathName.MaximumLength);
6852 RtlCopyMemory( uniFullPathName.Buffer,
6853 DirectoryCB->NameInformation.TargetName.Buffer,
6854 DirectoryCB->NameInformation.TargetName.Length);
6856 uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6859 // This name should begin with the \afs server so parse it off and chech it
6862 FsRtlDissectName( uniFullPathName,
6866 if( RtlCompareUnicodeString( &uniComponentName,
6872 // Try evaluating the full path
6875 uniFullPathName.Buffer = pwchBuffer;
6877 uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6879 uniFullPathName.MaximumLength = uniFullPathName.Length;
6884 uniFullPathName = uniRemainingPath;
6887 uniParsedName = uniFullPathName;
6889 ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
6891 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6897 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
6900 if( pNameArray == NULL)
6903 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6906 pVolumeCB = AFSGlobalRoot;
6908 pParentDirEntry = AFSGlobalRoot->DirectoryCB;
6910 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
6912 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6913 AFS_TRACE_LEVEL_VERBOSE,
6914 "AFSEvaluateRootEntry Increment count on volume %08lX Cnt %d\n",
6918 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
6920 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6921 AFS_TRACE_LEVEL_VERBOSE,
6922 "AFSEvaluateRootEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
6923 &pParentDirEntry->NameInformation.FileName,
6928 ntStatus = AFSLocateNameEntry( NULL,
6939 if( !NT_SUCCESS( ntStatus))
6943 // The volume lock was released on failure above
6944 // Except for STATUS_OBJECT_NAME_NOT_FOUND
6947 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
6950 if( pVolumeCB != NULL)
6953 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6955 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6956 AFS_TRACE_LEVEL_VERBOSE,
6957 "AFSEvaluateRootEntry Decrement count on volume %08lX Cnt %d\n",
6962 if( pDirectoryEntry != NULL)
6965 lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
6967 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6968 AFS_TRACE_LEVEL_VERBOSE,
6969 "AFSEvaluateRootEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6970 &pDirectoryEntry->NameInformation.FileName,
6975 ASSERT( lCount >= 0);
6980 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
6982 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6983 AFS_TRACE_LEVEL_VERBOSE,
6984 "AFSEvaluateRootEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
6985 &pParentDirEntry->NameInformation.FileName,
6990 ASSERT( lCount >= 0);
6996 try_return( ntStatus);
7000 // Pass back the target dir entry for this request
7003 *TargetDirEntry = pDirectoryEntry;
7007 if( pDirEntry != NULL)
7010 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
7013 if( pVolumeCB != NULL)
7016 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
7018 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7019 AFS_TRACE_LEVEL_VERBOSE,
7020 "AFSEvaluateRootEntry Decrement2 count on volume %08lX Cnt %d\n",
7025 if( pNameArray != NULL)
7028 AFSFreeNameArray( pNameArray);
7031 if( pwchBuffer != NULL)
7035 // Always free the buffer that we allocated as AFSLocateNameEntry
7036 // will not free it. If uniFullPathName.Buffer was allocated by
7037 // AFSLocateNameEntry, then we must free that as well.
7038 // Check that the uniFullPathName.Buffer in the string is not the same
7039 // offset by the length of the server name
7042 if( uniFullPathName.Length > 0 &&
7043 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
7046 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
7049 AFSExFreePoolWithTag( pwchBuffer, 0);
7057 AFSCleanupFcb( IN AFSFcb *Fcb,
7058 IN BOOLEAN ForceFlush)
7061 NTSTATUS ntStatus = STATUS_SUCCESS;
7062 AFSDeviceExt *pRDRDeviceExt = NULL, *pControlDeviceExt = NULL;
7063 LARGE_INTEGER liTime;
7064 IO_STATUS_BLOCK stIoStatus;
7069 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
7071 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
7073 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
7076 if( !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) &&
7077 !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
7080 AFSAcquireExcl( &Fcb->NPFcb->Resource,
7083 if( Fcb->OpenReferenceCount > 0)
7089 CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
7094 if( !NT_SUCCESS( stIoStatus.Status))
7097 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
7098 AFS_TRACE_LEVEL_ERROR,
7099 "AFSCleanupFcb CcFlushCache [1] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
7100 Fcb->ObjectInformation->FileId.Cell,
7101 Fcb->ObjectInformation->FileId.Volume,
7102 Fcb->ObjectInformation->FileId.Vnode,
7103 Fcb->ObjectInformation->FileId.Unique,
7105 stIoStatus.Information);
7107 ntStatus = stIoStatus.Status;
7110 if ( Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
7113 if ( !CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
7119 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
7120 AFS_TRACE_LEVEL_WARNING,
7121 "AFSCleanupFcb CcPurgeCacheSection [1] failure FID %08lX-%08lX-%08lX-%08lX\n",
7122 Fcb->ObjectInformation->FileId.Cell,
7123 Fcb->ObjectInformation->FileId.Volume,
7124 Fcb->ObjectInformation->FileId.Vnode,
7125 Fcb->ObjectInformation->FileId.Unique);
7127 SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
7131 __except( EXCEPTION_EXECUTE_HANDLER)
7134 ntStatus = GetExceptionCode();
7138 "EXCEPTION - AFSCleanupFcb Cc [1] FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
7139 Fcb->ObjectInformation->FileId.Cell,
7140 Fcb->ObjectInformation->FileId.Volume,
7141 Fcb->ObjectInformation->FileId.Vnode,
7142 Fcb->ObjectInformation->FileId.Unique,
7145 SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
7149 AFSReleaseResource( &Fcb->NPFcb->Resource);
7152 // Wait for any currently running flush or release requests to complete
7155 AFSWaitOnQueuedFlushes( Fcb);
7158 // Now perform another flush on the file
7161 if( !NT_SUCCESS( AFSFlushExtents( Fcb,
7165 AFSReleaseExtentsWithFlush( Fcb,
7171 if( Fcb->OpenReferenceCount == 0 ||
7172 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
7173 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
7176 AFSTearDownFcbExtents( Fcb,
7180 try_return( ntStatus);
7183 KeQueryTickCount( &liTime);
7186 // First up are there dirty extents in the cache to flush?
7189 if( BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
7190 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
7194 // The file has been marked as invalid. Dump it
7197 AFSTearDownFcbExtents( Fcb,
7200 else if( ForceFlush ||
7201 ( ( Fcb->Specific.File.ExtentsDirtyCount ||
7202 Fcb->Specific.File.ExtentCount) &&
7203 (liTime.QuadPart - Fcb->Specific.File.LastServerFlush.QuadPart)
7204 >= pControlDeviceExt->Specific.Control.FcbFlushTimeCount.QuadPart))
7206 if( !NT_SUCCESS( AFSFlushExtents( Fcb,
7208 Fcb->OpenReferenceCount == 0)
7211 AFSReleaseExtentsWithFlush( Fcb,
7218 // If there are extents and they haven't been used recently *and*
7219 // are not being used
7223 ( 0 != Fcb->Specific.File.ExtentCount &&
7224 0 != Fcb->Specific.File.LastExtentAccess.QuadPart &&
7225 (liTime.QuadPart - Fcb->Specific.File.LastExtentAccess.QuadPart) >=
7226 (AFS_SERVER_PURGE_SLEEP * pControlDeviceExt->Specific.Control.FcbPurgeTimeCount.QuadPart))))
7229 if ( AFSAcquireExcl( &Fcb->NPFcb->Resource, ForceFlush))
7235 CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
7240 if( !NT_SUCCESS( stIoStatus.Status))
7243 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
7244 AFS_TRACE_LEVEL_ERROR,
7245 "AFSCleanupFcb CcFlushCache [2] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
7246 Fcb->ObjectInformation->FileId.Cell,
7247 Fcb->ObjectInformation->FileId.Volume,
7248 Fcb->ObjectInformation->FileId.Vnode,
7249 Fcb->ObjectInformation->FileId.Unique,
7251 stIoStatus.Information);
7253 ntStatus = stIoStatus.Status;
7257 Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
7260 if ( !CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
7266 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
7267 AFS_TRACE_LEVEL_WARNING,
7268 "AFSCleanupFcb CcPurgeCacheSection [2] failure FID %08lX-%08lX-%08lX-%08lX\n",
7269 Fcb->ObjectInformation->FileId.Cell,
7270 Fcb->ObjectInformation->FileId.Volume,
7271 Fcb->ObjectInformation->FileId.Vnode,
7272 Fcb->ObjectInformation->FileId.Unique);
7274 SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
7278 __except( EXCEPTION_EXECUTE_HANDLER)
7281 ntStatus = GetExceptionCode();
7285 "EXCEPTION - AFSCleanupFcb Cc [2] FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
7286 Fcb->ObjectInformation->FileId.Cell,
7287 Fcb->ObjectInformation->FileId.Volume,
7288 Fcb->ObjectInformation->FileId.Vnode,
7289 Fcb->ObjectInformation->FileId.Unique,
7293 AFSReleaseResource( &Fcb->NPFcb->Resource);
7295 if( Fcb->OpenReferenceCount <= 0)
7299 // Tear em down we'll not be needing them again
7302 AFSTearDownFcbExtents( Fcb,
7309 ntStatus = STATUS_RETRY;
7322 AFSUpdateDirEntryName( IN AFSDirectoryCB *DirectoryCB,
7323 IN UNICODE_STRING *NewFileName)
7326 NTSTATUS ntStatus = STATUS_SUCCESS;
7327 WCHAR *pTmpBuffer = NULL;
7332 if( NewFileName->Length > DirectoryCB->NameInformation.FileName.Length)
7335 if( BooleanFlagOn( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
7338 AFSExFreePoolWithTag( DirectoryCB->NameInformation.FileName.Buffer, 0);
7340 ClearFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
7342 DirectoryCB->NameInformation.FileName.Buffer = NULL;
7346 // OK, we need to allocate a new name buffer
7349 pTmpBuffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
7350 NewFileName->Length,
7351 AFS_NAME_BUFFER_NINE_TAG);
7353 if( pTmpBuffer == NULL)
7356 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7359 DirectoryCB->NameInformation.FileName.Buffer = pTmpBuffer;
7361 DirectoryCB->NameInformation.FileName.MaximumLength = NewFileName->Length;
7363 SetFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
7366 DirectoryCB->NameInformation.FileName.Length = NewFileName->Length;
7368 RtlCopyMemory( DirectoryCB->NameInformation.FileName.Buffer,
7369 NewFileName->Buffer,
7370 NewFileName->Length);
7381 AFSReadCacheFile( IN void *ReadBuffer,
7382 IN LARGE_INTEGER *ReadOffset,
7383 IN ULONG RequestedDataLength,
7384 IN OUT PULONG BytesRead)
7387 NTSTATUS ntStatus = STATUS_SUCCESS;
7390 PIO_STACK_LOCATION pIoStackLocation = NULL;
7391 AFSDeviceExt *pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
7392 DEVICE_OBJECT *pTargetDeviceObject = NULL;
7393 FILE_OBJECT *pCacheFileObject = NULL;
7398 pCacheFileObject = AFSReferenceCacheFileObject();
7400 if( pCacheFileObject == NULL)
7402 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
7405 pTargetDeviceObject = IoGetRelatedDeviceObject( pCacheFileObject);
7408 // Initialize the event
7411 KeInitializeEvent( &kEvent,
7412 SynchronizationEvent,
7416 // Allocate an irp for this request. This could also come from a
7417 // private pool, for instance.
7420 pIrp = IoAllocateIrp( pTargetDeviceObject->StackSize,
7426 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7430 // Build the IRP's main body
7433 pIrp->UserBuffer = ReadBuffer;
7435 pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
7436 pIrp->RequestorMode = KernelMode;
7437 pIrp->Flags |= IRP_READ_OPERATION;
7440 // Set up the I/O stack location.
7443 pIoStackLocation = IoGetNextIrpStackLocation( pIrp);
7444 pIoStackLocation->MajorFunction = IRP_MJ_READ;
7445 pIoStackLocation->DeviceObject = pTargetDeviceObject;
7446 pIoStackLocation->FileObject = pCacheFileObject;
7447 pIoStackLocation->Parameters.Read.Length = RequestedDataLength;
7449 pIoStackLocation->Parameters.Read.ByteOffset.QuadPart = ReadOffset->QuadPart;
7452 // Set the completion routine.
7455 IoSetCompletionRoutine( pIrp,
7463 // Send it to the FSD
7466 ntStatus = IoCallDriver( pTargetDeviceObject,
7469 if( NT_SUCCESS( ntStatus))
7476 ntStatus = KeWaitForSingleObject( &kEvent,
7482 if( NT_SUCCESS( ntStatus))
7485 ntStatus = pIrp->IoStatus.Status;
7487 *BytesRead = (ULONG)pIrp->IoStatus.Information;
7493 if( pCacheFileObject != NULL)
7495 AFSReleaseCacheFileObject( pCacheFileObject);
7501 if( pIrp->MdlAddress != NULL)
7504 if( FlagOn( pIrp->MdlAddress->MdlFlags, MDL_PAGES_LOCKED))
7507 MmUnlockPages( pIrp->MdlAddress);
7510 IoFreeMdl( pIrp->MdlAddress);
7513 pIrp->MdlAddress = NULL;
7527 AFSIrpComplete( IN PDEVICE_OBJECT DeviceObject,
7532 KEVENT *pEvent = (KEVENT *)Context;
7538 return STATUS_MORE_PROCESSING_REQUIRED;
7542 AFSIsDirectoryEmptyForDelete( IN AFSFcb *Fcb)
7545 BOOLEAN bIsEmpty = FALSE;
7546 AFSDirectoryCB *pDirEntry = NULL;
7551 AFSAcquireShared( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
7556 if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
7559 pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
7561 while( pDirEntry != NULL)
7564 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
7565 !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
7573 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
7578 AFSReleaseResource( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
7585 AFSRemoveNameEntry( IN AFSObjectInfoCB *ParentObjectInfo,
7586 IN AFSDirectoryCB *DirEntry)
7589 NTSTATUS ntStatus = STATUS_SUCCESS;
7594 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7597 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7598 AFS_TRACE_LEVEL_VERBOSE,
7599 "AFSRemoveNameEntry DE %p for %wZ has NOT_IN flag set\n",
7601 &DirEntry->NameInformation.FileName);
7603 try_return( ntStatus);
7606 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
7609 // Remove the entry from the parent tree
7612 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7613 AFS_TRACE_LEVEL_VERBOSE,
7614 "AFSRemoveNameEntry DE %p for %wZ removing from case sensitive tree\n",
7616 &DirEntry->NameInformation.FileName);
7618 AFSRemoveCaseSensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7621 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7622 AFS_TRACE_LEVEL_VERBOSE,
7623 "AFSRemoveNameEntry DE %p for %wZ removing from case insensitive tree\n",
7625 &DirEntry->NameInformation.FileName);
7627 AFSRemoveCaseInsensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
7630 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
7634 // From the short name tree
7637 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7638 AFS_TRACE_LEVEL_VERBOSE,
7639 "AFSRemoveNameEntry DE %p for %wZ removing from shortname tree\n",
7641 &DirEntry->NameInformation.FileName);
7643 AFSRemoveShortNameDirEntry( &ParentObjectInfo->Specific.Directory.ShortNameTree,
7646 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
7649 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7650 AFS_TRACE_LEVEL_VERBOSE,
7651 "AFSRemoveNameEntry DE %p for %wZ setting NOT_IN flag\n",
7653 &DirEntry->NameInformation.FileName);
7655 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
7657 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
7668 AFSGetAuthenticationId()
7671 LARGE_INTEGER liAuthId = {0,0};
7672 NTSTATUS ntStatus = STATUS_SUCCESS;
7673 PACCESS_TOKEN hToken = NULL;
7674 PTOKEN_STATISTICS pTokenInfo = NULL;
7675 BOOLEAN bCopyOnOpen = FALSE;
7676 BOOLEAN bEffectiveOnly = FALSE;
7677 BOOLEAN bPrimaryToken = FALSE;
7678 SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
7683 hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
7686 &stImpersonationLevel);
7691 hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
7696 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7697 AFS_TRACE_LEVEL_ERROR,
7698 "AFSGetAuthenticationId Failed to retrieve impersonation or primary token\n");
7700 try_return( ntStatus);
7703 bPrimaryToken = TRUE;
7706 ntStatus = SeQueryInformationToken( hToken,
7708 (PVOID *)&pTokenInfo);
7710 if( !NT_SUCCESS( ntStatus))
7713 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7714 AFS_TRACE_LEVEL_ERROR,
7715 "AFSGetAuthenticationId Failed to retrieve information Status %08lX\n", ntStatus);
7717 try_return( ntStatus);
7720 liAuthId.HighPart = pTokenInfo->AuthenticationId.HighPart;
7721 liAuthId.LowPart = pTokenInfo->AuthenticationId.LowPart;
7723 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7724 AFS_TRACE_LEVEL_VERBOSE,
7725 "AFSGetAuthenticationId Successfully retrieved authentication ID %I64X\n",
7736 PsDereferenceImpersonationToken( hToken);
7741 PsDereferencePrimaryToken( hToken);
7745 if( pTokenInfo != NULL)
7748 ExFreePool( pTokenInfo); // Allocated by SeQueryInformationToken
7756 AFSUnwindFileInfo( IN AFSFcb *Fcb,
7760 if( Ccb->FileUnwindInfo.FileAttributes != (ULONG)-1)
7762 Ccb->DirectoryCB->ObjectInformation->FileAttributes = Ccb->FileUnwindInfo.FileAttributes;
7765 if( Ccb->FileUnwindInfo.CreationTime.QuadPart != (ULONGLONG)-1)
7767 Ccb->DirectoryCB->ObjectInformation->CreationTime.QuadPart = Ccb->FileUnwindInfo.CreationTime.QuadPart;
7770 if( Ccb->FileUnwindInfo.LastAccessTime.QuadPart != (ULONGLONG)-1)
7772 Ccb->DirectoryCB->ObjectInformation->LastAccessTime.QuadPart = Ccb->FileUnwindInfo.LastAccessTime.QuadPart;
7775 if( Ccb->FileUnwindInfo.LastWriteTime.QuadPart != (ULONGLONG)-1)
7777 Ccb->DirectoryCB->ObjectInformation->LastWriteTime.QuadPart = Ccb->FileUnwindInfo.LastWriteTime.QuadPart;
7780 if( Ccb->FileUnwindInfo.ChangeTime.QuadPart != (ULONGLONG)-1)
7782 Ccb->DirectoryCB->ObjectInformation->ChangeTime.QuadPart = Ccb->FileUnwindInfo.ChangeTime.QuadPart;
7789 AFSValidateDirList( IN AFSObjectInfoCB *ObjectInfo)
7792 BOOLEAN bIsValid = TRUE;
7794 AFSDirectoryCB *pCurrentDirEntry = NULL, *pDirEntry = NULL;
7796 pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
7798 while( pCurrentDirEntry != NULL)
7801 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
7805 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7810 AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7811 (ULONG)pCurrentDirEntry->CaseSensitiveTreeEntry.HashIndex,
7814 if( pDirEntry == NULL)
7821 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
7824 if( ulCount != ObjectInfo->Specific.Directory.DirectoryNodeCount)
7827 AFSPrint("AFSValidateDirList Count off Calc: %d Stored: %d\n",
7829 ObjectInfo->Specific.Directory.DirectoryNodeCount);
7831 ObjectInfo->Specific.Directory.DirectoryNodeCount = ulCount;
7840 AFSReferenceCacheFileObject()
7843 AFSDeviceExt *pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
7844 FILE_OBJECT *pCacheFileObject = NULL;
7846 AFSAcquireShared( &pRdrDevExt->Specific.RDR.CacheFileLock,
7849 pCacheFileObject = pRdrDevExt->Specific.RDR.CacheFileObject;
7851 if( pCacheFileObject != NULL)
7853 ObReferenceObject( pCacheFileObject);
7856 AFSReleaseResource( &pRdrDevExt->Specific.RDR.CacheFileLock);
7858 return pCacheFileObject;
7862 AFSReleaseCacheFileObject( IN PFILE_OBJECT CacheFileObject)
7865 ASSERT( CacheFileObject != NULL);
7867 ObDereferenceObject( CacheFileObject);
7873 AFSInitializeLibrary( IN AFSLibraryInitCB *LibraryInit)
7876 NTSTATUS ntStatus = STATUS_SUCCESS;
7877 AFSDeviceExt *pControlDevExt = NULL;
7878 ULONG ulTimeIncrement = 0;
7884 AFSControlDeviceObject = LibraryInit->AFSControlDeviceObject;
7886 AFSRDRDeviceObject = LibraryInit->AFSRDRDeviceObject;
7888 AFSServerName = LibraryInit->AFSServerName;
7890 AFSMountRootName = LibraryInit->AFSMountRootName;
7892 AFSDebugFlags = LibraryInit->AFSDebugFlags;
7895 // Callbacks in the framework
7898 AFSProcessRequest = LibraryInit->AFSProcessRequest;
7900 AFSDbgLogMsg = LibraryInit->AFSDbgLogMsg;
7902 AFSAddConnectionEx = LibraryInit->AFSAddConnectionEx;
7904 AFSExAllocatePoolWithTag = LibraryInit->AFSExAllocatePoolWithTag;
7906 AFSExFreePoolWithTag = LibraryInit->AFSExFreePoolWithTag;
7908 AFSDumpTraceFilesFnc = LibraryInit->AFSDumpTraceFiles;
7910 AFSRetrieveAuthGroupFnc = LibraryInit->AFSRetrieveAuthGroup;
7912 AFSLibCacheManagerCallbacks = LibraryInit->AFSCacheManagerCallbacks;
7914 if( LibraryInit->AFSCacheBaseAddress != NULL)
7917 SetFlag( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE);
7919 AFSLibCacheBaseAddress = LibraryInit->AFSCacheBaseAddress;
7921 AFSLibCacheLength = LibraryInit->AFSCacheLength;
7925 // Initialize some flush parameters
7928 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
7930 ulTimeIncrement = KeQueryTimeIncrement();
7932 pControlDevExt->Specific.Control.ObjectLifeTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_OBJECT_LIFETIME / (ULONGLONG)ulTimeIncrement);
7933 pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart = AFS_SERVER_PURGE_DELAY;
7934 pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart /= ulTimeIncrement;
7935 pControlDevExt->Specific.Control.FcbFlushTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_SERVER_FLUSH_DELAY / (ULONGLONG)ulTimeIncrement);
7936 pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_EXTENT_REQUEST_TIME/(ULONGLONG)ulTimeIncrement);
7939 // Initialize the global root entry
7942 ntStatus = AFSInitVolume( NULL,
7943 &LibraryInit->GlobalRootFid,
7946 if( !NT_SUCCESS( ntStatus))
7949 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
7950 AFS_TRACE_LEVEL_ERROR,
7951 "AFSInitializeLibrary AFSInitVolume failure %08lX\n",
7954 try_return( ntStatus);
7957 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
7960 if( !NT_SUCCESS( ntStatus))
7963 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
7964 AFS_TRACE_LEVEL_ERROR,
7965 "AFSInitializeLibrary AFSInitRootFcb failure %08lX\n",
7968 lCount = InterlockedDecrement( &AFSGlobalRoot->VolumeReferenceCount);
7970 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7971 AFS_TRACE_LEVEL_VERBOSE,
7972 "AFSInitializeLibrary Increment count on volume %08lX Cnt %d\n",
7976 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
7978 try_return( ntStatus);
7982 // Update the node type code to AFS_ROOT_ALL
7985 AFSGlobalRoot->ObjectInformation.Fcb->Header.NodeTypeCode = AFS_ROOT_ALL;
7987 SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_ACTIVE_GLOBAL_ROOT);
7990 // Invalidate all known volumes since contact with the service and therefore
7991 // the file server was lost.
7994 AFSInvalidateAllVolumes();
7997 // Drop the locks acquired above
8000 AFSInitVolumeWorker( AFSGlobalRoot);
8002 lCount = InterlockedDecrement( &AFSGlobalRoot->VolumeReferenceCount);
8004 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8005 AFS_TRACE_LEVEL_VERBOSE,
8006 "AFSInitializeLibrary Decrement count on volume %08lX Cnt %d\n",
8010 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
8012 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Fcb->Header.Resource);
8026 NTSTATUS ntStatus = STATUS_SUCCESS;
8027 AFSDirectoryCB *pDirNode = NULL, *pLastDirNode = NULL;
8032 if( AFSGlobalDotDirEntry != NULL)
8035 AFSDeleteObjectInfo( AFSGlobalDotDirEntry->ObjectInformation);
8037 ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
8039 ExFreePool( AFSGlobalDotDirEntry->NonPaged);
8041 ExFreePool( AFSGlobalDotDirEntry);
8043 AFSGlobalDotDirEntry = NULL;
8046 if( AFSGlobalDotDotDirEntry != NULL)
8049 AFSDeleteObjectInfo( AFSGlobalDotDotDirEntry->ObjectInformation);
8051 ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
8053 ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
8055 ExFreePool( AFSGlobalDotDotDirEntry);
8057 AFSGlobalDotDotDirEntry = NULL;
8060 if( AFSSpecialShareNames != NULL)
8063 pDirNode = AFSSpecialShareNames;
8065 while( pDirNode != NULL)
8068 pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
8070 AFSDeleteObjectInfo( pDirNode->ObjectInformation);
8072 ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
8074 ExFreePool( pDirNode->NonPaged);
8076 ExFreePool( pDirNode);
8078 pDirNode = pLastDirNode;
8081 AFSSpecialShareNames = NULL;
8089 AFSDefaultLogMsg( IN ULONG Subsystem,
8095 NTSTATUS ntStatus = STATUS_SUCCESS;
8097 char chDebugBuffer[ 256];
8102 va_start( va_args, Format);
8104 ntStatus = RtlStringCbVPrintfA( chDebugBuffer,
8109 if( NT_SUCCESS( ntStatus))
8111 DbgPrint( chDebugBuffer);
8121 AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
8122 IN ULONG InputBufferLength,
8123 IN AFSStatusInfoCB *StatusInfo,
8124 OUT ULONG *ReturnLength)
8127 NTSTATUS ntStatus = STATUS_SUCCESS;
8128 AFSFcb *pFcb = NULL;
8129 AFSVolumeCB *pVolumeCB = NULL;
8130 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
8131 AFSObjectInfoCB *pObjectInfo = NULL;
8132 ULONGLONG ullIndex = 0;
8133 UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName, uniParsedName;
8134 AFSNameArrayHdr *pNameArray = NULL;
8135 AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
8142 // If we are given a FID then look up the entry by that, otherwise
8146 if( GetStatusInfo->FileID.Cell != 0 &&
8147 GetStatusInfo->FileID.Volume != 0 &&
8148 GetStatusInfo->FileID.Vnode != 0 &&
8149 GetStatusInfo->FileID.Unique != 0)
8152 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
8155 // Locate the volume node
8158 ullIndex = AFSCreateHighIndex( &GetStatusInfo->FileID);
8160 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
8162 (AFSBTreeEntry **)&pVolumeCB);
8164 if( pVolumeCB != NULL)
8167 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
8169 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8170 AFS_TRACE_LEVEL_VERBOSE,
8171 "AFSGetObjectStatus Increment count on volume %08lX Cnt %d\n",
8176 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
8178 if( !NT_SUCCESS( ntStatus) ||
8181 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8184 if( AFSIsVolumeFID( &GetStatusInfo->FileID))
8187 pObjectInfo = &pVolumeCB->ObjectInformation;
8189 lCount = AFSObjectInfoIncrement( pObjectInfo);
8191 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
8193 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8194 AFS_TRACE_LEVEL_VERBOSE,
8195 "AFSGetObjectStatus Decrement count on volume %08lX Cnt %d\n",
8202 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
8205 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
8207 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8208 AFS_TRACE_LEVEL_VERBOSE,
8209 "AFSGetObjectStatus Decrement2 count on volume %08lX Cnt %d\n",
8213 ullIndex = AFSCreateLowIndex( &GetStatusInfo->FileID);
8215 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
8217 (AFSBTreeEntry **)&pObjectInfo);
8219 if( pObjectInfo != NULL)
8223 // Reference the node so it won't be torn down
8226 lCount = AFSObjectInfoIncrement( pObjectInfo);
8228 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8229 AFS_TRACE_LEVEL_VERBOSE,
8230 "AFSGetObjectStatus Increment count on object %08lX Cnt %d\n",
8235 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
8237 if( !NT_SUCCESS( ntStatus) ||
8238 pObjectInfo == NULL)
8240 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8247 if( GetStatusInfo->FileNameLength == 0 ||
8248 InputBufferLength < (ULONG)(FIELD_OFFSET( AFSGetStatusInfoCB, FileName) + GetStatusInfo->FileNameLength))
8250 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8253 uniFullPathName.Length = GetStatusInfo->FileNameLength;
8254 uniFullPathName.MaximumLength = uniFullPathName.Length;
8256 uniFullPathName.Buffer = (WCHAR *)GetStatusInfo->FileName;
8259 // This name should begin with the \afs server so parse it off and check it
8262 FsRtlDissectName( uniFullPathName,
8266 if( RtlCompareUnicodeString( &uniComponentName,
8270 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8271 AFS_TRACE_LEVEL_ERROR,
8272 "AFSGetObjectStatus Name %wZ contains invalid server name\n",
8275 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
8278 uniFullPathName = uniRemainingPath;
8280 uniParsedName = uniFullPathName;
8286 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
8289 if( pNameArray == NULL)
8291 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8294 pVolumeCB = AFSGlobalRoot;
8296 pParentDirEntry = AFSGlobalRoot->DirectoryCB;
8299 // Increment the ref count on the volume and dir entry for correct processing below
8302 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
8304 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8305 AFS_TRACE_LEVEL_VERBOSE,
8306 "AFSGetObjectStatus Increment2 count on volume %08lX Cnt %d\n",
8310 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
8312 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8313 AFS_TRACE_LEVEL_VERBOSE,
8314 "AFSGetObjectStatus Increment count on %wZ DE %p Ccb %p Cnt %d\n",
8315 &pParentDirEntry->NameInformation.FileName,
8320 ntStatus = AFSLocateNameEntry( NULL,
8325 AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL |
8326 AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL,
8332 if( !NT_SUCCESS( ntStatus))
8336 // The volume lock was released on failure above
8337 // Except for STATUS_OBJECT_NAME_NOT_FOUND
8340 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
8343 if( pVolumeCB != NULL)
8346 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
8348 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8349 AFS_TRACE_LEVEL_VERBOSE,
8350 "AFSGetObjectStatus Decrement3 count on volume %08lX Cnt %d\n",
8355 if( pDirectoryEntry != NULL)
8358 lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
8360 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8361 AFS_TRACE_LEVEL_VERBOSE,
8362 "AFSGetObjectStatus Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
8363 &pDirectoryEntry->NameInformation.FileName,
8368 ASSERT( lCount >= 0);
8373 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
8375 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8376 AFS_TRACE_LEVEL_VERBOSE,
8377 "AFSGetObjectStatus Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
8378 &pParentDirEntry->NameInformation.FileName,
8383 ASSERT( lCount >= 0);
8389 try_return( ntStatus);
8393 // Remove the reference made above
8396 lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
8398 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8399 AFS_TRACE_LEVEL_VERBOSE,
8400 "AFSGetObjectStatus Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
8401 &pDirectoryEntry->NameInformation.FileName,
8406 ASSERT( lCount >= 0);
8408 pObjectInfo = pDirectoryEntry->ObjectInformation;
8410 lCount = AFSObjectInfoIncrement( pObjectInfo);
8412 if( pVolumeCB != NULL)
8415 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
8417 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8418 AFS_TRACE_LEVEL_VERBOSE,
8419 "AFSGetObjectStatus Decrement4 count on volume %08lX Cnt %d\n",
8426 // At this point we have an object info block, return the information
8429 StatusInfo->FileId = pObjectInfo->FileId;
8431 StatusInfo->TargetFileId = pObjectInfo->TargetFileId;
8433 StatusInfo->Expiration = pObjectInfo->Expiration;
8435 StatusInfo->DataVersion = pObjectInfo->DataVersion;
8437 StatusInfo->FileType = pObjectInfo->FileType;
8439 StatusInfo->ObjectFlags = pObjectInfo->Flags;
8441 StatusInfo->CreationTime = pObjectInfo->CreationTime;
8443 StatusInfo->LastAccessTime = pObjectInfo->LastAccessTime;
8445 StatusInfo->LastWriteTime = pObjectInfo->LastWriteTime;
8447 StatusInfo->ChangeTime = pObjectInfo->ChangeTime;
8449 StatusInfo->FileAttributes = pObjectInfo->FileAttributes;
8451 StatusInfo->EndOfFile = pObjectInfo->EndOfFile;
8453 StatusInfo->AllocationSize = pObjectInfo->AllocationSize;
8455 StatusInfo->EaSize = pObjectInfo->EaSize;
8457 StatusInfo->Links = pObjectInfo->Links;
8460 // Return the information length
8463 *ReturnLength = sizeof( AFSStatusInfoCB);
8467 if( pObjectInfo != NULL)
8470 lCount = AFSObjectInfoDecrement( pObjectInfo);
8473 if( pNameArray != NULL)
8476 AFSFreeNameArray( pNameArray);
8484 AFSCheckSymlinkAccess( IN AFSDirectoryCB *ParentDirectoryCB,
8485 IN UNICODE_STRING *ComponentName)
8488 NTSTATUS ntStatus = STATUS_SUCCESS;
8489 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
8490 AFSDirectoryCB *pDirEntry = NULL;
8498 // Search for the entry in the parent
8501 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8502 AFS_TRACE_LEVEL_VERBOSE_2,
8503 "AFSCheckSymlinkAccess Searching for entry %wZ case sensitive\n",
8506 ulCRC = AFSGenerateCRC( ComponentName,
8509 AFSAcquireShared( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
8512 AFSLocateCaseSensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
8516 if( pDirEntry == NULL)
8520 // Missed so perform a case insensitive lookup
8523 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8524 AFS_TRACE_LEVEL_VERBOSE_2,
8525 "AFSCheckSymlinkAccess Searching for entry %wZ case insensitive\n",
8528 ulCRC = AFSGenerateCRC( ComponentName,
8531 AFSLocateCaseInsensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
8535 if( pDirEntry == NULL)
8539 // OK, if this component is a valid short name then try
8540 // a lookup in the short name tree
8543 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
8544 RtlIsNameLegalDOS8Dot3( ComponentName,
8549 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8550 AFS_TRACE_LEVEL_VERBOSE_2,
8551 "AFSCheckSymlinkAccess Searching for entry %wZ short name\n",
8554 AFSLocateShortNameDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.ShortNameTree,
8561 if( pDirEntry != NULL)
8563 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
8565 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8566 AFS_TRACE_LEVEL_VERBOSE,
8567 "AFSCheckSymlinkAccess Increment count on %wZ DE %p Ccb %p Cnt %d\n",
8568 &pDirEntry->NameInformation.FileName,
8573 ASSERT( lCount >= 0);
8576 AFSReleaseResource( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
8578 if( pDirEntry == NULL)
8581 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8582 AFS_TRACE_LEVEL_VERBOSE_2,
8583 "AFSCheckSymlinkAccess Failed to locate entry %wZ\n",
8586 try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
8590 // We have the symlink object but previously failed to process it so return access
8594 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8595 AFS_TRACE_LEVEL_VERBOSE_2,
8596 "AFSCheckSymlinkAccess Failing symlink access to entry %wZ REPARSE_POINT_NOT_RESOLVED\n",
8599 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
8601 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
8603 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8604 AFS_TRACE_LEVEL_VERBOSE,
8605 "AFSCheckSymlinkAccess Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
8606 &pDirEntry->NameInformation.FileName,
8611 ASSERT( lCount >= 0);
8622 AFSRetrieveFinalComponent( IN UNICODE_STRING *FullPathName,
8623 OUT UNICODE_STRING *ComponentName)
8626 NTSTATUS ntStatus = STATUS_SUCCESS;
8627 UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName;
8629 uniFullPathName = *FullPathName;
8634 FsRtlDissectName( uniFullPathName,
8638 if( uniRemainingPath.Length == 0)
8643 uniFullPathName = uniRemainingPath;
8646 if( uniComponentName.Length > 0)
8648 *ComponentName = uniComponentName;
8655 AFSDumpTraceFiles_Default()
8661 AFSValidNameFormat( IN UNICODE_STRING *FileName)
8664 BOOLEAN bIsValidName = TRUE;
8670 while( usIndex < FileName->Length/sizeof( WCHAR))
8673 if( FileName->Buffer[ usIndex] == L':' ||
8674 FileName->Buffer[ usIndex] == L'*' ||
8675 FileName->Buffer[ usIndex] == L'?' ||
8676 FileName->Buffer[ usIndex] == L'"' ||
8677 FileName->Buffer[ usIndex] == L'<' ||
8678 FileName->Buffer[ usIndex] == L'>')
8680 bIsValidName = FALSE;
8688 return bIsValidName;
8692 AFSCreateDefaultSecurityDescriptor()
8695 NTSTATUS ntStatus = STATUS_SUCCESS;
8697 ULONG ulSACLSize = 0;
8698 SYSTEM_MANDATORY_LABEL_ACE* pACE = NULL;
8699 ULONG ulACESize = 0;
8700 SECURITY_DESCRIPTOR *pSecurityDescr = NULL;
8701 ULONG ulSDLength = 0;
8702 SECURITY_DESCRIPTOR *pRelativeSecurityDescr = NULL;
8703 PSID pWorldSID = NULL;
8704 ULONG *pulSubAuthority = NULL;
8705 ULONG ulWorldSIDLEngth = 0;
8710 ulWorldSIDLEngth = RtlLengthRequiredSid( 1);
8712 pWorldSID = (PSID)ExAllocatePoolWithTag( PagedPool,
8714 AFS_GENERIC_MEMORY_29_TAG);
8716 if( pWorldSID == NULL)
8718 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate World SID\n");
8719 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8722 RtlZeroMemory( pWorldSID,
8725 RtlInitializeSid( pWorldSID,
8726 &SeWorldSidAuthority,
8729 pulSubAuthority = RtlSubAuthoritySid(pWorldSID, 0);
8730 *pulSubAuthority = SECURITY_WORLD_RID;
8732 if( AFSRtlSetSaclSecurityDescriptor == NULL)
8735 AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor == NULL\n");
8740 ulACESize = sizeof( SYSTEM_MANDATORY_LABEL_ACE) + 128;
8742 pACE = (SYSTEM_MANDATORY_LABEL_ACE *)ExAllocatePoolWithTag( PagedPool,
8744 AFS_GENERIC_MEMORY_29_TAG);
8749 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8751 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8754 RtlZeroMemory( pACE,
8757 pACE->Header.AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
8758 pACE->Header.AceType = SYSTEM_MANDATORY_LABEL_ACE_TYPE;
8759 pACE->Header.AceSize = FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + (USHORT)RtlLengthSid( SeExports->SeLowMandatorySid);
8760 pACE->Mask = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP;
8762 RtlCopySid( RtlLengthSid( SeExports->SeLowMandatorySid),
8764 SeExports->SeLowMandatorySid);
8766 ulSACLSize = sizeof(ACL) + RtlLengthSid( SeExports->SeLowMandatorySid) +
8767 FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + ulACESize;
8769 pSACL = (PACL)ExAllocatePoolWithTag( PagedPool,
8771 AFS_GENERIC_MEMORY_29_TAG);
8776 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8778 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8781 ntStatus = RtlCreateAcl( pSACL,
8785 if( !NT_SUCCESS( ntStatus))
8788 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateAcl ntStatus %08lX\n",
8791 try_return( ntStatus);
8794 ntStatus = RtlAddAce( pSACL,
8798 pACE->Header.AceSize);
8800 if( !NT_SUCCESS( ntStatus))
8803 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAddAce ntStatus %08lX\n",
8806 try_return( ntStatus);
8810 pSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
8811 sizeof( SECURITY_DESCRIPTOR),
8812 AFS_GENERIC_MEMORY_27_TAG);
8814 if( pSecurityDescr == NULL)
8817 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8819 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8822 ntStatus = RtlCreateSecurityDescriptor( pSecurityDescr,
8823 SECURITY_DESCRIPTOR_REVISION);
8825 if( !NT_SUCCESS( ntStatus))
8828 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateSecurityDescriptor ntStatus %08lX\n",
8831 try_return( ntStatus);
8834 if( AFSRtlSetSaclSecurityDescriptor != NULL)
8836 ntStatus = AFSRtlSetSaclSecurityDescriptor( pSecurityDescr,
8841 if( !NT_SUCCESS( ntStatus))
8844 AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor ntStatus %08lX\n",
8847 try_return( ntStatus);
8852 // Add in the group and owner to the SD
8855 if( AFSRtlSetGroupSecurityDescriptor != NULL)
8857 ntStatus = AFSRtlSetGroupSecurityDescriptor( pSecurityDescr,
8861 if( !NT_SUCCESS( ntStatus))
8864 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetGroupSecurityDescriptor failed ntStatus %08lX\n",
8867 try_return( ntStatus);
8871 ntStatus = RtlSetOwnerSecurityDescriptor( pSecurityDescr,
8875 if( !NT_SUCCESS( ntStatus))
8878 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetOwnerSecurityDescriptor failed ntStatus %08lX\n",
8881 try_return( ntStatus);
8884 if( !RtlValidSecurityDescriptor( pSecurityDescr))
8887 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlValidSecurityDescriptor NOT\n");
8889 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8892 pRelativeSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
8894 AFS_GENERIC_MEMORY_27_TAG);
8896 if( pRelativeSecurityDescr == NULL)
8899 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8901 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8904 ulSDLength = PAGE_SIZE;
8906 ntStatus = RtlAbsoluteToSelfRelativeSD( pSecurityDescr,
8907 pRelativeSecurityDescr,
8910 if( !NT_SUCCESS( ntStatus))
8913 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAbsoluteToSelfRelativeSD ntStatus %08lX\n",
8916 try_return( ntStatus);
8919 AFSDefaultSD = pRelativeSecurityDescr;
8923 if( !NT_SUCCESS( ntStatus))
8926 if( pRelativeSecurityDescr != NULL)
8928 ExFreePool( pRelativeSecurityDescr);
8932 if( pSecurityDescr != NULL)
8934 ExFreePool( pSecurityDescr);
8947 if( pWorldSID != NULL)
8949 ExFreePool( pWorldSID);
8957 AFSRetrieveParentPath( IN UNICODE_STRING *FullFileName,
8958 OUT UNICODE_STRING *ParentPath)
8963 *ParentPath = *FullFileName;
8966 // If the final character is a \, jump over it
8969 if( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] == L'\\')
8971 ParentPath->Length -= sizeof( WCHAR);
8974 while( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] != L'\\')
8976 ParentPath->Length -= sizeof( WCHAR);
8980 // And the separator
8983 ParentPath->Length -= sizeof( WCHAR);
8989 AFSRetrieveValidAuthGroup( IN AFSFcb *Fcb,
8990 IN AFSObjectInfoCB *ObjectInfo,
8991 IN BOOLEAN WriteAccess,
8992 OUT GUID *AuthGroup)
8995 NTSTATUS ntStatus = STATUS_SUCCESS;
8996 GUID stAuthGroup, stZeroAuthGroup;
8997 BOOLEAN bFoundAuthGroup = FALSE;
8998 AFSCcb *pCcb = NULL;
9004 RtlZeroMemory( &stAuthGroup,
9007 RtlZeroMemory( &stZeroAuthGroup,
9013 if( ObjectInfo != NULL &&
9014 ObjectInfo->Fcb != NULL)
9016 pFcb = ObjectInfo->Fcb;
9023 AFSAcquireShared( &Fcb->NPFcb->CcbListLock,
9026 pCcb = Fcb->CcbListHead;
9028 while( pCcb != NULL)
9032 pCcb->GrantedAccess & FILE_WRITE_DATA)
9034 RtlCopyMemory( &stAuthGroup,
9038 bFoundAuthGroup = TRUE;
9042 else if( pCcb->GrantedAccess & FILE_READ_DATA)
9045 // At least get the read-only access
9048 RtlCopyMemory( &stAuthGroup,
9052 bFoundAuthGroup = TRUE;
9055 pCcb = (AFSCcb *)pCcb->ListEntry.fLink;
9058 AFSReleaseResource( &Fcb->NPFcb->CcbListLock);
9061 if( !bFoundAuthGroup)
9064 AFSRetrieveAuthGroupFnc( (ULONGLONG)PsGetCurrentProcessId(),
9065 (ULONGLONG)PsGetCurrentThreadId(),
9068 if( RtlCompareMemory( &stZeroAuthGroup,
9070 sizeof( GUID)) == sizeof( GUID))
9073 DbgPrint("AFSRetrieveValidAuthGroup Failed to locate PAG\n");
9075 try_return( ntStatus = STATUS_ACCESS_DENIED);
9079 RtlCopyMemory( AuthGroup,
9092 AFSPerformObjectInvalidate( IN AFSObjectInfoCB *ObjectInfo,
9093 IN ULONG InvalidateReason)
9096 NTSTATUS ntStatus = STATUS_SUCCESS;
9097 IO_STATUS_BLOCK stIoStatus;
9100 ULONG ulProcessCount = 0;
9106 switch( InvalidateReason)
9109 case AFS_INVALIDATE_DELETED:
9112 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
9113 ObjectInfo->Fcb != NULL)
9116 AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9119 ObjectInfo->Links = 0;
9121 ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
9123 KeSetEvent( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
9128 // Clear out the extents
9129 // And get rid of them (note this involves waiting
9130 // for any writes or reads to the cache to complete)
9133 AFSTearDownFcbExtents( ObjectInfo->Fcb,
9136 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
9142 case AFS_INVALIDATE_DATA_VERSION:
9145 LARGE_INTEGER liCurrentOffset = {0,0};
9146 LARGE_INTEGER liFlushLength = {0,0};
9147 ULONG ulFlushLength = 0;
9148 BOOLEAN bLocked = FALSE;
9149 BOOLEAN bExtentsLocked = FALSE;
9150 BOOLEAN bCleanExtents = FALSE;
9152 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
9153 ObjectInfo->Fcb != NULL)
9156 AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Resource,
9161 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
9162 AFS_TRACE_LEVEL_VERBOSE,
9163 "AFSPerformObjectInvalidate Acquiring Fcb extents lock %08lX SHARED %08lX\n",
9164 &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9165 PsGetCurrentThread());
9167 AFSAcquireShared( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9170 bExtentsLocked = TRUE;
9173 // There are several possibilities here:
9175 // 0. If there are no extents or all of the extents are dirty, do nothing.
9177 // 1. There could be nothing dirty and an open reference count of zero
9178 // in which case we can just tear down all of the extents without
9179 // holding any resources.
9181 // 2. There could be nothing dirty and a non-zero open reference count
9182 // in which case we can issue a CcPurge against the entire file
9183 // while holding just the Fcb Resource.
9185 // 3. There can be dirty extents in which case we need to identify
9186 // the non-dirty ranges and then perform a CcPurge on just the
9187 // non-dirty ranges while holding just the Fcb Resource.
9190 if ( ObjectInfo->Fcb->Specific.File.ExtentCount != ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount)
9193 if ( ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount == 0)
9196 if ( ObjectInfo->Fcb->OpenReferenceCount == 0)
9199 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9201 bExtentsLocked = FALSE;
9203 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9207 AFSTearDownFcbExtents( ObjectInfo->Fcb,
9216 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9218 bExtentsLocked = FALSE;
9220 if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
9221 !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9227 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
9228 AFS_TRACE_LEVEL_WARNING,
9229 "AFSPerformObjectInvalidation CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9230 ObjectInfo->FileId.Cell,
9231 ObjectInfo->FileId.Volume,
9232 ObjectInfo->FileId.Vnode,
9233 ObjectInfo->FileId.Unique);
9235 SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9240 bCleanExtents = TRUE;
9243 __except( EXCEPTION_EXECUTE_HANDLER)
9246 ntStatus = GetExceptionCode();
9250 "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
9251 ObjectInfo->FileId.Cell,
9252 ObjectInfo->FileId.Volume,
9253 ObjectInfo->FileId.Vnode,
9254 ObjectInfo->FileId.Unique,
9257 SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9265 // Must build a list of non-dirty ranges from the beginning of the file
9266 // to the end. There can be at most (Fcb->Specific.File.ExtentsDirtyCount + 1)
9267 // ranges. In all but the most extreme random data write scenario there will
9268 // be significantly fewer.
9270 // For each range we need offset and size.
9273 AFSByteRange * ByteRangeList = NULL;
9274 ULONG ulByteRangeCount = 0;
9276 BOOLEAN bPurgeOnClose = FALSE;
9281 ulByteRangeCount = AFSConstructCleanByteRangeList( ObjectInfo->Fcb,
9284 if ( ByteRangeList != NULL ||
9285 ulByteRangeCount == 0)
9288 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9290 bExtentsLocked = FALSE;
9292 for ( ulIndex = 0; ulIndex < ulByteRangeCount; ulIndex++)
9299 ulSize = ByteRangeList[ulIndex].Length.QuadPart > DWORD_MAX ? DWORD_MAX : ByteRangeList[ulIndex].Length.LowPart;
9301 if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
9302 !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9303 &ByteRangeList[ulIndex].FileOffset,
9308 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
9309 AFS_TRACE_LEVEL_WARNING,
9310 "AFSPerformObjectInvalidation [1] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9311 ObjectInfo->FileId.Cell,
9312 ObjectInfo->FileId.Volume,
9313 ObjectInfo->FileId.Vnode,
9314 ObjectInfo->FileId.Unique);
9316 bPurgeOnClose = TRUE;
9321 bCleanExtents = TRUE;
9324 ByteRangeList[ulIndex].Length.QuadPart -= ulSize;
9326 ByteRangeList[ulIndex].FileOffset.QuadPart += ulSize;
9328 } while ( ByteRangeList[ulIndex].Length.QuadPart > 0);
9335 // We couldn't allocate the memory to build the purge list
9336 // so just walk the extent list while holding the ExtentsList Resource.
9337 // This could deadlock but we do not have much choice.
9340 le = ObjectInfo->Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
9344 ulCount = (ULONG)ObjectInfo->Fcb->Specific.File.ExtentCount;
9348 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
9350 while( ulProcessCount < ulCount)
9352 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
9354 if( !BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
9356 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9357 &pEntry->FileOffset,
9362 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
9363 AFS_TRACE_LEVEL_WARNING,
9364 "AFSPerformObjectInvalidation [2] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9365 ObjectInfo->FileId.Cell,
9366 ObjectInfo->FileId.Volume,
9367 ObjectInfo->FileId.Vnode,
9368 ObjectInfo->FileId.Unique);
9370 bPurgeOnClose = TRUE;
9375 bCleanExtents = TRUE;
9379 if( liCurrentOffset.QuadPart < pEntry->FileOffset.QuadPart)
9382 liFlushLength.QuadPart = pEntry->FileOffset.QuadPart - liCurrentOffset.QuadPart;
9384 while( liFlushLength.QuadPart > 0)
9387 if( liFlushLength.QuadPart > 512 * 1024000)
9389 ulFlushLength = 512 * 1024000;
9393 ulFlushLength = liFlushLength.LowPart;
9396 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9402 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
9403 AFS_TRACE_LEVEL_WARNING,
9404 "AFSPerformObjectInvalidation [3] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9405 ObjectInfo->FileId.Cell,
9406 ObjectInfo->FileId.Volume,
9407 ObjectInfo->FileId.Vnode,
9408 ObjectInfo->FileId.Unique);
9410 bPurgeOnClose = TRUE;
9415 bCleanExtents = TRUE;
9418 liFlushLength.QuadPart -= ulFlushLength;
9422 liCurrentOffset.QuadPart = pEntry->FileOffset.QuadPart + pEntry->Size;
9430 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9436 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
9437 AFS_TRACE_LEVEL_WARNING,
9438 "AFSPerformObjectInvalidation [4] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9439 ObjectInfo->FileId.Cell,
9440 ObjectInfo->FileId.Volume,
9441 ObjectInfo->FileId.Vnode,
9442 ObjectInfo->FileId.Unique);
9444 bPurgeOnClose = TRUE;
9449 bCleanExtents = TRUE;
9456 SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9460 __except( EXCEPTION_EXECUTE_HANDLER)
9463 ntStatus = GetExceptionCode();
9467 "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
9468 ObjectInfo->FileId.Cell,
9469 ObjectInfo->FileId.Volume,
9470 ObjectInfo->FileId.Vnode,
9471 ObjectInfo->FileId.Unique,
9477 if ( bExtentsLocked)
9480 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9486 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9492 AFSReleaseCleanExtents( ObjectInfo->Fcb,
9501 if( ObjectInfo != NULL)
9504 AFSObjectInfoDecrement( ObjectInfo);