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 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2005 try_return( ntStatus);
2008 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2011 if ( AFSIsVolumeFID( &InvalidateCB->FileID))
2014 pObjectInfo = &pVolumeCB->ObjectInformation;
2019 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2021 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2022 AFS_TRACE_LEVEL_VERBOSE,
2023 "AFSInvalidateCache Decrement count on volume %08lX Cnt %d\n",
2025 pVolumeCB->VolumeReferenceCount);
2027 ullIndex = AFSCreateLowIndex( &InvalidateCB->FileID);
2029 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2031 (AFSBTreeEntry **)&pObjectInfo);
2034 if( pObjectInfo != NULL)
2038 // Reference the node so it won't be torn down
2041 lCount = AFSObjectInfoIncrement( pObjectInfo);
2043 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2044 AFS_TRACE_LEVEL_VERBOSE,
2045 "AFSInvalidateCache Increment count on object %08lX Cnt %d\n",
2050 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2052 if( !NT_SUCCESS( ntStatus) ||
2053 pObjectInfo == NULL)
2056 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2057 AFS_TRACE_LEVEL_VERBOSE,
2058 "AFSInvalidateCache Invalidation FAILURE Unable to locate object FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2059 InvalidateCB->FileID.Cell,
2060 InvalidateCB->FileID.Volume,
2061 InvalidateCB->FileID.Vnode,
2062 InvalidateCB->FileID.Unique,
2065 try_return( ntStatus = STATUS_SUCCESS);
2068 AFSInvalidateObject( &pObjectInfo,
2069 InvalidateCB->Reason);
2073 if( pObjectInfo != NULL)
2076 lCount = AFSObjectInfoDecrement( pObjectInfo);
2078 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2079 AFS_TRACE_LEVEL_VERBOSE,
2080 "AFSInvalidateCache Decrement count on object %08lX Cnt %d\n",
2090 AFSIsChildOfParent( IN AFSFcb *Dcb,
2094 BOOLEAN bIsChild = FALSE;
2095 AFSFcb *pCurrentFcb = Fcb;
2097 while( pCurrentFcb != NULL)
2100 if( pCurrentFcb->ObjectInformation->ParentObjectInformation == Dcb->ObjectInformation)
2108 pCurrentFcb = pCurrentFcb->ObjectInformation->ParentObjectInformation->Fcb;
2116 AFSCreateHighIndex( IN AFSFileID *FileID)
2119 ULONGLONG ullIndex = 0;
2121 ullIndex = (((ULONGLONG)FileID->Cell << 32) | FileID->Volume);
2128 AFSCreateLowIndex( IN AFSFileID *FileID)
2131 ULONGLONG ullIndex = 0;
2133 ullIndex = (((ULONGLONG)FileID->Vnode << 32) | FileID->Unique);
2139 AFSCheckAccess( IN ACCESS_MASK DesiredAccess,
2140 IN ACCESS_MASK GrantedAccess,
2141 IN BOOLEAN DirectoryEntry)
2144 BOOLEAN bAccessGranted = TRUE;
2147 // Check if we are asking for read/write and granted only read only
2148 // NOTE: There will be more checks here
2151 if( !AFSCheckForReadOnlyAccess( DesiredAccess,
2153 AFSCheckForReadOnlyAccess( GrantedAccess,
2157 bAccessGranted = FALSE;
2160 return bAccessGranted;
2164 AFSGetDriverStatus( IN AFSDriverStatusRespCB *DriverStatus)
2167 NTSTATUS ntStatus = STATUS_SUCCESS;
2168 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2174 DriverStatus->Status = AFS_DRIVER_STATUS_READY;
2176 if( AFSGlobalRoot == NULL)
2183 DriverStatus->Status = AFS_DRIVER_STATUS_NOT_READY;
2186 if( pControlDevExt->Specific.Control.CommServiceCB.IrpPoolControlFlag != POOL_ACTIVE)
2193 DriverStatus->Status = AFS_DRIVER_STATUS_NO_SERVICE;
2200 AFSSubstituteSysName( IN UNICODE_STRING *ComponentName,
2201 IN UNICODE_STRING *SubstituteName,
2202 IN ULONG StringIndex)
2205 NTSTATUS ntStatus = STATUS_SUCCESS;
2206 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2207 AFSSysNameCB *pSysName = NULL;
2208 ERESOURCE *pSysNameLock = NULL;
2211 UNICODE_STRING uniSysName;
2218 if( IoIs32bitProcess( NULL))
2221 pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2223 pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2228 pSysNameLock = &pControlDevExt->Specific.Control.SysName64ListLock;
2230 pSysName = pControlDevExt->Specific.Control.SysName64ListHead;
2234 pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2236 pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2240 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2241 AFS_TRACE_LEVEL_VERBOSE,
2242 "AFSSubstituteSysName Acquiring SysName lock %08lX SHARED %08lX\n",
2244 PsGetCurrentThread());
2246 AFSAcquireShared( pSysNameLock,
2250 // Find where we are in the list
2253 while( pSysName != NULL &&
2254 ulIndex < StringIndex)
2257 pSysName = pSysName->fLink;
2262 if( pSysName == NULL)
2265 try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
2268 RtlInitUnicodeString( &uniSysName,
2271 // If it is a full component of @SYS then just substitue the
2275 if( RtlCompareUnicodeString( &uniSysName,
2280 SubstituteName->Length = pSysName->SysName.Length;
2281 SubstituteName->MaximumLength = SubstituteName->Length;
2283 SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2284 SubstituteName->Length,
2285 AFS_SUBST_BUFFER_TAG);
2287 if( SubstituteName->Buffer == NULL)
2290 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2293 RtlCopyMemory( SubstituteName->Buffer,
2294 pSysName->SysName.Buffer,
2295 pSysName->SysName.Length);
2302 while( ComponentName->Buffer[ usIndex] != L'@')
2308 SubstituteName->Length = (usIndex * sizeof( WCHAR)) + pSysName->SysName.Length;
2309 SubstituteName->MaximumLength = SubstituteName->Length;
2311 SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2312 SubstituteName->Length,
2313 AFS_SUBST_BUFFER_TAG);
2315 if( SubstituteName->Buffer == NULL)
2318 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2321 RtlCopyMemory( SubstituteName->Buffer,
2322 ComponentName->Buffer,
2323 usIndex * sizeof( WCHAR));
2325 RtlCopyMemory( &SubstituteName->Buffer[ usIndex],
2326 pSysName->SysName.Buffer,
2327 pSysName->SysName.Length);
2332 AFSReleaseResource( pSysNameLock);
2339 AFSSubstituteNameInPath( IN OUT UNICODE_STRING *FullPathName,
2340 IN OUT UNICODE_STRING *ComponentName,
2341 IN UNICODE_STRING *SubstituteName,
2342 IN OUT UNICODE_STRING *RemainingPath,
2343 IN BOOLEAN FreePathName)
2346 NTSTATUS ntStatus = STATUS_SUCCESS;
2347 UNICODE_STRING uniPathName;
2348 USHORT usPrefixNameLen = 0;
2349 SHORT sNameLenDelta = 0;
2355 // If the passed in name can handle the additional length
2356 // then just moves things around
2359 sNameLenDelta = SubstituteName->Length - ComponentName->Length;
2361 usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2363 if( FullPathName->MaximumLength > FullPathName->Length + sNameLenDelta)
2366 if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2369 RtlMoveMemory( &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + SubstituteName->Length)/sizeof( WCHAR))],
2370 &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + ComponentName->Length)/sizeof( WCHAR))],
2371 FullPathName->Length - usPrefixNameLen*sizeof( WCHAR) - ComponentName->Length);
2374 RtlCopyMemory( &FullPathName->Buffer[ usPrefixNameLen],
2375 SubstituteName->Buffer,
2376 SubstituteName->Length);
2378 FullPathName->Length += sNameLenDelta;
2380 ComponentName->Length += sNameLenDelta;
2382 ComponentName->MaximumLength = ComponentName->Length;
2384 if ( RemainingPath->Buffer)
2387 RemainingPath->Buffer += sNameLenDelta/sizeof( WCHAR);
2390 try_return( ntStatus);
2394 // Need to re-allocate the buffer
2397 uniPathName.Length = FullPathName->Length -
2398 ComponentName->Length +
2399 SubstituteName->Length;
2401 uniPathName.MaximumLength = FullPathName->MaximumLength + PAGE_SIZE;
2403 uniPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2404 uniPathName.MaximumLength,
2405 AFS_NAME_BUFFER_FOUR_TAG);
2407 if( uniPathName.Buffer == NULL)
2410 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2413 usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2415 usPrefixNameLen *= sizeof( WCHAR);
2417 RtlZeroMemory( uniPathName.Buffer,
2418 uniPathName.MaximumLength);
2420 RtlCopyMemory( uniPathName.Buffer,
2421 FullPathName->Buffer,
2424 RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen/sizeof( WCHAR))],
2425 SubstituteName->Buffer,
2426 SubstituteName->Length);
2428 if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2431 RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen + SubstituteName->Length)/sizeof( WCHAR)],
2432 &FullPathName->Buffer[ (usPrefixNameLen + ComponentName->Length)/sizeof( WCHAR)],
2433 FullPathName->Length - usPrefixNameLen - ComponentName->Length);
2436 ComponentName->Buffer = uniPathName.Buffer + (ComponentName->Buffer - FullPathName->Buffer);
2438 ComponentName->Length += sNameLenDelta;
2440 ComponentName->MaximumLength = ComponentName->Length;
2442 if ( RemainingPath->Buffer)
2445 RemainingPath->Buffer = uniPathName.Buffer
2446 + (RemainingPath->Buffer - FullPathName->Buffer)
2447 + sNameLenDelta/sizeof( WCHAR);
2452 AFSExFreePoolWithTag( FullPathName->Buffer, 0);
2455 *FullPathName = uniPathName;
2466 AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
2470 NTSTATUS ntStatus = STATUS_SUCCESS;
2471 AFSObjectInfoCB *pCurrentObject = NULL;
2472 AFSObjectInfoCB *pNextObject = NULL;
2474 AFSFcb *pFcb = NULL;
2480 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2481 AFS_TRACE_LEVEL_VERBOSE,
2482 "AFSInvalidateVolume Invalidate volume fid %08lX-%08lX-%08lX-%08lX Reason %08lX\n",
2483 VolumeCB->ObjectInformation.FileId.Cell,
2484 VolumeCB->ObjectInformation.FileId.Volume,
2485 VolumeCB->ObjectInformation.FileId.Vnode,
2486 VolumeCB->ObjectInformation.FileId.Unique,
2490 // Depending on the reason for invalidation then perform work on the node
2496 case AFS_INVALIDATE_DELETED:
2500 // Mark this volume as invalid
2503 SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
2505 SetFlag( VolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE);
2512 // Invalidate the volume root directory
2515 pCurrentObject = &VolumeCB->ObjectInformation;
2517 if ( pCurrentObject )
2520 lCount = AFSObjectInfoIncrement( pCurrentObject);
2522 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2523 AFS_TRACE_LEVEL_VERBOSE,
2524 "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2528 AFSInvalidateObject( &pCurrentObject,
2531 if ( pCurrentObject)
2534 lCount = AFSObjectInfoDecrement( pCurrentObject);
2536 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2537 AFS_TRACE_LEVEL_VERBOSE,
2538 "AFSInvalidateVolumeObjects Decrement count on object %08lX Cnt %d\n",
2545 // Apply invalidation to all other volume objects
2548 AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2551 pCurrentObject = VolumeCB->ObjectInfoListHead;
2553 if ( pCurrentObject)
2557 // Reference the node so it won't be torn down
2560 lCount = AFSObjectInfoIncrement( pCurrentObject);
2562 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2563 AFS_TRACE_LEVEL_VERBOSE,
2564 "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2569 while( pCurrentObject != NULL)
2572 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2578 // Reference the node so it won't be torn down
2581 lCount = AFSObjectInfoIncrement( pNextObject);
2583 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2584 AFS_TRACE_LEVEL_VERBOSE,
2585 "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2590 AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2592 AFSInvalidateObject( &pCurrentObject,
2595 if ( pCurrentObject )
2598 lCount = AFSObjectInfoDecrement( pCurrentObject);
2600 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2601 AFS_TRACE_LEVEL_VERBOSE,
2602 "AFSInvalidateVolumeObjects Decrement count on object %08lX Cnt %d\n",
2607 AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2610 pCurrentObject = pNextObject;
2613 AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2620 AFSInvalidateAllVolumes( VOID)
2622 AFSVolumeCB *pVolumeCB = NULL;
2623 AFSVolumeCB *pNextVolumeCB = NULL;
2624 AFSDeviceExt *pRDRDeviceExt = NULL;
2627 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2629 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2630 AFS_TRACE_LEVEL_VERBOSE,
2631 "AFSInvalidateAllVolumes Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
2632 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2633 PsGetCurrentThread());
2635 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2638 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
2643 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2644 AFS_TRACE_LEVEL_VERBOSE,
2645 "AFSInvalidateAllVolumes Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
2646 pVolumeCB->ObjectInfoTree.TreeLock,
2647 PsGetCurrentThread());
2649 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2652 while( pVolumeCB != NULL)
2655 pNextVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2660 lCount = InterlockedIncrement( &pNextVolumeCB->VolumeReferenceCount);
2663 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2665 // do I need to hold the volume lock here?
2667 AFSInvalidateVolume( pVolumeCB, AFS_INVALIDATE_EXPIRED);
2669 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2672 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2674 pVolumeCB = pNextVolumeCB;
2677 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2681 AFSVerifyEntry( IN GUID *AuthGroup,
2682 IN AFSDirectoryCB *DirEntry)
2685 NTSTATUS ntStatus = STATUS_SUCCESS;
2686 AFSDirEnumEntry *pDirEnumEntry = NULL;
2687 AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
2688 IO_STATUS_BLOCK stIoStatus;
2693 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2694 AFS_TRACE_LEVEL_VERBOSE_2,
2695 "AFSVerifyEntry Verifying entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2696 &DirEntry->NameInformation.FileName,
2697 pObjectInfo->FileId.Cell,
2698 pObjectInfo->FileId.Volume,
2699 pObjectInfo->FileId.Vnode,
2700 pObjectInfo->FileId.Unique);
2702 ntStatus = AFSEvaluateTargetByID( pObjectInfo,
2707 if( !NT_SUCCESS( ntStatus))
2710 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2711 AFS_TRACE_LEVEL_ERROR,
2712 "AFSVerifyEntry Evaluate Target failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2713 &DirEntry->NameInformation.FileName,
2714 pObjectInfo->FileId.Cell,
2715 pObjectInfo->FileId.Volume,
2716 pObjectInfo->FileId.Vnode,
2717 pObjectInfo->FileId.Unique,
2720 try_return( ntStatus);
2724 // Check the data version of the file
2727 if( pObjectInfo->DataVersion.QuadPart == pDirEnumEntry->DataVersion.QuadPart)
2729 if ( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2732 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2733 AFS_TRACE_LEVEL_VERBOSE,
2734 "AFSVerifyEntry No DV change %I64X for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2735 pObjectInfo->DataVersion.QuadPart,
2736 &DirEntry->NameInformation.FileName,
2737 pObjectInfo->FileId.Cell,
2738 pObjectInfo->FileId.Volume,
2739 pObjectInfo->FileId.Vnode,
2740 pObjectInfo->FileId.Unique);
2743 // We are ok, just get out
2746 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2748 try_return( ntStatus = STATUS_SUCCESS);
2753 // New data version so we will need to process the node based on the type
2756 switch( pDirEnumEntry->FileType)
2759 case AFS_FILE_TYPE_MOUNTPOINT:
2763 // For a mount point we need to ensure the target is the same
2766 if( !AFSIsEqualFID( &pObjectInfo->TargetFileId,
2767 &pDirEnumEntry->TargetFileId))
2773 // Update the metadata for the entry
2776 ntStatus = AFSUpdateMetaData( DirEntry,
2779 if( NT_SUCCESS( ntStatus))
2782 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2788 case AFS_FILE_TYPE_SYMLINK:
2792 // Update the metadata for the entry
2795 ntStatus = AFSUpdateMetaData( DirEntry,
2798 if( NT_SUCCESS( ntStatus))
2801 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2807 case AFS_FILE_TYPE_FILE:
2809 FILE_OBJECT * pCCFileObject = NULL;
2810 BOOLEAN bPurgeExtents = FALSE;
2812 if ( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
2815 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2816 AFS_TRACE_LEVEL_VERBOSE,
2817 "AFSVerifyEntry DV Change %wZ FID %08lX-%08lX-%08lX-%08lX (%08lX != %08lX)\n",
2818 &DirEntry->NameInformation.FileName,
2819 pObjectInfo->FileId.Cell,
2820 pObjectInfo->FileId.Volume,
2821 pObjectInfo->FileId.Vnode,
2822 pObjectInfo->FileId.Unique,
2823 pObjectInfo->DataVersion.LowPart,
2824 pDirEnumEntry->DataVersion.LowPart
2827 bPurgeExtents = TRUE;
2830 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2833 bPurgeExtents = TRUE;
2835 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2836 AFS_TRACE_LEVEL_VERBOSE,
2837 "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %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);
2844 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
2847 if( pObjectInfo->Fcb != NULL)
2850 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2851 AFS_TRACE_LEVEL_VERBOSE,
2852 "AFSVerifyEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2853 &DirEntry->NameInformation.FileName,
2854 pObjectInfo->FileId.Cell,
2855 pObjectInfo->FileId.Volume,
2856 pObjectInfo->FileId.Vnode,
2857 pObjectInfo->FileId.Unique);
2859 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
2865 CcFlushCache( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2870 if( !NT_SUCCESS( stIoStatus.Status))
2873 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2874 AFS_TRACE_LEVEL_ERROR,
2875 "AFSVerifyEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
2876 &DirEntry->NameInformation.FileName,
2877 pObjectInfo->FileId.Cell,
2878 pObjectInfo->FileId.Volume,
2879 pObjectInfo->FileId.Vnode,
2880 pObjectInfo->FileId.Unique,
2882 stIoStatus.Information);
2884 ntStatus = stIoStatus.Status;
2887 if ( bPurgeExtents &&
2888 pObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
2891 if ( !CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2897 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2898 AFS_TRACE_LEVEL_WARNING,
2899 "AFSVerifyEntry CcPurgeCacheSection failure %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2900 &DirEntry->NameInformation.FileName,
2901 pObjectInfo->FileId.Cell,
2902 pObjectInfo->FileId.Volume,
2903 pObjectInfo->FileId.Vnode,
2904 pObjectInfo->FileId.Unique);
2906 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
2910 __except( EXCEPTION_EXECUTE_HANDLER)
2912 ntStatus = GetExceptionCode();
2916 "EXCEPTION - AFSVerifyEntry CcFlushCache or CcPurgeCacheSection %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2917 &DirEntry->NameInformation.FileName,
2918 pObjectInfo->FileId.Cell,
2919 pObjectInfo->FileId.Volume,
2920 pObjectInfo->FileId.Vnode,
2921 pObjectInfo->FileId.Unique,
2924 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
2927 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
2931 AFSFlushExtents( pObjectInfo->Fcb,
2936 // Reacquire the Fcb to purge the cache
2939 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2940 AFS_TRACE_LEVEL_VERBOSE,
2941 "AFSVerifyEntry Acquiring Fcb lock %08lX EXCL %08lX\n",
2942 &pObjectInfo->Fcb->NPFcb->Resource,
2943 PsGetCurrentThread());
2945 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
2949 // Update the metadata for the entry
2952 ntStatus = AFSUpdateMetaData( DirEntry,
2955 if( !NT_SUCCESS( ntStatus))
2958 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2959 AFS_TRACE_LEVEL_ERROR,
2960 "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
2961 &DirEntry->NameInformation.FileName,
2962 pObjectInfo->FileId.Cell,
2963 pObjectInfo->FileId.Volume,
2964 pObjectInfo->FileId.Vnode,
2965 pObjectInfo->FileId.Unique,
2972 // Update file sizes
2975 pObjectInfo->Fcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart;
2976 pObjectInfo->Fcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart;
2977 pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
2979 pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
2981 if ( pCCFileObject != NULL)
2983 CcSetFileSizes( pCCFileObject,
2984 (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
2987 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
2993 // Update the metadata for the entry
2996 ntStatus = AFSUpdateMetaData( DirEntry,
2999 if( !NT_SUCCESS( ntStatus))
3002 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3003 AFS_TRACE_LEVEL_ERROR,
3004 "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
3005 &DirEntry->NameInformation.FileName,
3006 pObjectInfo->FileId.Cell,
3007 pObjectInfo->FileId.Volume,
3008 pObjectInfo->FileId.Vnode,
3009 pObjectInfo->FileId.Unique,
3015 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3016 AFS_TRACE_LEVEL_WARNING,
3017 "AFSVerifyEntry Fcb NULL %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3018 &DirEntry->NameInformation.FileName,
3019 pObjectInfo->FileId.Cell,
3020 pObjectInfo->FileId.Volume,
3021 pObjectInfo->FileId.Vnode,
3022 pObjectInfo->FileId.Unique);
3025 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3030 case AFS_FILE_TYPE_DIRECTORY:
3033 AFSFcb *pCurrentFcb = NULL;
3034 AFSDirectoryCB *pCurrentDirEntry = NULL;
3037 // For a directory or root entry flush the content of
3038 // the directory enumeration.
3041 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3044 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3045 AFS_TRACE_LEVEL_VERBOSE_2,
3046 "AFSVerifyEntry Validating directory content for entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3047 &DirEntry->NameInformation.FileName,
3048 pObjectInfo->FileId.Cell,
3049 pObjectInfo->FileId.Volume,
3050 pObjectInfo->FileId.Vnode,
3051 pObjectInfo->FileId.Unique);
3053 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3056 ntStatus = AFSValidateDirectoryCache( pObjectInfo,
3059 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3061 if ( !NT_SUCCESS( ntStatus))
3064 try_return( ntStatus);
3069 // Update the metadata for the entry
3072 ntStatus = AFSUpdateMetaData( DirEntry,
3075 if( NT_SUCCESS( ntStatus))
3078 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3084 case AFS_FILE_TYPE_DFSLINK:
3087 UNICODE_STRING uniTargetName;
3090 // For a DFS link need to check the target name has not changed
3093 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
3095 uniTargetName.MaximumLength = uniTargetName.Length;
3097 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
3099 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3102 if( DirEntry->NameInformation.TargetName.Length == 0 ||
3103 RtlCompareUnicodeString( &uniTargetName,
3104 &DirEntry->NameInformation.TargetName,
3109 // Update the target name
3112 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3114 uniTargetName.Buffer,
3115 uniTargetName.Length);
3117 if( !NT_SUCCESS( ntStatus))
3120 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3126 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3129 // Update the metadata for the entry
3132 ntStatus = AFSUpdateMetaData( DirEntry,
3135 if( NT_SUCCESS( ntStatus))
3138 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3146 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3147 AFS_TRACE_LEVEL_WARNING,
3148 "AFSVerifyEntry Attempt to verify node of type %d %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3149 pObjectInfo->FileType,
3150 &DirEntry->NameInformation.FileName,
3151 pObjectInfo->FileId.Cell,
3152 pObjectInfo->FileId.Volume,
3153 pObjectInfo->FileId.Vnode,
3154 pObjectInfo->FileId.Unique);
3161 if( pDirEnumEntry != NULL)
3164 AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_2_TAG);
3172 AFSSetVolumeState( IN AFSVolumeStatusCB *VolumeStatus)
3175 NTSTATUS ntStatus = STATUS_SUCCESS;
3176 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
3177 ULONGLONG ullIndex = 0;
3178 AFSVolumeCB *pVolumeCB = NULL;
3179 AFSFcb *pFcb = NULL;
3180 AFSObjectInfoCB *pCurrentObject = NULL;
3186 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3187 AFS_TRACE_LEVEL_VERBOSE,
3188 "AFSSetVolumeState Marking volume state %d Volume Cell %08lX Volume %08lX\n",
3189 VolumeStatus->Online,
3190 VolumeStatus->FileID.Cell,
3191 VolumeStatus->FileID.Volume);
3194 // Need to locate the Fcb for the directory to purge
3197 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3198 AFS_TRACE_LEVEL_VERBOSE,
3199 "AFSSetVolumeState Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
3200 &pDevExt->Specific.RDR.VolumeTreeLock,
3201 PsGetCurrentThread());
3203 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
3206 // Locate the volume node
3209 ullIndex = AFSCreateHighIndex( &VolumeStatus->FileID);
3211 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
3213 (AFSBTreeEntry **)&pVolumeCB);
3215 if( pVolumeCB != NULL)
3218 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
3220 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3223 // Set the volume state accordingly
3226 if( VolumeStatus->Online)
3229 InterlockedAnd( (LONG *)&(pVolumeCB->Flags), ~AFS_VOLUME_FLAGS_OFFLINE);
3234 InterlockedOr( (LONG *)&(pVolumeCB->Flags), AFS_VOLUME_FLAGS_OFFLINE);
3237 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
3240 pCurrentObject = pVolumeCB->ObjectInfoListHead;;
3242 while( pCurrentObject != NULL)
3245 if( VolumeStatus->Online)
3248 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
3250 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
3252 pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
3257 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
3260 pFcb = pCurrentObject->Fcb;
3263 !(VolumeStatus->Online) &&
3264 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
3267 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3268 AFS_TRACE_LEVEL_ERROR,
3269 "AFSSetVolumeState Marking volume offline and canceling extents Volume Cell %08lX Volume %08lX\n",
3270 VolumeStatus->FileID.Cell,
3271 VolumeStatus->FileID.Volume);
3274 // Clear out the extents
3277 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3278 AFS_TRACE_LEVEL_VERBOSE,
3279 "AFSSetVolumeState Acquiring Fcb extents lock %08lX EXCL %08lX\n",
3280 &pFcb->NPFcb->Specific.File.ExtentsResource,
3281 PsGetCurrentThread());
3283 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
3286 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
3288 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
3292 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3293 AFS_TRACE_LEVEL_VERBOSE,
3294 "AFSSetVolumeState Releasing Fcb extents lock %08lX EXCL %08lX\n",
3295 &pFcb->NPFcb->Specific.File.ExtentsResource,
3296 PsGetCurrentThread());
3298 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
3301 // And get rid of them (note this involves waiting
3302 // for any writes or reads to the cache to complete)
3305 AFSTearDownFcbExtents( pFcb,
3309 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
3312 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
3314 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
3319 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3327 AFSSetNetworkState( IN AFSNetworkStatusCB *NetworkStatus)
3330 NTSTATUS ntStatus = STATUS_SUCCESS;
3335 if( AFSGlobalRoot == NULL)
3338 try_return( ntStatus);
3341 AFSAcquireExcl( AFSGlobalRoot->VolumeLock,
3345 // Set the network state according to the information
3348 if( NetworkStatus->Online)
3351 ClearFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3356 SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3359 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3370 AFSValidateDirectoryCache( IN AFSObjectInfoCB *ObjectInfo,
3374 NTSTATUS ntStatus = STATUS_SUCCESS;
3375 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3376 BOOLEAN bAcquiredLock = FALSE;
3377 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
3378 AFSFcb *pFcb = NULL;
3383 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3384 AFS_TRACE_LEVEL_VERBOSE,
3385 "AFSValidateDirectoryCache Validating content for FID %08lX-%08lX-%08lX-%08lX\n",
3386 ObjectInfo->FileId.Cell,
3387 ObjectInfo->FileId.Volume,
3388 ObjectInfo->FileId.Vnode,
3389 ObjectInfo->FileId.Unique);
3391 if( !ExIsResourceAcquiredLite( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock))
3394 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3395 AFS_TRACE_LEVEL_VERBOSE,
3396 "AFSValidateDirectoryCache Acquiring DirectoryNodeHdr.TreeLock lock %08lX EXCL %08lX\n",
3397 ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3398 PsGetCurrentThread());
3400 AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3403 bAcquiredLock = TRUE;
3407 // Check for inconsistency between DirectoryNodeList and DirectoryNodeCount
3410 if ( ObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL &&
3411 ObjectInfo->Specific.Directory.DirectoryNodeCount > 0)
3414 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3415 AFS_TRACE_LEVEL_ERROR,
3416 "AFSValidateDirectoryCache Empty Node List but Non-Zero Node Count %08lX for dir FID %08lX-%08lX-%08lX-%08lX\n",
3417 ObjectInfo->Specific.Directory.DirectoryNodeCount,
3418 ObjectInfo->FileId.Cell,
3419 ObjectInfo->FileId.Volume,
3420 ObjectInfo->FileId.Vnode,
3421 ObjectInfo->FileId.Unique);
3425 // Reset the directory list information by clearing all valid entries
3428 pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3430 while( pCurrentDirEntry != NULL)
3433 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3435 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
3439 // If this entry has been deleted then process it here
3442 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
3443 pCurrentDirEntry->OpenReferenceCount == 0)
3446 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3447 AFS_TRACE_LEVEL_VERBOSE,
3448 "AFSValidateDirectoryCache Deleting dir entry %p name %wZ\n",
3450 &pCurrentDirEntry->NameInformation.FileName);
3452 AFSDeleteDirEntry( ObjectInfo,
3458 ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID);
3460 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3461 AFS_TRACE_LEVEL_VERBOSE,
3462 "AFSValidateDirectoryCache Clear VALID flag on DE %p Reference count %08lX\n",
3464 pCurrentDirEntry->OpenReferenceCount);
3467 // We pull the short name from the parent tree since it could change below
3470 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
3473 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3474 AFS_TRACE_LEVEL_VERBOSE,
3475 "AFSValidateDirectoryCache Removing DE %p (%08lX) from shortname tree for %wZ\n",
3477 pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3478 &pCurrentDirEntry->NameInformation.FileName);
3480 AFSRemoveShortNameDirEntry( &ObjectInfo->Specific.Directory.ShortNameTree,
3483 ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3488 pCurrentDirEntry = pNextDirEntry;
3492 // Reget the directory contents
3495 ntStatus = AFSVerifyDirectoryContent( ObjectInfo,
3498 if ( !NT_SUCCESS( ntStatus))
3500 try_return( ntStatus);
3504 // Now start again and tear down any entries not valid
3507 pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3509 while( pCurrentDirEntry != NULL)
3512 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3514 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID))
3517 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3518 !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME) &&
3519 pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex > 0)
3522 if( ObjectInfo->Specific.Directory.ShortNameTree == NULL)
3525 ObjectInfo->Specific.Directory.ShortNameTree = pCurrentDirEntry;
3527 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3528 AFS_TRACE_LEVEL_VERBOSE,
3529 "AFSValidateDirectoryCache Insert DE %p to head of shortname tree for %wZ\n",
3531 &pCurrentDirEntry->NameInformation.FileName);
3533 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3538 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfo->Specific.Directory.ShortNameTree,
3541 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3542 AFS_TRACE_LEVEL_VERBOSE,
3543 "AFSValidateDirectoryCache Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
3545 pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3546 &pCurrentDirEntry->NameInformation.FileName);
3550 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3552 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3553 AFS_TRACE_LEVEL_VERBOSE,
3554 "AFSValidateDirectoryCache Insert DE %p to shortname tree for %wZ\n",
3556 &pCurrentDirEntry->NameInformation.FileName);
3561 pCurrentDirEntry = pNextDirEntry;
3566 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3567 AFS_TRACE_LEVEL_VERBOSE,
3568 "AFSValidateDirectoryCache Processing INVALID DE %p Reference count %08lX\n",
3570 pCurrentDirEntry->OpenReferenceCount);
3572 if( pCurrentDirEntry->OpenReferenceCount == 0)
3575 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3576 AFS_TRACE_LEVEL_VERBOSE,
3577 "AFSValidateDirectoryCache Deleting dir entry %wZ from parent FID %08lX-%08lX-%08lX-%08lX\n",
3578 &pCurrentDirEntry->NameInformation.FileName,
3579 ObjectInfo->FileId.Cell,
3580 ObjectInfo->FileId.Volume,
3581 ObjectInfo->FileId.Vnode,
3582 ObjectInfo->FileId.Unique);
3584 AFSDeleteDirEntry( ObjectInfo,
3590 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3591 AFS_TRACE_LEVEL_VERBOSE,
3592 "AFSValidateDirectoryCache Setting dir entry %p Name %wZ DELETED in parent FID %08lX-%08lX-%08lX-%08lX\n",
3594 &pCurrentDirEntry->NameInformation.FileName,
3595 ObjectInfo->FileId.Cell,
3596 ObjectInfo->FileId.Volume,
3597 ObjectInfo->FileId.Vnode,
3598 ObjectInfo->FileId.Unique);
3600 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
3602 AFSRemoveNameEntry( ObjectInfo,
3606 pCurrentDirEntry = pNextDirEntry;
3610 if( !AFSValidateDirList( ObjectInfo))
3613 AFSPrint("AFSValidateDirectoryCache Invalid count ...\n");
3622 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3630 AFSIsVolumeFID( IN AFSFileID *FileID)
3633 BOOLEAN bIsVolume = FALSE;
3635 if( FileID->Vnode == 1 &&
3636 FileID->Unique == 1)
3646 AFSIsFinalNode( IN AFSFcb *Fcb)
3649 BOOLEAN bIsFinalNode = FALSE;
3651 if( Fcb->Header.NodeTypeCode == AFS_ROOT_FCB ||
3652 Fcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB ||
3653 Fcb->Header.NodeTypeCode == AFS_FILE_FCB ||
3654 Fcb->Header.NodeTypeCode == AFS_DFS_LINK_FCB ||
3655 Fcb->Header.NodeTypeCode == AFS_INVALID_FCB )
3658 bIsFinalNode = TRUE;
3663 ASSERT( Fcb->Header.NodeTypeCode == AFS_MOUNT_POINT_FCB ||
3664 Fcb->Header.NodeTypeCode == AFS_SYMBOLIC_LINK_FCB);
3667 return bIsFinalNode;
3671 AFSUpdateMetaData( IN AFSDirectoryCB *DirEntry,
3672 IN AFSDirEnumEntry *DirEnumEntry)
3675 NTSTATUS ntStatus = STATUS_SUCCESS;
3676 UNICODE_STRING uniTargetName;
3677 AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
3682 pObjectInfo->TargetFileId = DirEnumEntry->TargetFileId;
3684 pObjectInfo->Expiration = DirEnumEntry->Expiration;
3686 pObjectInfo->DataVersion = DirEnumEntry->DataVersion;
3688 pObjectInfo->FileType = DirEnumEntry->FileType;
3690 pObjectInfo->CreationTime = DirEnumEntry->CreationTime;
3692 pObjectInfo->LastAccessTime = DirEnumEntry->LastAccessTime;
3694 pObjectInfo->LastWriteTime = DirEnumEntry->LastWriteTime;
3696 pObjectInfo->ChangeTime = DirEnumEntry->ChangeTime;
3698 pObjectInfo->EndOfFile = DirEnumEntry->EndOfFile;
3700 pObjectInfo->AllocationSize = DirEnumEntry->AllocationSize;
3702 pObjectInfo->FileAttributes = DirEnumEntry->FileAttributes;
3704 if( pObjectInfo->FileType == AFS_FILE_TYPE_MOUNTPOINT)
3707 pObjectInfo->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
3710 if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK ||
3711 pObjectInfo->FileType == AFS_FILE_TYPE_DFSLINK)
3714 pObjectInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
3717 pObjectInfo->EaSize = DirEnumEntry->EaSize;
3719 pObjectInfo->Links = DirEnumEntry->Links;
3721 if( DirEnumEntry->TargetNameLength > 0 &&
3722 ( DirEntry->NameInformation.TargetName.Length != DirEnumEntry->TargetNameLength ||
3723 DirEntry->ObjectInformation->DataVersion.QuadPart != DirEnumEntry->DataVersion.QuadPart))
3727 // Update the target name information if needed
3730 uniTargetName.Length = (USHORT)DirEnumEntry->TargetNameLength;
3732 uniTargetName.MaximumLength = uniTargetName.Length;
3734 uniTargetName.Buffer = (WCHAR *)((char *)DirEnumEntry + DirEnumEntry->TargetNameOffset);
3736 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3739 if( DirEntry->NameInformation.TargetName.Length == 0 ||
3740 RtlCompareUnicodeString( &uniTargetName,
3741 &DirEntry->NameInformation.TargetName,
3746 // Update the target name
3749 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3751 uniTargetName.Buffer,
3752 uniTargetName.Length);
3754 if( !NT_SUCCESS( ntStatus))
3757 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3759 try_return( ntStatus);
3763 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3765 else if( DirEntry->NameInformation.TargetName.Length > 0 &&
3766 DirEntry->ObjectInformation->DataVersion.QuadPart != DirEnumEntry->DataVersion.QuadPart)
3769 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3772 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER) &&
3773 DirEntry->NameInformation.TargetName.Buffer != NULL)
3775 AFSExFreePoolWithTag( DirEntry->NameInformation.TargetName.Buffer, AFS_NAME_BUFFER_FIVE_TAG);
3778 ClearFlag( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER);
3780 DirEntry->NameInformation.TargetName.Length = 0;
3781 DirEntry->NameInformation.TargetName.MaximumLength = 0;
3782 DirEntry->NameInformation.TargetName.Buffer = NULL;
3784 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3796 AFSValidateEntry( IN AFSDirectoryCB *DirEntry,
3798 IN BOOLEAN FastCall,
3799 IN BOOLEAN bSafeToPurge)
3802 NTSTATUS ntStatus = STATUS_SUCCESS;
3803 LARGE_INTEGER liSystemTime;
3804 AFSDirEnumEntry *pDirEnumEntry = NULL;
3805 AFSFcb *pCurrentFcb = NULL;
3806 BOOLEAN bReleaseFcb = FALSE;
3807 AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
3813 // If we have an Fcb hanging off the directory entry then be sure to acquire the locks in the
3817 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3818 AFS_TRACE_LEVEL_VERBOSE_2,
3819 "AFSValidateEntry Validating entry %wZ FID %08lX-%08lX-%08lX-%08lX FastCall %u\n",
3820 &DirEntry->NameInformation.FileName,
3821 pObjectInfo->FileId.Cell,
3822 pObjectInfo->FileId.Volume,
3823 pObjectInfo->FileId.Vnode,
3824 pObjectInfo->FileId.Unique,
3828 // If this is a fake node then bail since the service knows nothing about it
3831 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_FAKE))
3834 try_return( ntStatus);
3838 // This routine ensures that the current entry is valid by:
3840 // 1) Checking that the expiration time is non-zero and after where we
3844 KeQuerySystemTime( &liSystemTime);
3846 if( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) &&
3847 !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
3848 !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA) &&
3849 pObjectInfo->Expiration.QuadPart >= liSystemTime.QuadPart)
3852 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3853 AFS_TRACE_LEVEL_VERBOSE_2,
3854 "AFSValidateEntry Directory entry %wZ FID %08lX-%08lX-%08lX-%08lX VALID\n",
3855 &DirEntry->NameInformation.FileName,
3856 pObjectInfo->FileId.Cell,
3857 pObjectInfo->FileId.Volume,
3858 pObjectInfo->FileId.Vnode,
3859 pObjectInfo->FileId.Unique);
3861 try_return( ntStatus);
3865 // This node requires updating
3868 ntStatus = AFSEvaluateTargetByID( pObjectInfo,
3873 if( !NT_SUCCESS( ntStatus))
3876 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3877 AFS_TRACE_LEVEL_ERROR,
3878 "AFSValidateEntry Failed to evaluate entry FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3880 &DirEntry->NameInformation.FileName,
3881 pObjectInfo->FileId.Cell,
3882 pObjectInfo->FileId.Volume,
3883 pObjectInfo->FileId.Vnode,
3884 pObjectInfo->FileId.Unique,
3888 // Failed validation of node so return access-denied
3891 try_return( ntStatus);
3894 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3895 AFS_TRACE_LEVEL_VERBOSE,
3896 "AFSValidateEntry Validating entry FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX DV %I64X returned DV %I64X FT %d\n",
3898 &DirEntry->NameInformation.FileName,
3899 pObjectInfo->FileId.Cell,
3900 pObjectInfo->FileId.Volume,
3901 pObjectInfo->FileId.Vnode,
3902 pObjectInfo->FileId.Unique,
3903 pObjectInfo->DataVersion.QuadPart,
3904 pDirEnumEntry->DataVersion.QuadPart,
3905 pDirEnumEntry->FileType);
3909 // Based on the file type, process the node
3912 switch( pDirEnumEntry->FileType)
3915 case AFS_FILE_TYPE_MOUNTPOINT:
3919 // Update the metadata for the entry
3922 ntStatus = AFSUpdateMetaData( DirEntry,
3925 if( NT_SUCCESS( ntStatus))
3928 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
3934 case AFS_FILE_TYPE_SYMLINK:
3935 case AFS_FILE_TYPE_DFSLINK:
3939 // Update the metadata for the entry
3942 ntStatus = AFSUpdateMetaData( DirEntry,
3945 if( NT_SUCCESS( ntStatus))
3948 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
3954 case AFS_FILE_TYPE_FILE:
3957 BOOLEAN bPurgeExtents = FALSE;
3960 // For a file where the data version has become invalid we need to
3961 // fail any current extent requests and purge the cache for the file
3962 // Can't hold the Fcb resource while doing this
3965 if( pObjectInfo->Fcb != NULL &&
3966 (pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart ||
3967 BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA)))
3970 pCurrentFcb = pObjectInfo->Fcb;
3972 if( !ExIsResourceAcquiredLite( &pCurrentFcb->NPFcb->Resource))
3975 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3976 AFS_TRACE_LEVEL_VERBOSE,
3977 "AFSValidateEntry Acquiring Fcb lock %08lX EXCL %08lX\n",
3978 &pCurrentFcb->NPFcb->Resource,
3979 PsGetCurrentThread());
3981 AFSAcquireExcl( &pCurrentFcb->NPFcb->Resource,
3987 if( pCurrentFcb != NULL)
3990 IO_STATUS_BLOCK stIoStatus;
3992 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3993 AFS_TRACE_LEVEL_VERBOSE_2,
3994 "AFSValidateEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3995 &DirEntry->NameInformation.FileName,
3996 pObjectInfo->FileId.Cell,
3997 pObjectInfo->FileId.Volume,
3998 pObjectInfo->FileId.Vnode,
3999 pObjectInfo->FileId.Unique);
4001 if ( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
4004 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4005 AFS_TRACE_LEVEL_VERBOSE,
4006 "AFSValidateEntry DV Change %wZ FID %08lX-%08lX-%08lX-%08lX (%08lX != %08lX)\n",
4007 &DirEntry->NameInformation.FileName,
4008 pObjectInfo->FileId.Cell,
4009 pObjectInfo->FileId.Volume,
4010 pObjectInfo->FileId.Vnode,
4011 pObjectInfo->FileId.Unique,
4012 pObjectInfo->DataVersion.LowPart,
4013 pDirEnumEntry->DataVersion.LowPart
4016 bPurgeExtents = TRUE;
4022 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
4024 bPurgeExtents = TRUE;
4026 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4027 AFS_TRACE_LEVEL_VERBOSE,
4028 "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4029 &DirEntry->NameInformation.FileName,
4030 pObjectInfo->FileId.Cell,
4031 pObjectInfo->FileId.Volume,
4032 pObjectInfo->FileId.Vnode,
4033 pObjectInfo->FileId.Unique);
4035 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
4041 CcFlushCache( &pCurrentFcb->NPFcb->SectionObjectPointers,
4046 if( !NT_SUCCESS( stIoStatus.Status))
4049 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
4050 AFS_TRACE_LEVEL_ERROR,
4051 "AFSValidateEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
4052 &DirEntry->NameInformation.FileName,
4053 pObjectInfo->FileId.Cell,
4054 pObjectInfo->FileId.Volume,
4055 pObjectInfo->FileId.Vnode,
4056 pObjectInfo->FileId.Unique,
4058 stIoStatus.Information);
4060 ntStatus = stIoStatus.Status;
4063 if ( bPurgeExtents &&
4064 pObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
4067 if ( !CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
4073 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
4074 AFS_TRACE_LEVEL_WARNING,
4075 "AFSValidateEntry CcPurgeCacheSection failure %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4076 &DirEntry->NameInformation.FileName,
4077 pObjectInfo->FileId.Cell,
4078 pObjectInfo->FileId.Volume,
4079 pObjectInfo->FileId.Vnode,
4080 pObjectInfo->FileId.Unique);
4082 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
4086 __except( EXCEPTION_EXECUTE_HANDLER)
4088 ntStatus = GetExceptionCode();
4092 "EXCEPTION - AFSValidateEntry CcFlushCache or CcPurgeCacheSection %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
4093 &DirEntry->NameInformation.FileName,
4094 pObjectInfo->FileId.Cell,
4095 pObjectInfo->FileId.Volume,
4096 pObjectInfo->FileId.Vnode,
4097 pObjectInfo->FileId.Unique,
4100 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
4109 SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
4114 AFSReleaseResource( &pCurrentFcb->NPFcb->Resource);
4116 bReleaseFcb = FALSE;
4118 if ( bPurgeExtents &&
4121 AFSFlushExtents( pCurrentFcb,
4128 // Update the metadata for the entry but only if it is safe to do so.
4129 // If it was determined that a data version change has occurred or
4130 // that a pending data verification was required, do not update the
4131 // ObjectInfo meta data or the FileObject size information. That
4132 // way it is consistent for the next time that the data is verified
4136 if ( !(bPurgeExtents && bSafeToPurge))
4139 ntStatus = AFSUpdateMetaData( DirEntry,
4142 if( !NT_SUCCESS( ntStatus))
4145 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4146 AFS_TRACE_LEVEL_ERROR,
4147 "AFSValidateEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
4148 &DirEntry->NameInformation.FileName,
4149 pObjectInfo->FileId.Cell,
4150 pObjectInfo->FileId.Volume,
4151 pObjectInfo->FileId.Vnode,
4152 pObjectInfo->FileId.Unique,
4158 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
4161 // Update file sizes
4164 if( pObjectInfo->Fcb != NULL)
4166 FILE_OBJECT *pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
4168 pObjectInfo->Fcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart;
4169 pObjectInfo->Fcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart;
4170 pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
4172 if ( pCCFileObject != NULL)
4174 CcSetFileSizes( pCCFileObject,
4175 (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
4182 case AFS_FILE_TYPE_DIRECTORY:
4185 AFSDirectoryCB *pCurrentDirEntry = NULL;
4187 if( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
4191 // For a directory or root entry flush the content of
4192 // the directory enumeration.
4195 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4196 AFS_TRACE_LEVEL_VERBOSE,
4197 "AFSValidateEntry Acquiring DirectoryNodeHdr.TreeLock lock %08lX EXCL %08lX\n",
4198 pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
4199 PsGetCurrentThread());
4201 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
4204 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4205 AFS_TRACE_LEVEL_VERBOSE_2,
4206 "AFSValidateEntry Validating directory content for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4207 &DirEntry->NameInformation.FileName,
4208 pObjectInfo->FileId.Cell,
4209 pObjectInfo->FileId.Volume,
4210 pObjectInfo->FileId.Vnode,
4211 pObjectInfo->FileId.Unique);
4213 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
4216 ntStatus = AFSValidateDirectoryCache( pObjectInfo,
4219 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
4222 if( !NT_SUCCESS( ntStatus))
4225 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4226 AFS_TRACE_LEVEL_ERROR,
4227 "AFSValidateEntry Failed to re-enumerate %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4228 &DirEntry->NameInformation.FileName,
4229 pObjectInfo->FileId.Cell,
4230 pObjectInfo->FileId.Volume,
4231 pObjectInfo->FileId.Vnode,
4232 pObjectInfo->FileId.Unique,
4240 // Update the metadata for the entry
4243 ntStatus = AFSUpdateMetaData( DirEntry,
4246 if( NT_SUCCESS( ntStatus))
4249 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
4257 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4258 AFS_TRACE_LEVEL_WARNING,
4259 "AFSValidateEntry Attempt to verify node of type %d FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4260 pObjectInfo->FileType,
4262 &DirEntry->NameInformation.FileName,
4263 pObjectInfo->FileId.Cell,
4264 pObjectInfo->FileId.Volume,
4265 pObjectInfo->FileId.Vnode,
4266 pObjectInfo->FileId.Unique);
4276 AFSReleaseResource( &pCurrentFcb->NPFcb->Resource);
4279 if( pDirEnumEntry != NULL)
4282 AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_2_TAG);
4290 AFSInitializeSpecialShareNameList()
4293 NTSTATUS ntStatus = STATUS_SUCCESS;
4294 AFSDirectoryCB *pDirNode = NULL, *pLastDirNode = NULL;
4295 AFSObjectInfoCB *pObjectInfoCB = NULL;
4296 UNICODE_STRING uniShareName;
4297 ULONG ulEntryLength = 0;
4298 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
4303 RtlInitUnicodeString( &uniShareName,
4306 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
4309 if( pObjectInfoCB == NULL)
4312 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4315 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4316 AFS_TRACE_LEVEL_VERBOSE,
4317 "AFSInitializeSpecialShareNameList (srvsvc) Initializing count (1) on object %08lX\n",
4320 pObjectInfoCB->ObjectReferenceCount = 1;
4322 pObjectInfoCB->FileType = AFS_FILE_TYPE_SPECIAL_SHARE_NAME;
4324 ulEntryLength = sizeof( AFSDirectoryCB) +
4325 uniShareName.Length;
4327 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
4331 if( pDirNode == NULL)
4334 AFSDeleteObjectInfo( pObjectInfoCB);
4336 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4339 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
4340 sizeof( AFSNonPagedDirectoryCB),
4341 AFS_DIR_ENTRY_NP_TAG);
4343 if( pNonPagedDirEntry == NULL)
4346 ExFreePool( pDirNode);
4348 AFSDeleteObjectInfo( pObjectInfoCB);
4350 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4353 RtlZeroMemory( pDirNode,
4356 RtlZeroMemory( pNonPagedDirEntry,
4357 sizeof( AFSNonPagedDirectoryCB));
4359 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
4361 pDirNode->NonPaged = pNonPagedDirEntry;
4363 pDirNode->ObjectInformation = pObjectInfoCB;
4369 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_PIPE_SERVICE);
4371 pDirNode->NameInformation.FileName.Length = uniShareName.Length;
4373 pDirNode->NameInformation.FileName.MaximumLength = uniShareName.Length;
4375 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
4377 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
4378 uniShareName.Buffer,
4379 pDirNode->NameInformation.FileName.Length);
4381 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
4384 AFSSpecialShareNames = pDirNode;
4386 pLastDirNode = pDirNode;
4389 RtlInitUnicodeString( &uniShareName,
4392 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
4395 if( pObjectInfoCB == NULL)
4398 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4401 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4402 AFS_TRACE_LEVEL_VERBOSE,
4403 "AFSInitializeSpecialShareNameList (ipc$) Initializing count (1) on object %08lX\n",
4406 pObjectInfoCB->ObjectReferenceCount = 1;
4408 pObjectInfoCB->FileType = AFS_FILE_TYPE_SPECIAL_SHARE_NAME;
4410 ulEntryLength = sizeof( AFSDirectoryCB) +
4411 uniShareName.Length;
4413 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
4417 if( pDirNode == NULL)
4420 AFSDeleteObjectInfo( pObjectInfoCB);
4422 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4425 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
4426 sizeof( AFSNonPagedDirectoryCB),
4427 AFS_DIR_ENTRY_NP_TAG);
4429 if( pNonPagedDirEntry == NULL)
4432 ExFreePool( pDirNode);
4434 AFSDeleteObjectInfo( pObjectInfoCB);
4436 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4439 RtlZeroMemory( pDirNode,
4442 RtlZeroMemory( pNonPagedDirEntry,
4443 sizeof( AFSNonPagedDirectoryCB));
4445 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
4447 pDirNode->NonPaged = pNonPagedDirEntry;
4449 pDirNode->ObjectInformation = pObjectInfoCB;
4455 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_IPC);
4457 pDirNode->NameInformation.FileName.Length = uniShareName.Length;
4459 pDirNode->NameInformation.FileName.MaximumLength = uniShareName.Length;
4461 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
4463 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
4464 uniShareName.Buffer,
4465 pDirNode->NameInformation.FileName.Length);
4467 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
4470 pLastDirNode->ListEntry.fLink = pDirNode;
4472 pDirNode->ListEntry.bLink = pLastDirNode;
4476 if( !NT_SUCCESS( ntStatus))
4479 if( AFSSpecialShareNames != NULL)
4482 pDirNode = AFSSpecialShareNames;
4484 while( pDirNode != NULL)
4487 pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
4489 AFSDeleteObjectInfo( pDirNode->ObjectInformation);
4491 ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
4493 ExFreePool( pDirNode->NonPaged);
4495 ExFreePool( pDirNode);
4497 pDirNode = pLastDirNode;
4500 AFSSpecialShareNames = NULL;
4509 AFSGetSpecialShareNameEntry( IN UNICODE_STRING *ShareName,
4510 IN UNICODE_STRING *SecondaryName)
4513 AFSDirectoryCB *pDirectoryCB = NULL;
4514 ULONGLONG ullHash = 0;
4515 UNICODE_STRING uniFullShareName;
4521 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4522 AFS_TRACE_LEVEL_VERBOSE_2,
4523 "AFSGetSpecialShareNameEntry share name %wZ secondary name %wZ\n",
4527 uniFullShareName = *ShareName;
4530 // Generate our hash value
4533 ullHash = AFSGenerateCRC( &uniFullShareName,
4537 // Loop through our special share names to see if this is one of them
4540 pDirectoryCB = AFSSpecialShareNames;
4542 while( pDirectoryCB != NULL)
4545 if( ullHash == pDirectoryCB->CaseInsensitiveTreeEntry.HashIndex)
4551 pDirectoryCB = (AFSDirectoryCB *)pDirectoryCB->ListEntry.fLink;
4555 return pDirectoryCB;
4559 AFSWaitOnQueuedFlushes( IN AFSFcb *Fcb)
4563 // Block on the queue flush event
4566 KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
4576 AFSWaitOnQueuedReleases()
4579 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
4582 // Block on the queue flush event
4585 KeWaitForSingleObject( &pRDRDeviceExt->Specific.RDR.QueuedReleaseExtentEvent,
4595 AFSIsEqualFID( IN AFSFileID *FileId1,
4596 IN AFSFileID *FileId2)
4599 BOOLEAN bIsEqual = FALSE;
4601 if( FileId1->Hash == FileId2->Hash &&
4602 FileId1->Unique == FileId2->Unique &&
4603 FileId1->Vnode == FileId2->Vnode &&
4604 FileId1->Volume == FileId2->Volume &&
4605 FileId1->Cell == FileId2->Cell)
4615 AFSResetDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB)
4618 NTSTATUS ntStatus = STATUS_SUCCESS;
4619 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
4624 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
4627 // Reset the directory list information
4630 pCurrentDirEntry = ObjectInfoCB->Specific.Directory.DirectoryNodeListHead;
4632 while( pCurrentDirEntry != NULL)
4635 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
4637 if( pCurrentDirEntry->OpenReferenceCount == 0)
4640 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
4641 AFS_TRACE_LEVEL_VERBOSE,
4642 "AFSResetDirectoryContent Deleting dir entry %p for %wZ\n",
4644 &pCurrentDirEntry->NameInformation.FileName);
4646 AFSDeleteDirEntry( ObjectInfoCB,
4652 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
4653 AFS_TRACE_LEVEL_VERBOSE,
4654 "AFSResetDirectoryContent Setting DELETE flag in dir entry %p for %wZ\n",
4656 &pCurrentDirEntry->NameInformation.FileName);
4658 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
4660 AFSRemoveNameEntry( ObjectInfoCB,
4664 pCurrentDirEntry = pNextDirEntry;
4667 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = NULL;
4669 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = NULL;
4671 ObjectInfoCB->Specific.Directory.ShortNameTree = NULL;
4673 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = NULL;
4675 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = NULL;
4677 ObjectInfoCB->Specific.Directory.DirectoryNodeCount = 0;
4679 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
4680 AFS_TRACE_LEVEL_VERBOSE,
4681 "AFSResetDirectoryContent Reset count to 0 on parent FID %08lX-%08lX-%08lX-%08lX\n",
4682 ObjectInfoCB->FileId.Cell,
4683 ObjectInfoCB->FileId.Volume,
4684 ObjectInfoCB->FileId.Vnode,
4685 ObjectInfoCB->FileId.Unique);
4692 AFSEnumerateGlobalRoot( IN GUID *AuthGroup)
4695 NTSTATUS ntStatus = STATUS_SUCCESS;
4696 AFSDirectoryCB *pDirGlobalDirNode = NULL;
4697 UNICODE_STRING uniFullName;
4702 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4703 AFS_TRACE_LEVEL_VERBOSE,
4704 "AFSEnumerateGlobalRoot Acquiring GlobalRoot DirectoryNodeHdr.TreeLock lock %08lX EXCL %08lX\n",
4705 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4706 PsGetCurrentThread());
4708 AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4711 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
4714 try_return( ntStatus);
4718 // Initialize the root information
4721 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.ContentIndex = 1;
4724 // Enumerate the shares in the volume
4727 ntStatus = AFSEnumerateDirectory( AuthGroup,
4728 &AFSGlobalRoot->ObjectInformation,
4731 if( !NT_SUCCESS( ntStatus))
4734 try_return( ntStatus);
4737 pDirGlobalDirNode = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead;
4740 // Indicate the node is initialized
4743 SetFlag( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
4745 uniFullName.MaximumLength = PAGE_SIZE;
4746 uniFullName.Length = 0;
4748 uniFullName.Buffer = (WCHAR *)AFSLibExAllocatePoolWithTag( PagedPool,
4749 uniFullName.MaximumLength,
4750 AFS_GENERIC_MEMORY_12_TAG);
4752 if( uniFullName.Buffer == NULL)
4756 // Reset the directory content
4759 AFSResetDirectoryContent( &AFSGlobalRoot->ObjectInformation);
4761 ClearFlag( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
4763 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4767 // Populate our list of entries in the NP enumeration list
4770 while( pDirGlobalDirNode != NULL)
4773 uniFullName.Buffer[ 0] = L'\\';
4774 uniFullName.Buffer[ 1] = L'\\';
4776 uniFullName.Length = 2 * sizeof( WCHAR);
4778 RtlCopyMemory( &uniFullName.Buffer[ 2],
4779 AFSServerName.Buffer,
4780 AFSServerName.Length);
4782 uniFullName.Length += AFSServerName.Length;
4784 uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)] = L'\\';
4786 uniFullName.Length += sizeof( WCHAR);
4788 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
4789 pDirGlobalDirNode->NameInformation.FileName.Buffer,
4790 pDirGlobalDirNode->NameInformation.FileName.Length);
4792 uniFullName.Length += pDirGlobalDirNode->NameInformation.FileName.Length;
4794 AFSAddConnectionEx( &uniFullName,
4795 RESOURCEDISPLAYTYPE_SHARE,
4798 pDirGlobalDirNode = (AFSDirectoryCB *)pDirGlobalDirNode->ListEntry.fLink;
4801 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
4805 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4812 AFSIsRelativeName( IN UNICODE_STRING *Name)
4815 BOOLEAN bIsRelative = FALSE;
4817 if( Name->Length > 0 &&
4818 Name->Buffer[ 0] != L'\\')
4828 AFSIsAbsoluteAFSName( IN UNICODE_STRING *Name)
4830 UNICODE_STRING uniTempName;
4831 BOOLEAN bIsAbsolute = FALSE;
4834 // An absolute AFS path must begin with \afs\... or equivalent
4837 if ( Name->Length == 0 ||
4838 Name->Length <= AFSMountRootName.Length + sizeof( WCHAR) ||
4839 Name->Buffer[ 0] != L'\\' ||
4840 Name->Buffer[ AFSMountRootName.Length/sizeof( WCHAR)] != L'\\')
4846 uniTempName.Length = AFSMountRootName.Length;
4847 uniTempName.MaximumLength = AFSMountRootName.Length;
4849 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4850 uniTempName.MaximumLength,
4851 AFS_NAME_BUFFER_TWO_TAG);
4853 if( uniTempName.Buffer == NULL)
4859 RtlCopyMemory( uniTempName.Buffer,
4861 AFSMountRootName.Length);
4863 bIsAbsolute = (0 == RtlCompareUnicodeString( &uniTempName,
4867 AFSExFreePoolWithTag( uniTempName.Buffer,
4868 AFS_NAME_BUFFER_TWO_TAG);
4875 AFSUpdateName( IN UNICODE_STRING *Name)
4880 while( usIndex < Name->Length/sizeof( WCHAR))
4883 if( Name->Buffer[ usIndex] == L'/')
4886 Name->Buffer[ usIndex] = L'\\';
4896 AFSUpdateTargetName( IN OUT UNICODE_STRING *TargetName,
4897 IN OUT ULONG *Flags,
4898 IN WCHAR *NameBuffer,
4899 IN USHORT NameLength)
4902 NTSTATUS ntStatus = STATUS_SUCCESS;
4903 WCHAR *pTmpBuffer = NULL;
4909 // If we have enough space then just move in the name otherwise
4910 // allocate a new buffer
4913 if( TargetName->Length < NameLength)
4916 pTmpBuffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4918 AFS_NAME_BUFFER_FIVE_TAG);
4920 if( pTmpBuffer == NULL)
4923 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4926 if( BooleanFlagOn( *Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
4929 AFSExFreePoolWithTag( TargetName->Buffer, AFS_NAME_BUFFER_FIVE_TAG);
4932 TargetName->MaximumLength = NameLength;
4934 TargetName->Buffer = pTmpBuffer;
4936 SetFlag( *Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER);
4939 TargetName->Length = NameLength;
4941 RtlCopyMemory( TargetName->Buffer,
4943 TargetName->Length);
4946 // Update the name in the buffer
4949 AFSUpdateName( TargetName);
4960 AFSInitNameArray( IN AFSDirectoryCB *DirectoryCB,
4961 IN ULONG InitialElementCount)
4964 AFSNameArrayHdr *pNameArray = NULL;
4965 AFSNameArrayCB *pCurrentElement = NULL;
4966 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4972 if( InitialElementCount == 0)
4975 InitialElementCount = pDevExt->Specific.RDR.NameArrayLength;
4978 pNameArray = (AFSNameArrayHdr *)AFSExAllocatePoolWithTag( PagedPool,
4979 sizeof( AFSNameArrayHdr) +
4980 (InitialElementCount * sizeof( AFSNameArrayCB)),
4981 AFS_NAME_ARRAY_TAG);
4983 if( pNameArray == NULL)
4986 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
4987 AFS_TRACE_LEVEL_ERROR,
4988 "AFSInitNameArray Failed to allocate name array\n");
4990 try_return( pNameArray);
4993 RtlZeroMemory( pNameArray,
4994 sizeof( AFSNameArrayHdr) +
4995 (InitialElementCount * sizeof( AFSNameArrayCB)));
4997 pNameArray->MaxElementCount = InitialElementCount;
4999 if( DirectoryCB != NULL)
5002 pCurrentElement = &pNameArray->ElementArray[ 0];
5004 pNameArray->CurrentEntry = pCurrentElement;
5006 pNameArray->Count = 1;
5008 pNameArray->LinkCount = 0;
5010 lCount = InterlockedIncrement( &DirectoryCB->OpenReferenceCount);
5012 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5013 AFS_TRACE_LEVEL_VERBOSE,
5014 "AFSInitNameArray Increment count on %wZ DE %p Cnt %d\n",
5015 &DirectoryCB->NameInformation.FileName,
5019 pCurrentElement->DirectoryCB = DirectoryCB;
5021 pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
5023 pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
5025 if( pCurrentElement->FileId.Vnode == 1)
5028 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5031 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5032 AFS_TRACE_LEVEL_VERBOSE,
5033 "AFSInitNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5035 pCurrentElement->DirectoryCB,
5036 pCurrentElement->FileId.Cell,
5037 pCurrentElement->FileId.Volume,
5038 pCurrentElement->FileId.Vnode,
5039 pCurrentElement->FileId.Unique,
5040 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5041 pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5053 AFSPopulateNameArray( IN AFSNameArrayHdr *NameArray,
5054 IN UNICODE_STRING *Path,
5055 IN AFSDirectoryCB *DirectoryCB)
5058 NTSTATUS ntStatus = STATUS_SUCCESS;
5059 AFSNameArrayCB *pCurrentElement = NULL;
5060 UNICODE_STRING uniComponentName, uniRemainingPath;
5061 AFSObjectInfoCB *pCurrentObject = NULL;
5062 ULONG ulTotalCount = 0;
5064 USHORT usLength = 0;
5070 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5071 AFS_TRACE_LEVEL_VERBOSE,
5072 "AFSPopulateNameArray [NA:%p] passed Path %wZ DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5076 DirectoryCB->ObjectInformation->FileId.Cell,
5077 DirectoryCB->ObjectInformation->FileId.Volume,
5078 DirectoryCB->ObjectInformation->FileId.Vnode,
5079 DirectoryCB->ObjectInformation->FileId.Unique,
5080 &DirectoryCB->NameInformation.FileName,
5081 DirectoryCB->ObjectInformation->FileType);
5084 // Init some info in the header
5087 pCurrentElement = &NameArray->ElementArray[ 0];
5089 NameArray->CurrentEntry = pCurrentElement;
5092 // The first entry points at the root
5095 pCurrentElement->DirectoryCB = DirectoryCB->ObjectInformation->VolumeCB->DirectoryCB;
5097 lCount = InterlockedIncrement( &pCurrentElement->DirectoryCB->OpenReferenceCount);
5099 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5100 AFS_TRACE_LEVEL_VERBOSE,
5101 "AFSPopulateNameArray Increment count on volume %wZ DE %p Cnt %d\n",
5102 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5103 pCurrentElement->DirectoryCB,
5106 pCurrentElement->Component = DirectoryCB->ObjectInformation->VolumeCB->DirectoryCB->NameInformation.FileName;
5108 pCurrentElement->FileId = DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
5110 pCurrentElement->Flags = 0;
5112 if( pCurrentElement->FileId.Vnode == 1)
5115 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5118 NameArray->Count = 1;
5120 NameArray->LinkCount = 0;
5122 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5123 AFS_TRACE_LEVEL_VERBOSE,
5124 "AFSPopulateNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5126 pCurrentElement->DirectoryCB,
5127 pCurrentElement->FileId.Cell,
5128 pCurrentElement->FileId.Volume,
5129 pCurrentElement->FileId.Vnode,
5130 pCurrentElement->FileId.Unique,
5131 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5132 pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5135 // If the root is the parent then we are done ...
5138 if( &DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation == DirectoryCB->ObjectInformation)
5140 try_return( ntStatus);
5152 AFSPopulateNameArrayFromRelatedArray( IN AFSNameArrayHdr *NameArray,
5153 IN AFSNameArrayHdr *RelatedNameArray,
5154 IN AFSDirectoryCB *DirectoryCB)
5157 NTSTATUS ntStatus = STATUS_SUCCESS;
5158 AFSNameArrayCB *pCurrentElement = NULL, *pCurrentRelatedElement = NULL;
5159 UNICODE_STRING uniComponentName, uniRemainingPath;
5160 AFSObjectInfoCB *pObjectInfo = NULL;
5161 ULONG ulTotalCount = 0;
5163 USHORT usLength = 0;
5169 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5170 AFS_TRACE_LEVEL_VERBOSE,
5171 "AFSPopulateNameArray [NA:%p] passed RelatedNameArray %p DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5175 DirectoryCB->ObjectInformation->FileId.Cell,
5176 DirectoryCB->ObjectInformation->FileId.Volume,
5177 DirectoryCB->ObjectInformation->FileId.Vnode,
5178 DirectoryCB->ObjectInformation->FileId.Unique,
5179 &DirectoryCB->NameInformation.FileName,
5180 DirectoryCB->ObjectInformation->FileType);
5183 // Init some info in the header
5186 pCurrentElement = &NameArray->ElementArray[ 0];
5188 pCurrentRelatedElement = &RelatedNameArray->ElementArray[ 0];
5190 NameArray->Count = 0;
5192 NameArray->LinkCount = RelatedNameArray->LinkCount;
5195 // Populate the name array with the data from the related array
5201 pCurrentElement->DirectoryCB = pCurrentRelatedElement->DirectoryCB;
5203 pCurrentElement->Component = pCurrentRelatedElement->DirectoryCB->NameInformation.FileName;
5205 pCurrentElement->FileId = pCurrentElement->DirectoryCB->ObjectInformation->FileId;
5207 pCurrentElement->Flags = 0;
5209 if( pCurrentElement->FileId.Vnode == 1)
5212 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5215 lCount = InterlockedIncrement( &pCurrentElement->DirectoryCB->OpenReferenceCount);
5217 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5218 AFS_TRACE_LEVEL_VERBOSE,
5219 "AFSPopulateNameArrayFromRelatedArray Increment count on %wZ DE %p Cnt %d\n",
5220 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5221 pCurrentElement->DirectoryCB,
5224 lCount = InterlockedIncrement( &NameArray->Count);
5226 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5227 AFS_TRACE_LEVEL_VERBOSE,
5228 "AFSPopulateNameArrayFromRelatedArray [NA:%p] Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5231 pCurrentElement->DirectoryCB,
5232 pCurrentElement->FileId.Cell,
5233 pCurrentElement->FileId.Volume,
5234 pCurrentElement->FileId.Vnode,
5235 pCurrentElement->FileId.Unique,
5236 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5237 pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5239 if( pCurrentElement->DirectoryCB == DirectoryCB ||
5240 NameArray->Count == RelatedNameArray->Count)
5252 pCurrentRelatedElement++;
5255 NameArray->CurrentEntry = NameArray->Count > 0 ? pCurrentElement : NULL;
5262 AFSFreeNameArray( IN AFSNameArrayHdr *NameArray)
5265 NTSTATUS ntStatus = STATUS_SUCCESS;
5266 AFSNameArrayCB *pCurrentElement = NULL;
5267 LONG lCount, lElement;
5272 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5273 AFS_TRACE_LEVEL_VERBOSE,
5274 "AFSFreeNameArray [NA:%p]\n",
5277 for ( lElement = 0; lElement < NameArray->Count; lElement++)
5280 pCurrentElement = &NameArray->ElementArray[ lElement];
5282 lCount = InterlockedDecrement( &pCurrentElement->DirectoryCB->OpenReferenceCount);
5284 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5285 AFS_TRACE_LEVEL_VERBOSE,
5286 "AFSFreeNameArray Decrement count on %wZ DE %p Cnt %d\n",
5287 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5288 pCurrentElement->DirectoryCB,
5292 AFSExFreePoolWithTag( NameArray, AFS_NAME_ARRAY_TAG);
5299 AFSInsertNextElement( IN AFSNameArrayHdr *NameArray,
5300 IN AFSDirectoryCB *DirectoryCB)
5303 NTSTATUS ntStatus = STATUS_SUCCESS;
5304 AFSNameArrayCB *pCurrentElement = NULL;
5310 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5311 AFS_TRACE_LEVEL_VERBOSE,
5312 "AFSInsertNextElement [NA:%p] passed DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5315 DirectoryCB->ObjectInformation->FileId.Cell,
5316 DirectoryCB->ObjectInformation->FileId.Volume,
5317 DirectoryCB->ObjectInformation->FileId.Vnode,
5318 DirectoryCB->ObjectInformation->FileId.Unique,
5319 &DirectoryCB->NameInformation.FileName,
5320 DirectoryCB->ObjectInformation->FileType);
5322 if( NameArray->Count == NameArray->MaxElementCount)
5325 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5326 AFS_TRACE_LEVEL_ERROR,
5327 "AFSInsertNextElement [NA:%p] Name has reached Maximum Size\n",
5330 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5333 for ( lCount = 0; lCount < NameArray->Count; lCount++)
5336 if ( AFSIsEqualFID( &NameArray->ElementArray[ lCount].FileId,
5337 &DirectoryCB->ObjectInformation->FileId) )
5340 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5341 AFS_TRACE_LEVEL_WARNING,
5342 "AFSInsertNextElement [NA:%p] DE %p recursion Status %08X\n",
5345 STATUS_ACCESS_DENIED);
5347 try_return( ntStatus = STATUS_ACCESS_DENIED);
5351 if( NameArray->Count > 0)
5354 NameArray->CurrentEntry++;
5358 NameArray->CurrentEntry = &NameArray->ElementArray[ 0];
5361 pCurrentElement = NameArray->CurrentEntry;
5363 lCount = InterlockedIncrement( &NameArray->Count);
5365 lCount = InterlockedIncrement( &DirectoryCB->OpenReferenceCount);
5367 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5368 AFS_TRACE_LEVEL_VERBOSE,
5369 "AFSInsertNextElement Increment count on %wZ DE %p Cnt %d\n",
5370 &DirectoryCB->NameInformation.FileName,
5374 pCurrentElement->DirectoryCB = DirectoryCB;
5376 pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
5378 pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
5380 pCurrentElement->Flags = 0;
5382 if( pCurrentElement->FileId.Vnode == 1)
5385 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5388 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5389 AFS_TRACE_LEVEL_VERBOSE,
5390 "AFSInsertNextElement [NA:%p] Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5392 NameArray->Count - 1,
5393 pCurrentElement->DirectoryCB,
5394 pCurrentElement->FileId.Cell,
5395 pCurrentElement->FileId.Volume,
5396 pCurrentElement->FileId.Vnode,
5397 pCurrentElement->FileId.Unique,
5398 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5399 pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5410 AFSBackupEntry( IN AFSNameArrayHdr *NameArray)
5413 AFSDirectoryCB *pDirectoryCB = NULL;
5414 AFSNameArrayCB *pCurrentElement = NULL;
5415 BOOLEAN bVolumeRoot = FALSE;
5421 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5422 AFS_TRACE_LEVEL_VERBOSE,
5423 "AFSBackupEntry [NA:%p]\n",
5426 if( NameArray->Count == 0)
5429 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5430 AFS_TRACE_LEVEL_ERROR,
5431 "AFSBackupEntry [NA:%p] No more entries\n",
5434 try_return( pCurrentElement);
5437 lCount = InterlockedDecrement( &NameArray->CurrentEntry->DirectoryCB->OpenReferenceCount);
5439 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5440 AFS_TRACE_LEVEL_VERBOSE,
5441 "AFSBackupEntry Decrement count on %wZ DE %p Cnt %d\n",
5442 &NameArray->CurrentEntry->DirectoryCB->NameInformation.FileName,
5443 NameArray->CurrentEntry->DirectoryCB,
5446 NameArray->CurrentEntry->DirectoryCB = NULL;
5448 lCount = InterlockedDecrement( &NameArray->Count);
5452 NameArray->CurrentEntry = NULL;
5454 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5455 AFS_TRACE_LEVEL_ERROR,
5456 "AFSBackupEntry [NA:%p] No more entries\n",
5462 bVolumeRoot = BooleanFlagOn( NameArray->CurrentEntry->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5464 NameArray->CurrentEntry--;
5466 pCurrentElement = NameArray->CurrentEntry;
5468 pDirectoryCB = pCurrentElement->DirectoryCB;
5470 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5471 AFS_TRACE_LEVEL_VERBOSE,
5472 "AFSBackupEntry [NA:%p] Returning Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5474 NameArray->Count - 1,
5475 pCurrentElement->DirectoryCB,
5476 pCurrentElement->FileId.Cell,
5477 pCurrentElement->FileId.Volume,
5478 pCurrentElement->FileId.Vnode,
5479 pCurrentElement->FileId.Unique,
5480 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5481 pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5484 // If the entry we are removing is a volume root,
5485 // we must remove the mount point entry as well.
5486 // If the NameArray was constructed by checking the
5487 // share name via the service, the name array can
5488 // contain two volume roots in sequence without a
5489 // mount point separating them.
5493 !BooleanFlagOn( NameArray->CurrentEntry->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT))
5496 pDirectoryCB = AFSBackupEntry( NameArray);
5506 return pDirectoryCB;
5510 AFSGetParentEntry( IN AFSNameArrayHdr *NameArray)
5513 AFSDirectoryCB *pDirEntry = NULL;
5514 AFSNameArrayCB *pElement = NULL;
5519 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5520 AFS_TRACE_LEVEL_VERBOSE,
5521 "AFSGetParentEntry [NA:%p]\n",
5524 if( NameArray->Count == 0 ||
5525 NameArray->Count == 1)
5528 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5529 AFS_TRACE_LEVEL_ERROR,
5530 "AFSGetParentEntry [NA:%p] No more entries\n",
5533 try_return( pDirEntry = NULL);
5536 pElement = &NameArray->ElementArray[ NameArray->Count - 2];
5538 pDirEntry = pElement->DirectoryCB;
5540 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5541 AFS_TRACE_LEVEL_VERBOSE,
5542 "AFSGetParentEntry [NA:%p] Returning Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5544 NameArray->Count - 2,
5545 pElement->DirectoryCB,
5546 pElement->FileId.Cell,
5547 pElement->FileId.Volume,
5548 pElement->FileId.Vnode,
5549 pElement->FileId.Unique,
5550 &pElement->DirectoryCB->NameInformation.FileName,
5551 pElement->DirectoryCB->ObjectInformation->FileType);
5562 AFSResetNameArray( IN AFSNameArrayHdr *NameArray,
5563 IN AFSDirectoryCB *DirectoryCB)
5566 AFSNameArrayCB *pCurrentElement = NULL;
5567 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
5568 LONG lCount, lElement;
5573 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5574 AFS_TRACE_LEVEL_VERBOSE,
5575 "AFSResetNameArray [NA:%p] passed DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5578 DirectoryCB->ObjectInformation->FileId.Cell,
5579 DirectoryCB->ObjectInformation->FileId.Volume,
5580 DirectoryCB->ObjectInformation->FileId.Vnode,
5581 DirectoryCB->ObjectInformation->FileId.Unique,
5582 &DirectoryCB->NameInformation.FileName,
5583 DirectoryCB->ObjectInformation->FileType);
5585 // Dereference previous name array contents
5588 for ( lElement = 0; lElement < NameArray->Count; lElement++)
5591 pCurrentElement = &NameArray->ElementArray[ lElement];
5593 lCount = InterlockedDecrement( &pCurrentElement->DirectoryCB->OpenReferenceCount);
5595 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5596 AFS_TRACE_LEVEL_VERBOSE,
5597 "AFSResetNameArray Decrement count on %wZ DE %p Cnt %d\n",
5598 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5599 pCurrentElement->DirectoryCB,
5603 RtlZeroMemory( NameArray,
5604 sizeof( AFSNameArrayHdr) +
5605 ((pDevExt->Specific.RDR.NameArrayLength - 1) * sizeof( AFSNameArrayCB)));
5607 NameArray->MaxElementCount = pDevExt->Specific.RDR.NameArrayLength;
5609 if( DirectoryCB != NULL)
5612 pCurrentElement = &NameArray->ElementArray[ 0];
5614 NameArray->CurrentEntry = pCurrentElement;
5616 NameArray->Count = 1;
5618 NameArray->LinkCount = 0;
5620 lCount = InterlockedIncrement( &DirectoryCB->OpenReferenceCount);
5622 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5623 AFS_TRACE_LEVEL_VERBOSE,
5624 "AFSResetNameArray Increment count on %wZ DE %p Cnt %d\n",
5625 &DirectoryCB->NameInformation.FileName,
5629 pCurrentElement->DirectoryCB = DirectoryCB;
5631 pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
5633 pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
5635 pCurrentElement->Flags = 0;
5637 if( pCurrentElement->FileId.Vnode == 1)
5640 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5643 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5644 AFS_TRACE_LEVEL_VERBOSE,
5645 "AFSResetNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5647 pCurrentElement->DirectoryCB,
5648 pCurrentElement->FileId.Cell,
5649 pCurrentElement->FileId.Volume,
5650 pCurrentElement->FileId.Vnode,
5651 pCurrentElement->FileId.Unique,
5652 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5653 pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5661 AFSDumpNameArray( IN AFSNameArrayHdr *NameArray)
5664 AFSNameArrayCB *pCurrentElement = NULL;
5666 pCurrentElement = &NameArray->ElementArray[ 0];
5668 AFSPrint("AFSDumpNameArray Start (%d)\n", NameArray->Count);
5670 while( pCurrentElement->DirectoryCB != NULL)
5673 AFSPrint("FID %08lX-%08lX-%08lX-%08lX %wZ\n",
5674 pCurrentElement->FileId.Cell,
5675 pCurrentElement->FileId.Volume,
5676 pCurrentElement->FileId.Vnode,
5677 pCurrentElement->FileId.Unique,
5678 &pCurrentElement->DirectoryCB->NameInformation.FileName);
5683 AFSPrint("AFSDumpNameArray End\n\n");
5689 AFSSetEnumerationEvent( IN AFSFcb *Fcb)
5694 // Depending on the type of node, set the event
5697 switch( Fcb->Header.NodeTypeCode)
5700 case AFS_DIRECTORY_FCB:
5705 lCount = InterlockedIncrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
5715 AFSClearEnumerationEvent( IN AFSFcb *Fcb)
5721 // Depending on the type of node, set the event
5724 switch( Fcb->Header.NodeTypeCode)
5727 case AFS_DIRECTORY_FCB:
5732 ASSERT( Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0);
5734 lCount = InterlockedDecrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
5744 AFSIsEnumerationInProcess( IN AFSObjectInfoCB *ObjectInfo)
5747 BOOLEAN bIsInProcess = FALSE;
5752 if( ObjectInfo->Fcb == NULL)
5755 try_return( bIsInProcess);
5758 switch( ObjectInfo->Fcb->Header.NodeTypeCode)
5761 case AFS_DIRECTORY_FCB:
5766 if( ObjectInfo->Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0)
5769 bIsInProcess = TRUE;
5781 return bIsInProcess;
5785 AFSVerifyVolume( IN ULONGLONG ProcessId,
5786 IN AFSVolumeCB *VolumeCB)
5789 NTSTATUS ntStatus = STATUS_SUCCESS;
5796 AFSInitPIOCtlDirectoryCB( IN AFSObjectInfoCB *ObjectInfo)
5799 NTSTATUS ntStatus = STATUS_SUCCESS;
5800 AFSObjectInfoCB *pObjectInfoCB = NULL;
5801 AFSDirectoryCB *pDirNode = NULL;
5802 ULONG ulEntryLength = 0;
5803 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
5809 pObjectInfoCB = AFSAllocateObjectInfo( ObjectInfo,
5812 if( pObjectInfoCB == NULL)
5815 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5818 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
5819 AFS_TRACE_LEVEL_VERBOSE,
5820 "AFSInitPIOCtlDirectoryCB Initializing count (1) on object %08lX\n",
5823 pObjectInfoCB->ObjectReferenceCount = 1;
5825 pObjectInfoCB->FileType = AFS_FILE_TYPE_PIOCTL;
5827 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
5829 ulEntryLength = sizeof( AFSDirectoryCB) + AFSPIOCtlName.Length;
5831 pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
5835 if( pDirNode == NULL)
5838 AFSDeleteObjectInfo( pObjectInfoCB);
5840 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5843 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
5844 sizeof( AFSNonPagedDirectoryCB),
5845 AFS_DIR_ENTRY_NP_TAG);
5847 if( pNonPagedDirEntry == NULL)
5850 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5853 RtlZeroMemory( pDirNode,
5856 RtlZeroMemory( pNonPagedDirEntry,
5857 sizeof( AFSNonPagedDirectoryCB));
5859 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
5861 pDirNode->NonPaged = pNonPagedDirEntry;
5863 pDirNode->ObjectInformation = pObjectInfoCB;
5865 pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_PIOCTL_INDEX;
5871 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_FAKE);
5873 pDirNode->NameInformation.FileName.Length = AFSPIOCtlName.Length;
5875 pDirNode->NameInformation.FileName.MaximumLength = AFSPIOCtlName.Length;
5877 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
5879 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
5880 AFSPIOCtlName.Buffer,
5881 pDirNode->NameInformation.FileName.Length);
5883 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
5886 if ( InterlockedCompareExchangePointer( (PVOID *)&ObjectInfo->Specific.Directory.PIOCtlDirectoryCB, pDirNode, NULL) != NULL)
5889 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
5890 AFS_TRACE_LEVEL_WARNING,
5891 "AFSInitPIOCtlDirectoryCB Raced PIOCtlDirectoryCB %08lX pFcb %08lX\n",
5892 ObjectInfo->Specific.Directory.PIOCtlDirectoryCB,
5896 // Increment the open reference and handle on the node
5899 lCount = AFSObjectInfoIncrement( pDirNode->ObjectInformation);
5901 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
5902 AFS_TRACE_LEVEL_VERBOSE,
5903 "AFSInitPIOCtlDirectoryCB Increment count on Object %08lX Cnt %d\n",
5904 pDirNode->ObjectInformation,
5907 try_return( ntStatus = STATUS_REPARSE);
5912 if ( ntStatus != STATUS_SUCCESS)
5915 if ( pDirNode != NULL)
5918 AFSExFreePoolWithTag( pDirNode, AFS_DIR_ENTRY_TAG);
5921 if( pNonPagedDirEntry != NULL)
5924 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
5926 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
5929 if ( pObjectInfoCB != NULL)
5932 AFSDeleteObjectInfo( pObjectInfoCB);
5941 AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB,
5942 IN AFSDirectoryCB *DirectoryCB,
5943 IN UNICODE_STRING *ParentPathName,
5944 IN AFSNameArrayHdr *RelatedNameArray,
5946 OUT AFSFileInfoCB *FileInfo)
5949 NTSTATUS ntStatus = STATUS_SUCCESS;
5950 AFSDirEnumEntry *pDirEntry = NULL, *pLastDirEntry = NULL;
5951 UNICODE_STRING uniFullPathName;
5952 AFSNameArrayHdr *pNameArray = NULL;
5953 AFSVolumeCB *pVolumeCB = NULL;
5954 AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
5955 WCHAR *pwchBuffer = NULL;
5956 UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
5957 ULONG ulNameDifference = 0;
5964 // Retrieve a target name for the entry
5967 AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
5970 if( DirectoryCB->NameInformation.TargetName.Length == 0)
5973 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5975 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
5980 if( !NT_SUCCESS( ntStatus) ||
5981 pDirEntry->TargetNameLength == 0)
5984 if( pDirEntry != NULL)
5987 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
5990 try_return( ntStatus);
5993 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
5996 if( DirectoryCB->NameInformation.TargetName.Length == 0)
6000 // Update the target name
6003 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
6004 &DirectoryCB->Flags,
6005 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
6006 (USHORT)pDirEntry->TargetNameLength);
6008 if( !NT_SUCCESS( ntStatus))
6011 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6013 try_return( ntStatus);
6017 AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
6021 // Need to pass the full path in for parsing.
6024 if( AFSIsRelativeName( &DirectoryCB->NameInformation.TargetName))
6027 uniFullPathName.Length = 0;
6028 uniFullPathName.MaximumLength = ParentPathName->Length +
6030 DirectoryCB->NameInformation.TargetName.Length;
6032 uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6033 uniFullPathName.MaximumLength,
6034 AFS_NAME_BUFFER_SIX_TAG);
6036 if( uniFullPathName.Buffer == NULL)
6039 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6041 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6044 pwchBuffer = uniFullPathName.Buffer;
6046 RtlZeroMemory( uniFullPathName.Buffer,
6047 uniFullPathName.MaximumLength);
6049 RtlCopyMemory( uniFullPathName.Buffer,
6050 ParentPathName->Buffer,
6051 ParentPathName->Length);
6053 uniFullPathName.Length = ParentPathName->Length;
6055 if( uniFullPathName.Buffer[ (uniFullPathName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
6056 DirectoryCB->NameInformation.TargetName.Buffer[ 0] != L'\\')
6059 uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)] = L'\\';
6061 uniFullPathName.Length += sizeof( WCHAR);
6064 RtlCopyMemory( &uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)],
6065 DirectoryCB->NameInformation.TargetName.Buffer,
6066 DirectoryCB->NameInformation.TargetName.Length);
6068 uniFullPathName.Length += DirectoryCB->NameInformation.TargetName.Length;
6070 uniParsedName.Length = uniFullPathName.Length - ParentPathName->Length;
6071 uniParsedName.MaximumLength = uniParsedName.Length;
6073 uniParsedName.Buffer = &uniFullPathName.Buffer[ ParentPathName->Length/sizeof( WCHAR)];
6075 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6078 // We populate up to the current parent
6081 if( RelatedNameArray != NULL)
6084 pNameArray = AFSInitNameArray( NULL,
6085 RelatedNameArray->MaxElementCount);
6087 if( pNameArray == NULL)
6090 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6093 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
6100 pNameArray = AFSInitNameArray( NULL,
6103 if( pNameArray == NULL)
6106 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6109 ntStatus = AFSPopulateNameArray( pNameArray,
6114 if( !NT_SUCCESS( ntStatus))
6117 try_return( ntStatus);
6120 pVolumeCB = ParentDirectoryCB->ObjectInformation->VolumeCB;
6122 pParentDirEntry = ParentDirectoryCB;
6127 uniFullPathName.Length = 0;
6128 uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
6130 uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6131 uniFullPathName.MaximumLength,
6132 AFS_NAME_BUFFER_SEVEN_TAG);
6134 if( uniFullPathName.Buffer == NULL)
6137 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6139 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6142 pwchBuffer = uniFullPathName.Buffer;
6144 RtlZeroMemory( uniFullPathName.Buffer,
6145 uniFullPathName.MaximumLength);
6147 RtlCopyMemory( uniFullPathName.Buffer,
6148 DirectoryCB->NameInformation.TargetName.Buffer,
6149 DirectoryCB->NameInformation.TargetName.Length);
6151 uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6154 // This name should begin with the \afs server so parse it off and check it
6157 FsRtlDissectName( uniFullPathName,
6161 if( RtlCompareUnicodeString( &uniComponentName,
6166 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6168 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
6169 AFS_TRACE_LEVEL_ERROR,
6170 "AFSRetrieveFileAttributes Name %wZ contains invalid server name\n",
6173 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
6176 uniFullPathName = uniRemainingPath;
6178 uniParsedName = uniFullPathName;
6180 ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
6182 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6188 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
6191 if( pNameArray == NULL)
6194 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6197 pVolumeCB = AFSGlobalRoot;
6199 pParentDirEntry = AFSGlobalRoot->DirectoryCB;
6203 // Increment the ref count on the volume and dir entry for correct processing below
6206 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
6208 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6209 AFS_TRACE_LEVEL_VERBOSE,
6210 "AFSRetrieveFileAttributes Increment count on volume %08lX Cnt %d\n",
6214 lCount = InterlockedIncrement( &pParentDirEntry->OpenReferenceCount);
6216 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6217 AFS_TRACE_LEVEL_VERBOSE,
6218 "AFSRetrieveFileAttributes Increment count on %wZ DE %p Ccb %p Cnt %d\n",
6219 &pParentDirEntry->NameInformation.FileName,
6224 ntStatus = AFSLocateNameEntry( NULL,
6229 AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL,
6235 if( !NT_SUCCESS( ntStatus))
6239 // The volume lock was released on failure above
6240 // Except for STATUS_OBJECT_NAME_NOT_FOUND
6243 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
6246 if( pVolumeCB != NULL)
6249 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6251 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6252 AFS_TRACE_LEVEL_VERBOSE,
6253 "AFSRetrieveFileAttributes Decrement count on volume %08lX Cnt %d\n",
6258 if( pDirectoryEntry != NULL)
6261 lCount = InterlockedDecrement( &pDirectoryEntry->OpenReferenceCount);
6263 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6264 AFS_TRACE_LEVEL_VERBOSE,
6265 "AFSRetrieveFileAttributes Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6266 &pDirectoryEntry->NameInformation.FileName,
6274 lCount = InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
6276 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6277 AFS_TRACE_LEVEL_VERBOSE,
6278 "AFSRetrieveFileAttributes Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
6279 &pParentDirEntry->NameInformation.FileName,
6288 try_return( ntStatus);
6292 // Store off the information
6295 FileInfo->FileAttributes = pDirectoryEntry->ObjectInformation->FileAttributes;
6298 // Check for the mount point being returned
6301 if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT)
6304 FileInfo->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
6306 else if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK ||
6307 pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DFSLINK)
6310 if ( FileInfo->FileAttributes == FILE_ATTRIBUTE_NORMAL)
6313 FileInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
6318 FileInfo->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
6322 FileInfo->AllocationSize = pDirectoryEntry->ObjectInformation->AllocationSize;
6324 FileInfo->EndOfFile = pDirectoryEntry->ObjectInformation->EndOfFile;
6326 FileInfo->CreationTime = pDirectoryEntry->ObjectInformation->CreationTime;
6328 FileInfo->LastAccessTime = pDirectoryEntry->ObjectInformation->LastAccessTime;
6330 FileInfo->LastWriteTime = pDirectoryEntry->ObjectInformation->LastWriteTime;
6332 FileInfo->ChangeTime = pDirectoryEntry->ObjectInformation->ChangeTime;
6335 // Remove the reference made above
6338 lCount = InterlockedDecrement( &pDirectoryEntry->OpenReferenceCount);
6340 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6341 AFS_TRACE_LEVEL_VERBOSE,
6342 "AFSRetrieveFileAttributes Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
6343 &pDirectoryEntry->NameInformation.FileName,
6350 if( pDirEntry != NULL)
6353 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
6356 if( pVolumeCB != NULL)
6359 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6361 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6362 AFS_TRACE_LEVEL_VERBOSE,
6363 "AFSRetrieveFileAttributes Decrement2 count on volume %08lX Cnt %d\n",
6368 if( pNameArray != NULL)
6371 AFSFreeNameArray( pNameArray);
6374 if( pwchBuffer != NULL)
6378 // Always free the buffer that we allocated as AFSLocateNameEntry
6379 // will not free it. If uniFullPathName.Buffer was allocated by
6380 // AFSLocateNameEntry, then we must free that as well.
6381 // Check that the uniFullPathName.Buffer in the string is not the same
6382 // offset by the length of the server name
6385 if( uniFullPathName.Length > 0 &&
6386 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
6389 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
6392 AFSExFreePoolWithTag( pwchBuffer, 0);
6400 AFSAllocateObjectInfo( IN AFSObjectInfoCB *ParentObjectInfo,
6401 IN ULONGLONG HashIndex)
6404 NTSTATUS ntStatus = STATUS_SUCCESS;
6405 AFSObjectInfoCB *pObjectInfo = NULL;
6411 pObjectInfo = (AFSObjectInfoCB *)AFSExAllocatePoolWithTag( PagedPool,
6412 sizeof( AFSObjectInfoCB),
6413 AFS_OBJECT_INFO_TAG);
6415 if( pObjectInfo == NULL)
6418 try_return( pObjectInfo);
6421 RtlZeroMemory( pObjectInfo,
6422 sizeof( AFSObjectInfoCB));
6424 pObjectInfo->NonPagedInfo = (AFSNonPagedObjectInfoCB *)AFSExAllocatePoolWithTag( NonPagedPool,
6425 sizeof( AFSNonPagedObjectInfoCB),
6426 AFS_NP_OBJECT_INFO_TAG);
6428 if( pObjectInfo->NonPagedInfo == NULL)
6431 AFSExFreePoolWithTag( pObjectInfo, AFS_OBJECT_INFO_TAG);
6433 try_return( pObjectInfo = NULL);
6436 ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6438 ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
6440 pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock = &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock;
6442 pObjectInfo->VolumeCB = ParentObjectInfo->VolumeCB;
6444 pObjectInfo->ParentObjectInformation = ParentObjectInfo;
6446 if( ParentObjectInfo != NULL)
6448 lCount = AFSObjectInfoIncrement( ParentObjectInfo);
6452 // Initialize the access time
6455 KeQueryTickCount( &pObjectInfo->LastAccessCount);
6461 // Insert the entry into the object tree and list
6464 pObjectInfo->TreeEntry.HashIndex = HashIndex;
6466 if( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead == NULL)
6469 ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead = &pObjectInfo->TreeEntry;
6474 ntStatus = AFSInsertHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
6475 &pObjectInfo->TreeEntry);
6477 ASSERT( NT_SUCCESS( ntStatus));
6481 // And the object list in the volume
6484 if( ParentObjectInfo->VolumeCB->ObjectInfoListHead == NULL)
6487 ParentObjectInfo->VolumeCB->ObjectInfoListHead = pObjectInfo;
6492 ParentObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = (void *)pObjectInfo;
6494 pObjectInfo->ListEntry.bLink = (void *)ParentObjectInfo->VolumeCB->ObjectInfoListTail;
6497 ParentObjectInfo->VolumeCB->ObjectInfoListTail = pObjectInfo;
6500 // Indicate the object is in the hash tree and linked list in the volume
6503 SetFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE | AFS_OBJECT_INSERTED_VOLUME_LIST);
6515 AFSObjectInfoIncrement( IN AFSObjectInfoCB *ObjectInfo)
6520 if ( ObjectInfo->ObjectReferenceCount == 0)
6523 AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6526 lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6531 AFSAcquireShared( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6534 lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6539 AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6541 AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6546 AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6552 AFSObjectInfoDecrement( IN AFSObjectInfoCB *ObjectInfo)
6557 AFSAcquireShared( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6560 lCount = InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);
6565 lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6567 AFSReleaseResource(&ObjectInfo->NonPagedInfo->ObjectInfoLock);
6569 AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6572 lCount = InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);
6575 AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6583 AFSDeleteObjectInfo( IN AFSObjectInfoCB *ObjectInfo)
6586 BOOLEAN bAcquiredTreeLock = FALSE;
6589 if( !ExIsResourceAcquiredExclusiveLite( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock))
6592 ASSERT( !ExIsResourceAcquiredLite( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock));
6594 AFSAcquireExcl( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
6597 bAcquiredTreeLock = TRUE;
6601 // Remove it from the tree and list if it was inserted
6604 if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
6607 AFSRemoveHashEntry( &ObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
6608 &ObjectInfo->TreeEntry);
6611 if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_INSERTED_VOLUME_LIST))
6614 if( ObjectInfo->ListEntry.fLink == NULL)
6617 ObjectInfo->VolumeCB->ObjectInfoListTail = (AFSObjectInfoCB *)ObjectInfo->ListEntry.bLink;
6619 if( ObjectInfo->VolumeCB->ObjectInfoListTail != NULL)
6622 ObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = NULL;
6628 ((AFSObjectInfoCB *)(ObjectInfo->ListEntry.fLink))->ListEntry.bLink = ObjectInfo->ListEntry.bLink;
6631 if( ObjectInfo->ListEntry.bLink == NULL)
6634 ObjectInfo->VolumeCB->ObjectInfoListHead = (AFSObjectInfoCB *)ObjectInfo->ListEntry.fLink;
6636 if( ObjectInfo->VolumeCB->ObjectInfoListHead != NULL)
6639 ObjectInfo->VolumeCB->ObjectInfoListHead->ListEntry.bLink = NULL;
6645 ((AFSObjectInfoCB *)(ObjectInfo->ListEntry.bLink))->ListEntry.fLink = ObjectInfo->ListEntry.fLink;
6649 if( ObjectInfo->ParentObjectInformation != NULL)
6652 lCount = AFSObjectInfoDecrement( ObjectInfo->ParentObjectInformation);
6655 if( bAcquiredTreeLock)
6658 AFSReleaseResource( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
6662 // Release the fid in the service
6665 if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_HELD_IN_SERVICE))
6668 AFSReleaseFid( &ObjectInfo->FileId);
6671 ExDeleteResourceLite( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6673 ExDeleteResourceLite( &ObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6675 AFSExFreePoolWithTag( ObjectInfo->NonPagedInfo, AFS_NP_OBJECT_INFO_TAG);
6677 AFSExFreePoolWithTag( ObjectInfo, AFS_OBJECT_INFO_TAG);
6683 AFSEvaluateRootEntry( IN AFSDirectoryCB *DirectoryCB,
6684 OUT AFSDirectoryCB **TargetDirEntry)
6687 NTSTATUS ntStatus = STATUS_SUCCESS;
6688 AFSDirEnumEntry *pDirEntry = NULL, *pLastDirEntry = NULL;
6689 UNICODE_STRING uniFullPathName;
6690 AFSNameArrayHdr *pNameArray = NULL;
6691 AFSVolumeCB *pVolumeCB = NULL;
6692 AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
6693 WCHAR *pwchBuffer = NULL;
6694 UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
6695 ULONG ulNameDifference = 0;
6702 ntStatus = AFSRetrieveValidAuthGroup( NULL,
6703 DirectoryCB->ObjectInformation,
6707 if( !NT_SUCCESS( ntStatus))
6709 try_return( ntStatus);
6713 // Retrieve a target name for the entry
6716 AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
6719 if( DirectoryCB->NameInformation.TargetName.Length == 0)
6722 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6724 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
6729 if( !NT_SUCCESS( ntStatus) ||
6730 pDirEntry->TargetNameLength == 0)
6733 if( pDirEntry != NULL)
6736 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
6739 try_return( ntStatus);
6742 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
6745 if( DirectoryCB->NameInformation.TargetName.Length == 0)
6749 // Update the target name
6752 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
6753 &DirectoryCB->Flags,
6754 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
6755 (USHORT)pDirEntry->TargetNameLength);
6757 if( !NT_SUCCESS( ntStatus))
6760 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6762 try_return( ntStatus);
6766 AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
6770 // Need to pass the full path in for parsing.
6773 uniFullPathName.Length = 0;
6774 uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
6776 uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6777 uniFullPathName.MaximumLength,
6778 AFS_NAME_BUFFER_EIGHT_TAG);
6780 if( uniFullPathName.Buffer == NULL)
6783 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6785 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6788 pwchBuffer = uniFullPathName.Buffer;
6790 RtlZeroMemory( uniFullPathName.Buffer,
6791 uniFullPathName.MaximumLength);
6793 RtlCopyMemory( uniFullPathName.Buffer,
6794 DirectoryCB->NameInformation.TargetName.Buffer,
6795 DirectoryCB->NameInformation.TargetName.Length);
6797 uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6800 // This name should begin with the \afs server so parse it off and chech it
6803 FsRtlDissectName( uniFullPathName,
6807 if( RtlCompareUnicodeString( &uniComponentName,
6813 // Try evaluating the full path
6816 uniFullPathName.Buffer = pwchBuffer;
6818 uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6820 uniFullPathName.MaximumLength = uniFullPathName.Length;
6825 uniFullPathName = uniRemainingPath;
6828 uniParsedName = uniFullPathName;
6830 ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
6832 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6838 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
6841 if( pNameArray == NULL)
6844 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6847 pVolumeCB = AFSGlobalRoot;
6849 pParentDirEntry = AFSGlobalRoot->DirectoryCB;
6851 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
6853 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6854 AFS_TRACE_LEVEL_VERBOSE,
6855 "AFSEvaluateRootEntry Increment count on volume %08lX Cnt %d\n",
6859 lCount = InterlockedIncrement( &pParentDirEntry->OpenReferenceCount);
6861 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6862 AFS_TRACE_LEVEL_VERBOSE,
6863 "AFSEvaluateRootEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
6864 &pParentDirEntry->NameInformation.FileName,
6869 ntStatus = AFSLocateNameEntry( NULL,
6880 if( !NT_SUCCESS( ntStatus))
6884 // The volume lock was released on failure above
6885 // Except for STATUS_OBJECT_NAME_NOT_FOUND
6888 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
6891 if( pVolumeCB != NULL)
6894 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6896 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6897 AFS_TRACE_LEVEL_VERBOSE,
6898 "AFSEvaluateRootEntry Decrement count on volume %08lX Cnt %d\n",
6903 if( pDirectoryEntry != NULL)
6906 lCount = InterlockedDecrement( &pDirectoryEntry->OpenReferenceCount);
6908 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6909 AFS_TRACE_LEVEL_VERBOSE,
6910 "AFSEvaluateRootEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6911 &pDirectoryEntry->NameInformation.FileName,
6919 lCount = InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
6921 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6922 AFS_TRACE_LEVEL_VERBOSE,
6923 "AFSEvaluateRootEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6924 &pParentDirEntry->NameInformation.FileName,
6933 try_return( ntStatus);
6937 // Pass back the target dir entry for this request
6940 *TargetDirEntry = pDirectoryEntry;
6944 if( pDirEntry != NULL)
6947 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
6950 if( pVolumeCB != NULL)
6953 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6955 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6956 AFS_TRACE_LEVEL_VERBOSE,
6957 "AFSEvaluateRootEntry2 Decrement count on volume %08lX Cnt %d\n",
6962 if( pNameArray != NULL)
6965 AFSFreeNameArray( pNameArray);
6968 if( pwchBuffer != NULL)
6972 // Always free the buffer that we allocated as AFSLocateNameEntry
6973 // will not free it. If uniFullPathName.Buffer was allocated by
6974 // AFSLocateNameEntry, then we must free that as well.
6975 // Check that the uniFullPathName.Buffer in the string is not the same
6976 // offset by the length of the server name
6979 if( uniFullPathName.Length > 0 &&
6980 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
6983 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
6986 AFSExFreePoolWithTag( pwchBuffer, 0);
6994 AFSCleanupFcb( IN AFSFcb *Fcb,
6995 IN BOOLEAN ForceFlush)
6998 NTSTATUS ntStatus = STATUS_SUCCESS;
6999 AFSDeviceExt *pRDRDeviceExt = NULL, *pControlDeviceExt = NULL;
7000 LARGE_INTEGER liTime;
7001 IO_STATUS_BLOCK stIoStatus;
7006 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
7008 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
7010 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
7013 if( !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) &&
7014 !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
7017 AFSAcquireExcl( &Fcb->NPFcb->Resource,
7020 if( Fcb->OpenReferenceCount > 0)
7026 CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
7031 if( !NT_SUCCESS( stIoStatus.Status))
7034 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
7035 AFS_TRACE_LEVEL_ERROR,
7036 "AFSCleanupFcb CcFlushCache [1] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
7037 Fcb->ObjectInformation->FileId.Cell,
7038 Fcb->ObjectInformation->FileId.Volume,
7039 Fcb->ObjectInformation->FileId.Vnode,
7040 Fcb->ObjectInformation->FileId.Unique,
7042 stIoStatus.Information);
7044 ntStatus = stIoStatus.Status;
7047 if ( Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
7050 if ( !CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
7056 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
7057 AFS_TRACE_LEVEL_WARNING,
7058 "AFSCleanupFcb CcPurgeCacheSection [1] failure FID %08lX-%08lX-%08lX-%08lX\n",
7059 Fcb->ObjectInformation->FileId.Cell,
7060 Fcb->ObjectInformation->FileId.Volume,
7061 Fcb->ObjectInformation->FileId.Vnode,
7062 Fcb->ObjectInformation->FileId.Unique);
7064 SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
7068 __except( EXCEPTION_EXECUTE_HANDLER)
7071 ntStatus = GetExceptionCode();
7075 "EXCEPTION - AFSCleanupFcb Cc [1] FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
7076 Fcb->ObjectInformation->FileId.Cell,
7077 Fcb->ObjectInformation->FileId.Volume,
7078 Fcb->ObjectInformation->FileId.Vnode,
7079 Fcb->ObjectInformation->FileId.Unique,
7082 SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
7086 AFSReleaseResource( &Fcb->NPFcb->Resource);
7089 // Wait for any currently running flush or release requests to complete
7092 AFSWaitOnQueuedFlushes( Fcb);
7095 // Now perform another flush on the file
7098 if( !NT_SUCCESS( AFSFlushExtents( Fcb,
7102 AFSReleaseExtentsWithFlush( Fcb,
7108 if( Fcb->OpenReferenceCount == 0 ||
7109 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
7110 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
7113 AFSTearDownFcbExtents( Fcb,
7117 try_return( ntStatus);
7120 KeQueryTickCount( &liTime);
7123 // First up are there dirty extents in the cache to flush?
7126 if( BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
7127 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
7131 // The file has been marked as invalid. Dump it
7134 AFSTearDownFcbExtents( Fcb,
7137 else if( ForceFlush ||
7138 ( ( Fcb->Specific.File.ExtentsDirtyCount ||
7139 Fcb->Specific.File.ExtentCount) &&
7140 (liTime.QuadPart - Fcb->Specific.File.LastServerFlush.QuadPart)
7141 >= pControlDeviceExt->Specific.Control.FcbFlushTimeCount.QuadPart))
7143 if( !NT_SUCCESS( AFSFlushExtents( Fcb,
7145 Fcb->OpenReferenceCount == 0)
7148 AFSReleaseExtentsWithFlush( Fcb,
7155 // If there are extents and they haven't been used recently *and*
7156 // are not being used
7160 ( 0 != Fcb->Specific.File.ExtentCount &&
7161 0 != Fcb->Specific.File.LastExtentAccess.QuadPart &&
7162 (liTime.QuadPart - Fcb->Specific.File.LastExtentAccess.QuadPart) >=
7163 (AFS_SERVER_PURGE_SLEEP * pControlDeviceExt->Specific.Control.FcbPurgeTimeCount.QuadPart))))
7166 if ( AFSAcquireExcl( &Fcb->NPFcb->Resource, ForceFlush))
7172 CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
7177 if( !NT_SUCCESS( stIoStatus.Status))
7180 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
7181 AFS_TRACE_LEVEL_ERROR,
7182 "AFSCleanupFcb CcFlushCache [2] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
7183 Fcb->ObjectInformation->FileId.Cell,
7184 Fcb->ObjectInformation->FileId.Volume,
7185 Fcb->ObjectInformation->FileId.Vnode,
7186 Fcb->ObjectInformation->FileId.Unique,
7188 stIoStatus.Information);
7190 ntStatus = stIoStatus.Status;
7194 Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
7197 if ( !CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
7203 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
7204 AFS_TRACE_LEVEL_WARNING,
7205 "AFSCleanupFcb CcPurgeCacheSection [2] failure FID %08lX-%08lX-%08lX-%08lX\n",
7206 Fcb->ObjectInformation->FileId.Cell,
7207 Fcb->ObjectInformation->FileId.Volume,
7208 Fcb->ObjectInformation->FileId.Vnode,
7209 Fcb->ObjectInformation->FileId.Unique);
7211 SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
7215 __except( EXCEPTION_EXECUTE_HANDLER)
7218 ntStatus = GetExceptionCode();
7222 "EXCEPTION - AFSCleanupFcb Cc [2] FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
7223 Fcb->ObjectInformation->FileId.Cell,
7224 Fcb->ObjectInformation->FileId.Volume,
7225 Fcb->ObjectInformation->FileId.Vnode,
7226 Fcb->ObjectInformation->FileId.Unique,
7230 AFSReleaseResource( &Fcb->NPFcb->Resource);
7232 if( Fcb->OpenReferenceCount <= 0)
7236 // Tear em down we'll not be needing them again
7239 AFSTearDownFcbExtents( Fcb,
7246 ntStatus = STATUS_RETRY;
7259 AFSUpdateDirEntryName( IN AFSDirectoryCB *DirectoryCB,
7260 IN UNICODE_STRING *NewFileName)
7263 NTSTATUS ntStatus = STATUS_SUCCESS;
7264 WCHAR *pTmpBuffer = NULL;
7269 if( NewFileName->Length > DirectoryCB->NameInformation.FileName.Length)
7272 if( BooleanFlagOn( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
7275 AFSExFreePoolWithTag( DirectoryCB->NameInformation.FileName.Buffer, 0);
7277 ClearFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
7279 DirectoryCB->NameInformation.FileName.Buffer = NULL;
7283 // OK, we need to allocate a new name buffer
7286 pTmpBuffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
7287 NewFileName->Length,
7288 AFS_NAME_BUFFER_NINE_TAG);
7290 if( pTmpBuffer == NULL)
7293 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7296 DirectoryCB->NameInformation.FileName.Buffer = pTmpBuffer;
7298 DirectoryCB->NameInformation.FileName.MaximumLength = NewFileName->Length;
7300 SetFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
7303 DirectoryCB->NameInformation.FileName.Length = NewFileName->Length;
7305 RtlCopyMemory( DirectoryCB->NameInformation.FileName.Buffer,
7306 NewFileName->Buffer,
7307 NewFileName->Length);
7318 AFSReadCacheFile( IN void *ReadBuffer,
7319 IN LARGE_INTEGER *ReadOffset,
7320 IN ULONG RequestedDataLength,
7321 IN OUT PULONG BytesRead)
7324 NTSTATUS ntStatus = STATUS_SUCCESS;
7327 PIO_STACK_LOCATION pIoStackLocation = NULL;
7328 AFSDeviceExt *pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
7329 DEVICE_OBJECT *pTargetDeviceObject = NULL;
7330 FILE_OBJECT *pCacheFileObject = NULL;
7335 pCacheFileObject = AFSReferenceCacheFileObject();
7337 if( pCacheFileObject == NULL)
7339 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
7342 pTargetDeviceObject = IoGetRelatedDeviceObject( pCacheFileObject);
7345 // Initialize the event
7348 KeInitializeEvent( &kEvent,
7349 SynchronizationEvent,
7353 // Allocate an irp for this request. This could also come from a
7354 // private pool, for instance.
7357 pIrp = IoAllocateIrp( pTargetDeviceObject->StackSize,
7363 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7367 // Build the IRP's main body
7370 pIrp->UserBuffer = ReadBuffer;
7372 pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
7373 pIrp->RequestorMode = KernelMode;
7374 pIrp->Flags |= IRP_READ_OPERATION;
7377 // Set up the I/O stack location.
7380 pIoStackLocation = IoGetNextIrpStackLocation( pIrp);
7381 pIoStackLocation->MajorFunction = IRP_MJ_READ;
7382 pIoStackLocation->DeviceObject = pTargetDeviceObject;
7383 pIoStackLocation->FileObject = pCacheFileObject;
7384 pIoStackLocation->Parameters.Read.Length = RequestedDataLength;
7386 pIoStackLocation->Parameters.Read.ByteOffset.QuadPart = ReadOffset->QuadPart;
7389 // Set the completion routine.
7392 IoSetCompletionRoutine( pIrp,
7400 // Send it to the FSD
7403 ntStatus = IoCallDriver( pTargetDeviceObject,
7406 if( NT_SUCCESS( ntStatus))
7413 ntStatus = KeWaitForSingleObject( &kEvent,
7419 if( NT_SUCCESS( ntStatus))
7422 ntStatus = pIrp->IoStatus.Status;
7424 *BytesRead = (ULONG)pIrp->IoStatus.Information;
7430 if( pCacheFileObject != NULL)
7432 AFSReleaseCacheFileObject( pCacheFileObject);
7438 if( pIrp->MdlAddress != NULL)
7441 if( FlagOn( pIrp->MdlAddress->MdlFlags, MDL_PAGES_LOCKED))
7444 MmUnlockPages( pIrp->MdlAddress);
7447 IoFreeMdl( pIrp->MdlAddress);
7450 pIrp->MdlAddress = NULL;
7464 AFSIrpComplete( IN PDEVICE_OBJECT DeviceObject,
7469 KEVENT *pEvent = (KEVENT *)Context;
7475 return STATUS_MORE_PROCESSING_REQUIRED;
7479 AFSIsDirectoryEmptyForDelete( IN AFSFcb *Fcb)
7482 BOOLEAN bIsEmpty = FALSE;
7483 AFSDirectoryCB *pDirEntry = NULL;
7488 AFSAcquireShared( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
7493 if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
7496 pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
7498 while( pDirEntry != NULL)
7501 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
7502 !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
7510 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
7515 AFSReleaseResource( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
7522 AFSRemoveNameEntry( IN AFSObjectInfoCB *ParentObjectInfo,
7523 IN AFSDirectoryCB *DirEntry)
7526 NTSTATUS ntStatus = STATUS_SUCCESS;
7531 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7534 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7535 AFS_TRACE_LEVEL_VERBOSE,
7536 "AFSRemoveNameEntry DE %p for %wZ has NOT_IN flag set\n",
7538 &DirEntry->NameInformation.FileName);
7540 try_return( ntStatus);
7543 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
7546 // Remove the entry from the parent tree
7549 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7550 AFS_TRACE_LEVEL_VERBOSE,
7551 "AFSRemoveNameEntry DE %p for %wZ removing from case sensitive tree\n",
7553 &DirEntry->NameInformation.FileName);
7555 AFSRemoveCaseSensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7558 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7559 AFS_TRACE_LEVEL_VERBOSE,
7560 "AFSRemoveNameEntry DE %p for %wZ removing from case insensitive tree\n",
7562 &DirEntry->NameInformation.FileName);
7564 AFSRemoveCaseInsensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
7567 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
7571 // From the short name tree
7574 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7575 AFS_TRACE_LEVEL_VERBOSE,
7576 "AFSRemoveNameEntry DE %p for %wZ removing from shortname tree\n",
7578 &DirEntry->NameInformation.FileName);
7580 AFSRemoveShortNameDirEntry( &ParentObjectInfo->Specific.Directory.ShortNameTree,
7583 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
7586 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7587 AFS_TRACE_LEVEL_VERBOSE,
7588 "AFSRemoveNameEntry DE %p for %wZ setting NOT_IN flag\n",
7590 &DirEntry->NameInformation.FileName);
7592 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
7594 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
7605 AFSGetAuthenticationId()
7608 LARGE_INTEGER liAuthId = {0,0};
7609 NTSTATUS ntStatus = STATUS_SUCCESS;
7610 PACCESS_TOKEN hToken = NULL;
7611 PTOKEN_STATISTICS pTokenInfo = NULL;
7612 BOOLEAN bCopyOnOpen = FALSE;
7613 BOOLEAN bEffectiveOnly = FALSE;
7614 BOOLEAN bPrimaryToken = FALSE;
7615 SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
7620 hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
7623 &stImpersonationLevel);
7628 hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
7633 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7634 AFS_TRACE_LEVEL_ERROR,
7635 "AFSGetAuthenticationId Failed to retrieve impersonation or primary token\n");
7637 try_return( ntStatus);
7640 bPrimaryToken = TRUE;
7643 ntStatus = SeQueryInformationToken( hToken,
7645 (PVOID *)&pTokenInfo);
7647 if( !NT_SUCCESS( ntStatus))
7650 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7651 AFS_TRACE_LEVEL_ERROR,
7652 "AFSGetAuthenticationId Failed to retrieve information Status %08lX\n", ntStatus);
7654 try_return( ntStatus);
7657 liAuthId.HighPart = pTokenInfo->AuthenticationId.HighPart;
7658 liAuthId.LowPart = pTokenInfo->AuthenticationId.LowPart;
7660 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7661 AFS_TRACE_LEVEL_VERBOSE,
7662 "AFSGetAuthenticationId Successfully retrieved authentication ID %I64X\n",
7673 PsDereferenceImpersonationToken( hToken);
7678 PsDereferencePrimaryToken( hToken);
7682 if( pTokenInfo != NULL)
7685 ExFreePool( pTokenInfo); // Allocated by SeQueryInformationToken
7693 AFSUnwindFileInfo( IN AFSFcb *Fcb,
7697 if( Ccb->FileUnwindInfo.FileAttributes != (ULONG)-1)
7699 Ccb->DirectoryCB->ObjectInformation->FileAttributes = Ccb->FileUnwindInfo.FileAttributes;
7702 if( Ccb->FileUnwindInfo.CreationTime.QuadPart != (ULONGLONG)-1)
7704 Ccb->DirectoryCB->ObjectInformation->CreationTime.QuadPart = Ccb->FileUnwindInfo.CreationTime.QuadPart;
7707 if( Ccb->FileUnwindInfo.LastAccessTime.QuadPart != (ULONGLONG)-1)
7709 Ccb->DirectoryCB->ObjectInformation->LastAccessTime.QuadPart = Ccb->FileUnwindInfo.LastAccessTime.QuadPart;
7712 if( Ccb->FileUnwindInfo.LastWriteTime.QuadPart != (ULONGLONG)-1)
7714 Ccb->DirectoryCB->ObjectInformation->LastWriteTime.QuadPart = Ccb->FileUnwindInfo.LastWriteTime.QuadPart;
7717 if( Ccb->FileUnwindInfo.ChangeTime.QuadPart != (ULONGLONG)-1)
7719 Ccb->DirectoryCB->ObjectInformation->ChangeTime.QuadPart = Ccb->FileUnwindInfo.ChangeTime.QuadPart;
7726 AFSValidateDirList( IN AFSObjectInfoCB *ObjectInfo)
7729 BOOLEAN bIsValid = TRUE;
7731 AFSDirectoryCB *pCurrentDirEntry = NULL, *pDirEntry = NULL;
7733 pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
7735 while( pCurrentDirEntry != NULL)
7738 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
7742 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7747 AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7748 (ULONG)pCurrentDirEntry->CaseSensitiveTreeEntry.HashIndex,
7751 if( pDirEntry == NULL)
7758 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
7761 if( ulCount != ObjectInfo->Specific.Directory.DirectoryNodeCount)
7764 AFSPrint("AFSValidateDirList Count off Calc: %d Stored: %d\n",
7766 ObjectInfo->Specific.Directory.DirectoryNodeCount);
7768 ObjectInfo->Specific.Directory.DirectoryNodeCount = ulCount;
7777 AFSReferenceCacheFileObject()
7780 AFSDeviceExt *pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
7781 FILE_OBJECT *pCacheFileObject = NULL;
7783 AFSAcquireShared( &pRdrDevExt->Specific.RDR.CacheFileLock,
7786 pCacheFileObject = pRdrDevExt->Specific.RDR.CacheFileObject;
7788 if( pCacheFileObject != NULL)
7790 ObReferenceObject( pCacheFileObject);
7793 AFSReleaseResource( &pRdrDevExt->Specific.RDR.CacheFileLock);
7795 return pCacheFileObject;
7799 AFSReleaseCacheFileObject( IN PFILE_OBJECT CacheFileObject)
7802 ASSERT( CacheFileObject != NULL);
7804 ObDereferenceObject( CacheFileObject);
7810 AFSInitializeLibrary( IN AFSLibraryInitCB *LibraryInit)
7813 NTSTATUS ntStatus = STATUS_SUCCESS;
7814 AFSDeviceExt *pControlDevExt = NULL;
7815 ULONG ulTimeIncrement = 0;
7821 AFSControlDeviceObject = LibraryInit->AFSControlDeviceObject;
7823 AFSRDRDeviceObject = LibraryInit->AFSRDRDeviceObject;
7825 AFSServerName = LibraryInit->AFSServerName;
7827 AFSMountRootName = LibraryInit->AFSMountRootName;
7829 AFSDebugFlags = LibraryInit->AFSDebugFlags;
7832 // Callbacks in the framework
7835 AFSProcessRequest = LibraryInit->AFSProcessRequest;
7837 AFSDbgLogMsg = LibraryInit->AFSDbgLogMsg;
7839 AFSAddConnectionEx = LibraryInit->AFSAddConnectionEx;
7841 AFSExAllocatePoolWithTag = LibraryInit->AFSExAllocatePoolWithTag;
7843 AFSExFreePoolWithTag = LibraryInit->AFSExFreePoolWithTag;
7845 AFSDumpTraceFilesFnc = LibraryInit->AFSDumpTraceFiles;
7847 AFSRetrieveAuthGroupFnc = LibraryInit->AFSRetrieveAuthGroup;
7849 AFSLibCacheManagerCallbacks = LibraryInit->AFSCacheManagerCallbacks;
7851 if( LibraryInit->AFSCacheBaseAddress != NULL)
7854 SetFlag( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE);
7856 AFSLibCacheBaseAddress = LibraryInit->AFSCacheBaseAddress;
7858 AFSLibCacheLength = LibraryInit->AFSCacheLength;
7862 // Initialize some flush parameters
7865 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
7867 ulTimeIncrement = KeQueryTimeIncrement();
7869 pControlDevExt->Specific.Control.ObjectLifeTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_OBJECT_LIFETIME / (ULONGLONG)ulTimeIncrement);
7870 pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart = AFS_SERVER_PURGE_DELAY;
7871 pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart /= ulTimeIncrement;
7872 pControlDevExt->Specific.Control.FcbFlushTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_SERVER_FLUSH_DELAY / (ULONGLONG)ulTimeIncrement);
7873 pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_EXTENT_REQUEST_TIME/(ULONGLONG)ulTimeIncrement);
7876 // Initialize the global root entry
7879 ntStatus = AFSInitVolume( NULL,
7880 &LibraryInit->GlobalRootFid,
7883 if( !NT_SUCCESS( ntStatus))
7886 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
7887 AFS_TRACE_LEVEL_ERROR,
7888 "AFSInitializeLibrary AFSInitVolume failure %08lX\n",
7891 try_return( ntStatus);
7894 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
7897 if( !NT_SUCCESS( ntStatus))
7900 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
7901 AFS_TRACE_LEVEL_ERROR,
7902 "AFSInitializeLibrary AFSInitRootFcb failure %08lX\n",
7905 lCount = InterlockedDecrement( &AFSGlobalRoot->VolumeReferenceCount);
7907 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
7909 try_return( ntStatus);
7913 // Update the node type code to AFS_ROOT_ALL
7916 AFSGlobalRoot->ObjectInformation.Fcb->Header.NodeTypeCode = AFS_ROOT_ALL;
7918 SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_ACTIVE_GLOBAL_ROOT);
7921 // Invalidate all known volumes since contact with the service and therefore
7922 // the file server was lost.
7925 AFSInvalidateAllVolumes();
7928 // Drop the locks acquired above
7931 AFSInitVolumeWorker( AFSGlobalRoot);
7933 lCount = InterlockedDecrement( &AFSGlobalRoot->VolumeReferenceCount);
7935 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
7937 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Fcb->Header.Resource);
7951 NTSTATUS ntStatus = STATUS_SUCCESS;
7952 AFSDirectoryCB *pDirNode = NULL, *pLastDirNode = NULL;
7957 if( AFSGlobalDotDirEntry != NULL)
7960 AFSDeleteObjectInfo( AFSGlobalDotDirEntry->ObjectInformation);
7962 ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
7964 ExFreePool( AFSGlobalDotDirEntry->NonPaged);
7966 ExFreePool( AFSGlobalDotDirEntry);
7968 AFSGlobalDotDirEntry = NULL;
7971 if( AFSGlobalDotDotDirEntry != NULL)
7974 AFSDeleteObjectInfo( AFSGlobalDotDotDirEntry->ObjectInformation);
7976 ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
7978 ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
7980 ExFreePool( AFSGlobalDotDotDirEntry);
7982 AFSGlobalDotDotDirEntry = NULL;
7985 if( AFSSpecialShareNames != NULL)
7988 pDirNode = AFSSpecialShareNames;
7990 while( pDirNode != NULL)
7993 pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
7995 AFSDeleteObjectInfo( pDirNode->ObjectInformation);
7997 ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
7999 ExFreePool( pDirNode->NonPaged);
8001 ExFreePool( pDirNode);
8003 pDirNode = pLastDirNode;
8006 AFSSpecialShareNames = NULL;
8014 AFSDefaultLogMsg( IN ULONG Subsystem,
8020 NTSTATUS ntStatus = STATUS_SUCCESS;
8022 char chDebugBuffer[ 256];
8027 va_start( va_args, Format);
8029 ntStatus = RtlStringCbVPrintfA( chDebugBuffer,
8034 if( NT_SUCCESS( ntStatus))
8036 DbgPrint( chDebugBuffer);
8046 AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
8047 IN ULONG InputBufferLength,
8048 IN AFSStatusInfoCB *StatusInfo,
8049 OUT ULONG *ReturnLength)
8052 NTSTATUS ntStatus = STATUS_SUCCESS;
8053 AFSFcb *pFcb = NULL;
8054 AFSVolumeCB *pVolumeCB = NULL;
8055 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
8056 AFSObjectInfoCB *pObjectInfo = NULL;
8057 ULONGLONG ullIndex = 0;
8058 UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName, uniParsedName;
8059 AFSNameArrayHdr *pNameArray = NULL;
8060 AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
8067 // If we are given a FID then look up the entry by that, otherwise
8071 if( GetStatusInfo->FileID.Cell != 0 &&
8072 GetStatusInfo->FileID.Volume != 0 &&
8073 GetStatusInfo->FileID.Vnode != 0 &&
8074 GetStatusInfo->FileID.Unique != 0)
8077 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
8080 // Locate the volume node
8083 ullIndex = AFSCreateHighIndex( &GetStatusInfo->FileID);
8085 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
8087 (AFSBTreeEntry **)&pVolumeCB);
8089 if( pVolumeCB != NULL)
8092 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
8094 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8095 AFS_TRACE_LEVEL_VERBOSE,
8096 "AFSGetObjectStatus Increment count on volume %08lX Cnt %d\n",
8101 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
8103 if( !NT_SUCCESS( ntStatus) ||
8106 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8109 if( AFSIsVolumeFID( &GetStatusInfo->FileID))
8112 pObjectInfo = &pVolumeCB->ObjectInformation;
8114 lCount = AFSObjectInfoIncrement( pObjectInfo);
8116 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
8121 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
8124 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
8126 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8127 AFS_TRACE_LEVEL_VERBOSE,
8128 "AFSGetObjectStatus Decrement count on volume %08lX Cnt %d\n",
8132 ullIndex = AFSCreateLowIndex( &GetStatusInfo->FileID);
8134 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
8136 (AFSBTreeEntry **)&pObjectInfo);
8138 if( pObjectInfo != NULL)
8142 // Reference the node so it won't be torn down
8145 lCount = AFSObjectInfoIncrement( pObjectInfo);
8147 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8148 AFS_TRACE_LEVEL_VERBOSE,
8149 "AFSGetObjectStatus Increment count on object %08lX Cnt %d\n",
8154 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
8156 if( !NT_SUCCESS( ntStatus) ||
8157 pObjectInfo == NULL)
8159 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8166 if( GetStatusInfo->FileNameLength == 0 ||
8167 InputBufferLength < (ULONG)(FIELD_OFFSET( AFSGetStatusInfoCB, FileName) + GetStatusInfo->FileNameLength))
8169 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8172 uniFullPathName.Length = GetStatusInfo->FileNameLength;
8173 uniFullPathName.MaximumLength = uniFullPathName.Length;
8175 uniFullPathName.Buffer = (WCHAR *)GetStatusInfo->FileName;
8178 // This name should begin with the \afs server so parse it off and check it
8181 FsRtlDissectName( uniFullPathName,
8185 if( RtlCompareUnicodeString( &uniComponentName,
8189 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8190 AFS_TRACE_LEVEL_ERROR,
8191 "AFSGetObjectStatus Name %wZ contains invalid server name\n",
8194 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
8197 uniFullPathName = uniRemainingPath;
8199 uniParsedName = uniFullPathName;
8205 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
8208 if( pNameArray == NULL)
8210 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8213 pVolumeCB = AFSGlobalRoot;
8215 pParentDirEntry = AFSGlobalRoot->DirectoryCB;
8218 // Increment the ref count on the volume and dir entry for correct processing below
8221 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
8223 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8224 AFS_TRACE_LEVEL_VERBOSE,
8225 "AFSGetObjectStatus Increment count on volume %08lX Cnt %d\n",
8229 lCount = InterlockedIncrement( &pParentDirEntry->OpenReferenceCount);
8231 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8232 AFS_TRACE_LEVEL_VERBOSE,
8233 "AFSGetObjectStatus Increment count on %wZ DE %p Ccb %p Cnt %d\n",
8234 &pParentDirEntry->NameInformation.FileName,
8239 ntStatus = AFSLocateNameEntry( NULL,
8244 AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL |
8245 AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL,
8251 if( !NT_SUCCESS( ntStatus))
8255 // The volume lock was released on failure above
8256 // Except for STATUS_OBJECT_NAME_NOT_FOUND
8259 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
8262 if( pVolumeCB != NULL)
8265 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
8267 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8268 AFS_TRACE_LEVEL_VERBOSE,
8269 "AFSGetObjectStatus Decrement count on volume %08lX Cnt %d\n",
8274 if( pDirectoryEntry != NULL)
8277 lCount = InterlockedDecrement( &pDirectoryEntry->OpenReferenceCount);
8279 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8280 AFS_TRACE_LEVEL_VERBOSE,
8281 "AFSGetObjectStatus Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
8282 &pDirectoryEntry->NameInformation.FileName,
8290 lCount = InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
8292 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8293 AFS_TRACE_LEVEL_VERBOSE,
8294 "AFSGetObjectStatus Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
8295 &pParentDirEntry->NameInformation.FileName,
8304 try_return( ntStatus);
8308 // Remove the reference made above
8311 lCount = InterlockedDecrement( &pDirectoryEntry->OpenReferenceCount);
8313 pObjectInfo = pDirectoryEntry->ObjectInformation;
8315 lCount = AFSObjectInfoIncrement( pObjectInfo);
8317 if( pVolumeCB != NULL)
8320 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
8322 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8323 AFS_TRACE_LEVEL_VERBOSE,
8324 "AFSRetrieveFileAttributes Decrement2 count on volume %08lX Cnt %d\n",
8326 pVolumeCB->VolumeReferenceCount);
8331 // At this point we have an object info block, return the information
8334 StatusInfo->FileId = pObjectInfo->FileId;
8336 StatusInfo->TargetFileId = pObjectInfo->TargetFileId;
8338 StatusInfo->Expiration = pObjectInfo->Expiration;
8340 StatusInfo->DataVersion = pObjectInfo->DataVersion;
8342 StatusInfo->FileType = pObjectInfo->FileType;
8344 StatusInfo->ObjectFlags = pObjectInfo->Flags;
8346 StatusInfo->CreationTime = pObjectInfo->CreationTime;
8348 StatusInfo->LastAccessTime = pObjectInfo->LastAccessTime;
8350 StatusInfo->LastWriteTime = pObjectInfo->LastWriteTime;
8352 StatusInfo->ChangeTime = pObjectInfo->ChangeTime;
8354 StatusInfo->FileAttributes = pObjectInfo->FileAttributes;
8356 StatusInfo->EndOfFile = pObjectInfo->EndOfFile;
8358 StatusInfo->AllocationSize = pObjectInfo->AllocationSize;
8360 StatusInfo->EaSize = pObjectInfo->EaSize;
8362 StatusInfo->Links = pObjectInfo->Links;
8365 // Return the information length
8368 *ReturnLength = sizeof( AFSStatusInfoCB);
8372 if( pObjectInfo != NULL)
8375 lCount = AFSObjectInfoDecrement( pObjectInfo);
8378 if( pNameArray != NULL)
8381 AFSFreeNameArray( pNameArray);
8389 AFSCheckSymlinkAccess( IN AFSDirectoryCB *ParentDirectoryCB,
8390 IN UNICODE_STRING *ComponentName)
8393 NTSTATUS ntStatus = STATUS_SUCCESS;
8394 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
8395 AFSDirectoryCB *pDirEntry = NULL;
8403 // Search for the entry in the parent
8406 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8407 AFS_TRACE_LEVEL_VERBOSE_2,
8408 "AFSCheckSymlinkAccess Searching for entry %wZ case sensitive\n",
8411 ulCRC = AFSGenerateCRC( ComponentName,
8414 AFSAcquireShared( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
8417 AFSLocateCaseSensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
8421 if( pDirEntry == NULL)
8425 // Missed so perform a case insensitive lookup
8428 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8429 AFS_TRACE_LEVEL_VERBOSE_2,
8430 "AFSCheckSymlinkAccess Searching for entry %wZ case insensitive\n",
8433 ulCRC = AFSGenerateCRC( ComponentName,
8436 AFSLocateCaseInsensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
8440 if( pDirEntry == NULL)
8444 // OK, if this component is a valid short name then try
8445 // a lookup in the short name tree
8448 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
8449 RtlIsNameLegalDOS8Dot3( ComponentName,
8454 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8455 AFS_TRACE_LEVEL_VERBOSE_2,
8456 "AFSCheckSymlinkAccess Searching for entry %wZ short name\n",
8459 AFSLocateShortNameDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.ShortNameTree,
8466 if( pDirEntry != NULL)
8468 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
8471 AFSReleaseResource( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
8473 if( pDirEntry == NULL)
8476 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8477 AFS_TRACE_LEVEL_VERBOSE_2,
8478 "AFSCheckSymlinkAccess Failed to locate entry %wZ\n",
8481 try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
8485 // We have the symlink object but previously failed to process it so return access
8489 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8490 AFS_TRACE_LEVEL_VERBOSE_2,
8491 "AFSCheckSymlinkAccess Failing symlink access to entry %wZ REPARSE_POINT_NOT_RESOLVED\n",
8494 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
8496 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
8507 AFSRetrieveFinalComponent( IN UNICODE_STRING *FullPathName,
8508 OUT UNICODE_STRING *ComponentName)
8511 NTSTATUS ntStatus = STATUS_SUCCESS;
8512 UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName;
8514 uniFullPathName = *FullPathName;
8519 FsRtlDissectName( uniFullPathName,
8523 if( uniRemainingPath.Length == 0)
8528 uniFullPathName = uniRemainingPath;
8531 if( uniComponentName.Length > 0)
8533 *ComponentName = uniComponentName;
8540 AFSDumpTraceFiles_Default()
8546 AFSValidNameFormat( IN UNICODE_STRING *FileName)
8549 BOOLEAN bIsValidName = TRUE;
8555 while( usIndex < FileName->Length/sizeof( WCHAR))
8558 if( FileName->Buffer[ usIndex] == L':' ||
8559 FileName->Buffer[ usIndex] == L'*' ||
8560 FileName->Buffer[ usIndex] == L'?' ||
8561 FileName->Buffer[ usIndex] == L'"' ||
8562 FileName->Buffer[ usIndex] == L'<' ||
8563 FileName->Buffer[ usIndex] == L'>')
8565 bIsValidName = FALSE;
8573 return bIsValidName;
8577 AFSCreateDefaultSecurityDescriptor()
8580 NTSTATUS ntStatus = STATUS_SUCCESS;
8582 ULONG ulSACLSize = 0;
8583 SYSTEM_MANDATORY_LABEL_ACE* pACE = NULL;
8584 ULONG ulACESize = 0;
8585 SECURITY_DESCRIPTOR *pSecurityDescr = NULL;
8586 ULONG ulSDLength = 0;
8587 SECURITY_DESCRIPTOR *pRelativeSecurityDescr = NULL;
8588 PSID pWorldSID = NULL;
8589 ULONG *pulSubAuthority = NULL;
8590 ULONG ulWorldSIDLEngth = 0;
8595 ulWorldSIDLEngth = RtlLengthRequiredSid( 1);
8597 pWorldSID = (PSID)ExAllocatePoolWithTag( PagedPool,
8599 AFS_GENERIC_MEMORY_29_TAG);
8601 if( pWorldSID == NULL)
8603 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate World SID\n");
8604 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8607 RtlZeroMemory( pWorldSID,
8610 RtlInitializeSid( pWorldSID,
8611 &SeWorldSidAuthority,
8614 pulSubAuthority = RtlSubAuthoritySid(pWorldSID, 0);
8615 *pulSubAuthority = SECURITY_WORLD_RID;
8617 if( AFSRtlSetSaclSecurityDescriptor == NULL)
8620 AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor == NULL\n");
8625 ulACESize = sizeof( SYSTEM_MANDATORY_LABEL_ACE) + 128;
8627 pACE = (SYSTEM_MANDATORY_LABEL_ACE *)ExAllocatePoolWithTag( PagedPool,
8629 AFS_GENERIC_MEMORY_29_TAG);
8634 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8636 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8639 RtlZeroMemory( pACE,
8642 pACE->Header.AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
8643 pACE->Header.AceType = SYSTEM_MANDATORY_LABEL_ACE_TYPE;
8644 pACE->Header.AceSize = FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + (USHORT)RtlLengthSid( SeExports->SeLowMandatorySid);
8645 pACE->Mask = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP;
8647 RtlCopySid( RtlLengthSid( SeExports->SeLowMandatorySid),
8649 SeExports->SeLowMandatorySid);
8651 ulSACLSize = sizeof(ACL) + RtlLengthSid( SeExports->SeLowMandatorySid) +
8652 FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + ulACESize;
8654 pSACL = (PACL)ExAllocatePoolWithTag( PagedPool,
8656 AFS_GENERIC_MEMORY_29_TAG);
8661 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8663 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8666 ntStatus = RtlCreateAcl( pSACL,
8670 if( !NT_SUCCESS( ntStatus))
8673 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateAcl ntStatus %08lX\n",
8676 try_return( ntStatus);
8679 ntStatus = RtlAddAce( pSACL,
8683 pACE->Header.AceSize);
8685 if( !NT_SUCCESS( ntStatus))
8688 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAddAce ntStatus %08lX\n",
8691 try_return( ntStatus);
8695 pSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
8696 sizeof( SECURITY_DESCRIPTOR),
8697 AFS_GENERIC_MEMORY_27_TAG);
8699 if( pSecurityDescr == NULL)
8702 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8704 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8707 ntStatus = RtlCreateSecurityDescriptor( pSecurityDescr,
8708 SECURITY_DESCRIPTOR_REVISION);
8710 if( !NT_SUCCESS( ntStatus))
8713 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateSecurityDescriptor ntStatus %08lX\n",
8716 try_return( ntStatus);
8719 if( AFSRtlSetSaclSecurityDescriptor != NULL)
8721 ntStatus = AFSRtlSetSaclSecurityDescriptor( pSecurityDescr,
8726 if( !NT_SUCCESS( ntStatus))
8729 AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor ntStatus %08lX\n",
8732 try_return( ntStatus);
8737 // Add in the group and owner to the SD
8740 if( AFSRtlSetGroupSecurityDescriptor != NULL)
8742 ntStatus = AFSRtlSetGroupSecurityDescriptor( pSecurityDescr,
8746 if( !NT_SUCCESS( ntStatus))
8749 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetGroupSecurityDescriptor failed ntStatus %08lX\n",
8752 try_return( ntStatus);
8756 ntStatus = RtlSetOwnerSecurityDescriptor( pSecurityDescr,
8760 if( !NT_SUCCESS( ntStatus))
8763 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetOwnerSecurityDescriptor failed ntStatus %08lX\n",
8766 try_return( ntStatus);
8769 if( !RtlValidSecurityDescriptor( pSecurityDescr))
8772 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlValidSecurityDescriptor NOT\n");
8774 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8777 pRelativeSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
8779 AFS_GENERIC_MEMORY_27_TAG);
8781 if( pRelativeSecurityDescr == NULL)
8784 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8786 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8789 ulSDLength = PAGE_SIZE;
8791 ntStatus = RtlAbsoluteToSelfRelativeSD( pSecurityDescr,
8792 pRelativeSecurityDescr,
8795 if( !NT_SUCCESS( ntStatus))
8798 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAbsoluteToSelfRelativeSD ntStatus %08lX\n",
8801 try_return( ntStatus);
8804 AFSDefaultSD = pRelativeSecurityDescr;
8808 if( !NT_SUCCESS( ntStatus))
8811 if( pRelativeSecurityDescr != NULL)
8813 ExFreePool( pRelativeSecurityDescr);
8817 if( pSecurityDescr != NULL)
8819 ExFreePool( pSecurityDescr);
8832 if( pWorldSID != NULL)
8834 ExFreePool( pWorldSID);
8842 AFSRetrieveParentPath( IN UNICODE_STRING *FullFileName,
8843 OUT UNICODE_STRING *ParentPath)
8848 *ParentPath = *FullFileName;
8851 // If the final character is a \, jump over it
8854 if( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] == L'\\')
8856 ParentPath->Length -= sizeof( WCHAR);
8859 while( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] != L'\\')
8861 ParentPath->Length -= sizeof( WCHAR);
8865 // And the separator
8868 ParentPath->Length -= sizeof( WCHAR);
8874 AFSRetrieveValidAuthGroup( IN AFSFcb *Fcb,
8875 IN AFSObjectInfoCB *ObjectInfo,
8876 IN BOOLEAN WriteAccess,
8877 OUT GUID *AuthGroup)
8880 NTSTATUS ntStatus = STATUS_SUCCESS;
8881 GUID stAuthGroup, stZeroAuthGroup;
8882 BOOLEAN bFoundAuthGroup = FALSE;
8883 AFSCcb *pCcb = NULL;
8889 RtlZeroMemory( &stAuthGroup,
8892 RtlZeroMemory( &stZeroAuthGroup,
8898 if( ObjectInfo != NULL &&
8899 ObjectInfo->Fcb != NULL)
8901 pFcb = ObjectInfo->Fcb;
8908 AFSAcquireShared( &Fcb->NPFcb->CcbListLock,
8911 pCcb = Fcb->CcbListHead;
8913 while( pCcb != NULL)
8917 pCcb->GrantedAccess & FILE_WRITE_DATA)
8919 RtlCopyMemory( &stAuthGroup,
8923 bFoundAuthGroup = TRUE;
8927 else if( pCcb->GrantedAccess & FILE_READ_DATA)
8930 // At least get the read-only access
8933 RtlCopyMemory( &stAuthGroup,
8937 bFoundAuthGroup = TRUE;
8940 pCcb = (AFSCcb *)pCcb->ListEntry.fLink;
8943 AFSReleaseResource( &Fcb->NPFcb->CcbListLock);
8946 if( !bFoundAuthGroup)
8949 AFSRetrieveAuthGroupFnc( (ULONGLONG)PsGetCurrentProcessId(),
8950 (ULONGLONG)PsGetCurrentThreadId(),
8953 if( RtlCompareMemory( &stZeroAuthGroup,
8955 sizeof( GUID)) == sizeof( GUID))
8958 DbgPrint("AFSRetrieveValidAuthGroup Failed to locate PAG\n");
8960 try_return( ntStatus = STATUS_ACCESS_DENIED);
8964 RtlCopyMemory( AuthGroup,
8977 AFSPerformObjectInvalidate( IN AFSObjectInfoCB *ObjectInfo,
8978 IN ULONG InvalidateReason)
8981 NTSTATUS ntStatus = STATUS_SUCCESS;
8982 IO_STATUS_BLOCK stIoStatus;
8985 ULONG ulProcessCount = 0;
8991 switch( InvalidateReason)
8994 case AFS_INVALIDATE_DELETED:
8997 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
8998 ObjectInfo->Fcb != NULL)
9001 AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9004 ObjectInfo->Links = 0;
9006 ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
9008 KeSetEvent( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
9013 // Clear out the extents
9014 // And get rid of them (note this involves waiting
9015 // for any writes or reads to the cache to complete)
9018 AFSTearDownFcbExtents( ObjectInfo->Fcb,
9021 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
9027 case AFS_INVALIDATE_DATA_VERSION:
9030 LARGE_INTEGER liCurrentOffset = {0,0};
9031 LARGE_INTEGER liFlushLength = {0,0};
9032 ULONG ulFlushLength = 0;
9033 BOOLEAN bLocked = FALSE;
9034 BOOLEAN bExtentsLocked = FALSE;
9035 BOOLEAN bCleanExtents = FALSE;
9037 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
9038 ObjectInfo->Fcb != NULL)
9041 AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Resource,
9046 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
9047 AFS_TRACE_LEVEL_VERBOSE,
9048 "AFSPerformObjectInvalidate Acquiring Fcb extents lock %08lX SHARED %08lX\n",
9049 &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9050 PsGetCurrentThread());
9052 AFSAcquireShared( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9055 bExtentsLocked = TRUE;
9058 // There are several possibilities here:
9060 // 0. If there are no extents or all of the extents are dirty, do nothing.
9062 // 1. There could be nothing dirty and an open reference count of zero
9063 // in which case we can just tear down all of the extents without
9064 // holding any resources.
9066 // 2. There could be nothing dirty and a non-zero open reference count
9067 // in which case we can issue a CcPurge against the entire file
9068 // while holding just the Fcb Resource.
9070 // 3. There can be dirty extents in which case we need to identify
9071 // the non-dirty ranges and then perform a CcPurge on just the
9072 // non-dirty ranges while holding just the Fcb Resource.
9075 if ( ObjectInfo->Fcb->Specific.File.ExtentCount != ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount)
9078 if ( ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount == 0)
9081 if ( ObjectInfo->Fcb->OpenReferenceCount == 0)
9084 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9086 bExtentsLocked = FALSE;
9088 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9092 AFSTearDownFcbExtents( ObjectInfo->Fcb,
9101 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9103 bExtentsLocked = FALSE;
9105 if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
9106 !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9112 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
9113 AFS_TRACE_LEVEL_WARNING,
9114 "AFSPerformObjectInvalidation CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9115 ObjectInfo->FileId.Cell,
9116 ObjectInfo->FileId.Volume,
9117 ObjectInfo->FileId.Vnode,
9118 ObjectInfo->FileId.Unique);
9120 SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9125 bCleanExtents = TRUE;
9128 __except( EXCEPTION_EXECUTE_HANDLER)
9131 ntStatus = GetExceptionCode();
9135 "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
9136 ObjectInfo->FileId.Cell,
9137 ObjectInfo->FileId.Volume,
9138 ObjectInfo->FileId.Vnode,
9139 ObjectInfo->FileId.Unique,
9142 SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9150 // Must build a list of non-dirty ranges from the beginning of the file
9151 // to the end. There can be at most (Fcb->Specific.File.ExtentsDirtyCount + 1)
9152 // ranges. In all but the most extreme random data write scenario there will
9153 // be significantly fewer.
9155 // For each range we need offset and size.
9158 AFSByteRange * ByteRangeList = NULL;
9159 ULONG ulByteRangeCount = 0;
9161 BOOLEAN bPurgeOnClose = FALSE;
9166 ulByteRangeCount = AFSConstructCleanByteRangeList( ObjectInfo->Fcb,
9169 if ( ByteRangeList != NULL ||
9170 ulByteRangeCount == 0)
9173 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9175 bExtentsLocked = FALSE;
9177 for ( ulIndex = 0; ulIndex < ulByteRangeCount; ulIndex++)
9184 ulSize = ByteRangeList[ulIndex].Length.QuadPart > DWORD_MAX ? DWORD_MAX : ByteRangeList[ulIndex].Length.LowPart;
9186 if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
9187 !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9188 &ByteRangeList[ulIndex].FileOffset,
9193 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
9194 AFS_TRACE_LEVEL_WARNING,
9195 "AFSPerformObjectInvalidation [1] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9196 ObjectInfo->FileId.Cell,
9197 ObjectInfo->FileId.Volume,
9198 ObjectInfo->FileId.Vnode,
9199 ObjectInfo->FileId.Unique);
9201 bPurgeOnClose = TRUE;
9206 bCleanExtents = TRUE;
9209 ByteRangeList[ulIndex].Length.QuadPart -= ulSize;
9211 ByteRangeList[ulIndex].FileOffset.QuadPart += ulSize;
9213 } while ( ByteRangeList[ulIndex].Length.QuadPart > 0);
9220 // We couldn't allocate the memory to build the purge list
9221 // so just walk the extent list while holding the ExtentsList Resource.
9222 // This could deadlock but we do not have much choice.
9225 le = ObjectInfo->Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
9229 ulCount = (ULONG)ObjectInfo->Fcb->Specific.File.ExtentCount;
9233 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
9235 while( ulProcessCount < ulCount)
9237 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
9239 if( !BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
9241 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9242 &pEntry->FileOffset,
9247 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
9248 AFS_TRACE_LEVEL_WARNING,
9249 "AFSPerformObjectInvalidation [2] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9250 ObjectInfo->FileId.Cell,
9251 ObjectInfo->FileId.Volume,
9252 ObjectInfo->FileId.Vnode,
9253 ObjectInfo->FileId.Unique);
9255 bPurgeOnClose = TRUE;
9260 bCleanExtents = TRUE;
9264 if( liCurrentOffset.QuadPart < pEntry->FileOffset.QuadPart)
9267 liFlushLength.QuadPart = pEntry->FileOffset.QuadPart - liCurrentOffset.QuadPart;
9269 while( liFlushLength.QuadPart > 0)
9272 if( liFlushLength.QuadPart > 512 * 1024000)
9274 ulFlushLength = 512 * 1024000;
9278 ulFlushLength = liFlushLength.LowPart;
9281 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9287 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
9288 AFS_TRACE_LEVEL_WARNING,
9289 "AFSPerformObjectInvalidation [3] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9290 ObjectInfo->FileId.Cell,
9291 ObjectInfo->FileId.Volume,
9292 ObjectInfo->FileId.Vnode,
9293 ObjectInfo->FileId.Unique);
9295 bPurgeOnClose = TRUE;
9300 bCleanExtents = TRUE;
9303 liFlushLength.QuadPart -= ulFlushLength;
9307 liCurrentOffset.QuadPart = pEntry->FileOffset.QuadPart + pEntry->Size;
9315 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9321 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
9322 AFS_TRACE_LEVEL_WARNING,
9323 "AFSPerformObjectInvalidation [4] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9324 ObjectInfo->FileId.Cell,
9325 ObjectInfo->FileId.Volume,
9326 ObjectInfo->FileId.Vnode,
9327 ObjectInfo->FileId.Unique);
9329 bPurgeOnClose = TRUE;
9334 bCleanExtents = TRUE;
9341 SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9345 __except( EXCEPTION_EXECUTE_HANDLER)
9348 ntStatus = GetExceptionCode();
9352 "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
9353 ObjectInfo->FileId.Cell,
9354 ObjectInfo->FileId.Volume,
9355 ObjectInfo->FileId.Vnode,
9356 ObjectInfo->FileId.Unique,
9362 if ( bExtentsLocked)
9365 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9371 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9377 AFSReleaseCleanExtents( ObjectInfo->Fcb,
9386 if( ObjectInfo != NULL)
9389 AFSObjectInfoDecrement( ObjectInfo);