2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011, 2012, 2013 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
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
16 * nor the names of their contributors may be used to endorse or promote
17 * products derived from this software without specific prior written
18 * permission from Kernel Drivers, LLC and Your File System, Inc.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
24 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 // File: AFSGeneric.cpp
37 #include "AFSCommon.h"
40 // Function: AFSExceptionFilter
44 // This function is the exception handler
48 // A status is returned for the function
52 AFSExceptionFilter( IN CHAR *FunctionString,
54 IN PEXCEPTION_POINTERS ExceptPtrs)
57 UNREFERENCED_PARAMETER(Code);
58 PEXCEPTION_RECORD ExceptRec;
64 ExceptRec = ExceptPtrs->ExceptionRecord;
66 Context = ExceptPtrs->ContextRecord;
70 "AFSExceptionFilter (Library) - EXR %p CXR %p Function %s Code %08lX Address %p Routine %p\n",
74 ExceptRec->ExceptionCode,
75 ExceptRec->ExceptionAddress,
76 (void *)AFSExceptionFilter));
78 DbgPrint("**** Exception Caught in AFS Redirector Library ****\n");
80 DbgPrint("\n\nPerform the following WnDbg Cmds:\n");
81 DbgPrint("\n\t.exr %p ; .cxr %p\n\n", ExceptRec, Context);
83 DbgPrint("**** Exception Complete from AFS Redirector Library ****\n");
85 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION))
88 KeBugCheck( (ULONG)-2);
96 __except( EXCEPTION_EXECUTE_HANDLER)
102 return EXCEPTION_EXECUTE_HANDLER;
106 // Function: AFSLibExAllocatePoolWithTag()
108 // Purpose: Allocate Pool Memory. If BugCheck Exception flag
109 // is configured on, then bugcheck the system if
110 // a memory allocation fails. The routine should be
111 // used for all memory allocations that are to be freed
112 // when the library is unloaded. Memory allocations that
113 // are to survive library unload and reload should be
114 // performed using AFSExAllocatePoolWithTag() which is
115 // provided by the AFS Framework.
118 // POOL_TYPE PoolType - Paged or NonPaged
119 // SIZE_T NumberOfBytes - requested allocation size
120 // ULONG Tag - Pool Allocation Tag to be applied for tracking
123 // void * - the memory allocation
127 AFSLibExAllocatePoolWithTag( IN POOL_TYPE PoolType,
128 IN SIZE_T NumberOfBytes,
132 void *pBuffer = NULL;
134 pBuffer = ExAllocatePoolWithTag( PoolType,
141 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION))
144 KeBugCheck( (ULONG)-2);
151 "AFSLibExAllocatePoolWithTag failure Type %08lX Size %08lX Tag %08lX %08lX\n",
155 PsGetCurrentThread()));
165 // Function: AFSAcquireExcl()
167 // Purpose: Called to acquire a resource exclusive with optional wait
170 // PERESOURCE Resource - Resource to acquire
171 // BOOLEAN Wait - Whether to block
174 // BOOLEAN - Whether the mask was acquired
178 AFSAcquireExcl( IN PERESOURCE Resource,
182 BOOLEAN bStatus = FALSE;
185 // Normal kernel APCs must be disabled before calling
186 // ExAcquireResourceExclusiveLite. Otherwise a bugcheck occurs.
189 KeEnterCriticalRegion();
191 bStatus = ExAcquireResourceExclusiveLite( Resource,
197 KeLeaveCriticalRegion();
204 AFSAcquireSharedStarveExclusive( IN PERESOURCE Resource,
208 BOOLEAN bStatus = FALSE;
210 KeEnterCriticalRegion();
212 bStatus = ExAcquireSharedStarveExclusive( Resource,
218 KeLeaveCriticalRegion();
225 // Function: AFSAcquireShared()
227 // Purpose: Called to acquire a resource shared with optional wait
230 // PERESOURCE Resource - Resource to acquire
231 // BOOLEAN Wait - Whether to block
234 // BOOLEAN - Whether the mask was acquired
238 AFSAcquireShared( IN PERESOURCE Resource,
242 BOOLEAN bStatus = FALSE;
244 KeEnterCriticalRegion();
246 bStatus = ExAcquireResourceSharedLite( Resource,
252 KeLeaveCriticalRegion();
259 // Function: AFSReleaseResource()
261 // Purpose: Called to release a resource
264 // PERESOURCE Resource - Resource to release
271 AFSReleaseResource( IN PERESOURCE Resource)
274 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
275 AFS_TRACE_LEVEL_VERBOSE,
276 "AFSReleaseResource Releasing lock %p Thread %08lX\n",
278 PsGetCurrentThread()));
280 ExReleaseResourceLite( Resource);
282 KeLeaveCriticalRegion();
288 AFSConvertToShared( IN PERESOURCE Resource)
291 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
292 AFS_TRACE_LEVEL_VERBOSE,
293 "AFSConvertToShared Converting lock %p Thread %08lX\n",
295 PsGetCurrentThread()));
297 ExConvertExclusiveToSharedLite( Resource);
303 // Function: AFSCompleteRequest
307 // This function completes irps
311 // A status is returned for the function
315 AFSCompleteRequest( IN PIRP Irp,
319 Irp->IoStatus.Status = Status;
321 IoCompleteRequest( Irp,
328 // Function: AFSGenerateCRC
332 // Given a device and filename this function generates a CRC
336 // A status is returned for the function
340 AFSGenerateCRC( IN PUNICODE_STRING FileName,
341 IN BOOLEAN UpperCaseName)
345 NTSTATUS ntStatus = STATUS_SUCCESS;
347 ntStatus = RtlHashUnicodeString( FileName,
349 HASH_STRING_ALGORITHM_DEFAULT,
352 if( !NT_SUCCESS( ntStatus))
361 AFSLockSystemBuffer( IN PIRP Irp,
365 void *pAddress = NULL;
367 if( Irp->MdlAddress != NULL)
370 pAddress = MmGetSystemAddressForMdlSafe( Irp->MdlAddress,
373 else if( Irp->AssociatedIrp.SystemBuffer != NULL)
376 pAddress = Irp->AssociatedIrp.SystemBuffer;
378 else if( Irp->UserBuffer != NULL)
381 Irp->MdlAddress = IoAllocateMdl( Irp->UserBuffer,
387 if( Irp->MdlAddress != NULL)
391 // Lock the new Mdl in memory.
396 PIO_STACK_LOCATION pIoStack;
397 pIoStack = IoGetCurrentIrpStackLocation( Irp);
400 MmProbeAndLockPages( Irp->MdlAddress, KernelMode,
401 (pIoStack->MajorFunction == IRP_MJ_READ) ? IoWriteAccess : IoReadAccess);
403 pAddress = MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority );
406 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
409 AFSDumpTraceFilesFnc();
411 IoFreeMdl( Irp->MdlAddress );
412 Irp->MdlAddress = NULL;
422 AFSLockUserBuffer( IN void *UserBuffer,
423 IN ULONG BufferLength,
427 NTSTATUS ntStatus = STATUS_SUCCESS;
428 void *pAddress = NULL;
434 pMdl = IoAllocateMdl( UserBuffer,
443 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
447 // Lock the new Mdl in memory.
453 MmProbeAndLockPages( pMdl,
457 pAddress = MmGetSystemAddressForMdlSafe( pMdl,
460 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
463 AFSDumpTraceFilesFnc();
485 AFSMapToService( IN PIRP Irp,
489 NTSTATUS ntStatus = STATUS_SUCCESS;
490 void *pMappedBuffer = NULL;
491 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
497 if( pDevExt->Specific.Control.ServiceProcess == NULL)
500 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
503 if( Irp->MdlAddress == NULL)
506 if( AFSLockSystemBuffer( Irp,
510 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
515 // Attach to the service process for mapping
518 KeStackAttachProcess( pDevExt->Specific.Control.ServiceProcess,
519 (PRKAPC_STATE)&stApcState);
521 pMappedBuffer = MmMapLockedPagesSpecifyCache( Irp->MdlAddress,
528 KeUnstackDetachProcess( (PRKAPC_STATE)&stApcState);
535 return pMappedBuffer;
539 AFSUnmapServiceMappedBuffer( IN void *MappedBuffer,
543 NTSTATUS ntStatus = STATUS_SUCCESS;
544 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
550 if( pDevExt->Specific.Control.ServiceProcess == NULL)
553 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
560 // Attach to the service process for mapping
563 KeStackAttachProcess( pDevExt->Specific.Control.ServiceProcess,
564 (PRKAPC_STATE)&stApcState);
566 MmUnmapLockedPages( MappedBuffer,
569 KeUnstackDetachProcess( (PRKAPC_STATE)&stApcState);
581 AFSInitializeLibraryDevice()
584 NTSTATUS ntStatus = STATUS_SUCCESS;
585 AFSDeviceExt *pDeviceExt = NULL;
590 pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
593 // The PIOCtl file name
596 RtlInitUnicodeString( &AFSPIOCtlName,
597 AFS_PIOCTL_FILE_INTERFACE_NAME);
600 // And the global root share name
603 RtlInitUnicodeString( &AFSGlobalRootName,
604 AFS_GLOBAL_ROOT_SHARE_NAME);
612 AFSRemoveLibraryDevice()
615 NTSTATUS ntStatus = STATUS_SUCCESS;
626 AFSDefaultDispatch( IN PDEVICE_OBJECT DeviceObject,
630 UNREFERENCED_PARAMETER(DeviceObject);
631 NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
633 AFSCompleteRequest( Irp,
640 AFSInitializeGlobalDirectoryEntries()
643 NTSTATUS ntStatus = STATUS_SUCCESS;
644 AFSDirectoryCB *pDirNode = NULL;
645 ULONG ulEntryLength = 0;
646 AFSObjectInfoCB *pObjectInfoCB = NULL;
647 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
654 // Initialize the global . entry
657 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
660 if( pObjectInfoCB == NULL)
663 AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
664 AFS_TRACE_LEVEL_ERROR,
665 "AFSInitializeGlobalDirectory AFSAllocateObjectInfo failure %08lX\n",
668 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
671 lCount = AFSObjectInfoIncrement( pObjectInfoCB,
672 AFS_OBJECT_REFERENCE_GLOBAL);
674 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
675 AFS_TRACE_LEVEL_VERBOSE,
676 "AFSInitializeGlobalDirectoryEntries Increment count on object %p Cnt %d\n",
680 ntStatus = STATUS_SUCCESS;
682 ulEntryLength = sizeof( AFSDirectoryCB) +
685 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
689 if( pDirNode == NULL)
692 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
693 AFS_OBJECT_REFERENCE_GLOBAL);
695 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
696 AFS_TRACE_LEVEL_VERBOSE,
697 "AFSInitializeGlobalDirectoryEntries Decrement count on object %p Cnt %d\n",
704 AFSDeleteObjectInfo( &pObjectInfoCB);
707 AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
708 AFS_TRACE_LEVEL_ERROR,
709 "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_TAG allocation failure\n"));
711 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
714 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
715 AFS_TRACE_LEVEL_VERBOSE,
716 "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_TAG allocated %p\n",
719 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
720 sizeof( AFSNonPagedDirectoryCB),
721 AFS_DIR_ENTRY_NP_TAG);
723 if( pNonPagedDirEntry == NULL)
726 ExFreePool( pDirNode);
728 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
729 AFS_OBJECT_REFERENCE_GLOBAL);
731 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
732 AFS_TRACE_LEVEL_VERBOSE,
733 "AFSInitializeGlobalDirectoryEntries Decrement count on object %p Cnt %d\n",
740 AFSDeleteObjectInfo( &pObjectInfoCB);
743 AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
744 AFS_TRACE_LEVEL_ERROR,
745 "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_NP_TAG allocation failure\n"));
747 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
750 RtlZeroMemory( pDirNode,
753 RtlZeroMemory( pNonPagedDirEntry,
754 sizeof( AFSNonPagedDirectoryCB));
756 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
758 pDirNode->NonPaged = pNonPagedDirEntry;
760 pDirNode->ObjectInformation = pObjectInfoCB;
766 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE | AFS_DIR_ENTRY_FAKE | AFS_DIR_ENTRY_VALID);
768 pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_DOT_INDEX;
771 // Setup the names in the entry
774 pDirNode->NameInformation.FileName.Length = sizeof( WCHAR);
776 pDirNode->NameInformation.FileName.MaximumLength = sizeof( WCHAR);
778 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
780 pDirNode->NameInformation.FileName.Buffer[ 0] = L'.';
783 // Populate the rest of the data
786 pObjectInfoCB->FileType = AFS_FILE_TYPE_DIRECTORY;
788 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
790 AFSGlobalDotDirEntry = pDirNode;
796 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
799 if( pObjectInfoCB == NULL)
802 AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
803 AFS_TRACE_LEVEL_ERROR,
804 "AFSInitializeGlobalDirectory AFSAllocateObjectInfo (2) failure %08lX\n",
807 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
810 lCount = AFSObjectInfoIncrement( pObjectInfoCB,
811 AFS_OBJECT_REFERENCE_GLOBAL);
813 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
814 AFS_TRACE_LEVEL_VERBOSE,
815 "AFSInitializeGlobalDirectoryEntries Increment count on object %p Cnt %d\n",
819 ntStatus = STATUS_SUCCESS;
821 ulEntryLength = sizeof( AFSDirectoryCB) +
822 ( 2 * sizeof( WCHAR));
824 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
828 if( pDirNode == NULL)
831 AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
832 AFS_TRACE_LEVEL_ERROR,
833 "AFSInitializeGlobalDirectoryEntries AFS_DIR_ENTRY_TAG allocation failure\n"));
835 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
836 AFS_OBJECT_REFERENCE_GLOBAL);
838 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
839 AFS_TRACE_LEVEL_VERBOSE,
840 "AFSInitializeGlobalDirectoryEntries Decrement count on object %p Cnt %d\n",
847 AFSDeleteObjectInfo( &pObjectInfoCB);
850 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
853 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
854 AFS_TRACE_LEVEL_VERBOSE,
855 "AFSInitializeGlobalDirectoryEntries AFS_DIR_ENTRY_TAG allocated %p\n",
858 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
859 sizeof( AFSNonPagedDirectoryCB),
860 AFS_DIR_ENTRY_NP_TAG);
862 if( pNonPagedDirEntry == NULL)
865 ExFreePool( pDirNode);
867 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
868 AFS_OBJECT_REFERENCE_GLOBAL);
870 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
871 AFS_TRACE_LEVEL_VERBOSE,
872 "AFSInitializeGlobalDirectoryEntries Decrement count on object %p Cnt %d\n",
879 AFSDeleteObjectInfo( &pObjectInfoCB);
882 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
885 RtlZeroMemory( pDirNode,
888 RtlZeroMemory( pNonPagedDirEntry,
889 sizeof( AFSNonPagedDirectoryCB));
891 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
893 pDirNode->NonPaged = pNonPagedDirEntry;
895 pDirNode->ObjectInformation = pObjectInfoCB;
901 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE | AFS_DIR_ENTRY_FAKE | AFS_DIR_ENTRY_VALID);
903 pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX;
906 // Setup the names in the entry
909 pDirNode->NameInformation.FileName.Length = 2 * sizeof( WCHAR);
911 pDirNode->NameInformation.FileName.MaximumLength = 2 * sizeof( WCHAR);
913 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
915 pDirNode->NameInformation.FileName.Buffer[ 0] = L'.';
917 pDirNode->NameInformation.FileName.Buffer[ 1] = L'.';
920 // Populate the rest of the data
923 pObjectInfoCB->FileType = AFS_FILE_TYPE_DIRECTORY;
925 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
927 AFSGlobalDotDotDirEntry = pDirNode;
931 if( !NT_SUCCESS( ntStatus))
934 if( AFSGlobalDotDirEntry != NULL)
937 lCount = AFSObjectInfoDecrement( AFSGlobalDotDirEntry->ObjectInformation,
938 AFS_OBJECT_REFERENCE_GLOBAL);
940 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
941 AFS_TRACE_LEVEL_VERBOSE,
942 "AFSInitializeGlobalDirectoryEntries Decrement count on object %p Cnt %d\n",
943 AFSGlobalDotDirEntry->ObjectInformation,
949 AFSDeleteObjectInfo( &AFSGlobalDotDirEntry->ObjectInformation);
952 ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
954 ExFreePool( AFSGlobalDotDirEntry->NonPaged);
956 ExFreePool( AFSGlobalDotDirEntry);
958 AFSGlobalDotDirEntry = NULL;
961 if( AFSGlobalDotDotDirEntry != NULL)
964 lCount = AFSObjectInfoDecrement( AFSGlobalDotDotDirEntry->ObjectInformation,
965 AFS_OBJECT_REFERENCE_GLOBAL);
967 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
968 AFS_TRACE_LEVEL_VERBOSE,
969 "AFSInitializeGlobalDirectoryEntries Decrement count on object %p Cnt %d\n",
970 AFSGlobalDotDotDirEntry->ObjectInformation,
976 AFSDeleteObjectInfo( &AFSGlobalDotDotDirEntry->ObjectInformation);
979 ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
981 ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
983 ExFreePool( AFSGlobalDotDotDirEntry);
985 AFSGlobalDotDotDirEntry = NULL;
994 AFSInitDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
995 IN PUNICODE_STRING FileName,
996 IN PUNICODE_STRING TargetName,
997 IN AFSDirEnumEntry *DirEnumEntry,
1001 AFSDirectoryCB *pDirNode = NULL;
1002 NTSTATUS ntStatus = STATUS_SUCCESS;
1003 ULONG ulEntryLength = 0;
1004 AFSObjectInfoCB *pObjectInfoCB = NULL;
1005 ULONGLONG ullIndex = 0;
1006 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
1012 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1013 AFS_TRACE_LEVEL_VERBOSE,
1014 "AFSInitDirEntry Initializing entry %wZ parent FID %08lX-%08lX-%08lX-%08lX\n",
1016 ParentObjectInfo->FileId.Cell,
1017 ParentObjectInfo->FileId.Volume,
1018 ParentObjectInfo->FileId.Vnode,
1019 ParentObjectInfo->FileId.Unique));
1022 // First thing is to locate/create our object information block
1026 AFSAcquireExcl( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
1029 ullIndex = AFSCreateLowIndex( &DirEnumEntry->FileId);
1031 ntStatus = AFSLocateHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
1033 (AFSBTreeEntry **)&pObjectInfoCB);
1035 if( !NT_SUCCESS( ntStatus))
1039 // Allocate our object info cb
1042 pObjectInfoCB = AFSAllocateObjectInfo( ParentObjectInfo,
1045 if( pObjectInfoCB == NULL)
1048 AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
1050 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1053 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1054 AFS_TRACE_LEVEL_VERBOSE,
1055 "AFSInitDirEntry initialized object %p Parent Object %p for %wZ\n",
1061 // If we allocated the object information cb then set the information
1064 pObjectInfoCB->FileId = DirEnumEntry->FileId;
1066 pObjectInfoCB->TargetFileId = DirEnumEntry->TargetFileId;
1068 pObjectInfoCB->FileType = DirEnumEntry->FileType;
1070 pObjectInfoCB->FileAttributes = DirEnumEntry->FileAttributes;
1072 if( pObjectInfoCB->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1073 pObjectInfoCB->FileType == AFS_FILE_TYPE_DFSLINK)
1076 pObjectInfoCB->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1079 if (pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK)
1082 if ( pObjectInfoCB->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1085 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1090 pObjectInfoCB->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1095 // Check for the case where we have a filetype of SymLink but both the TargetFid and the
1096 // TargetName are empty. In this case set the filetype to zero so we evaluate it later in
1100 if( pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK &&
1101 pObjectInfoCB->TargetFileId.Vnode == 0 &&
1102 pObjectInfoCB->TargetFileId.Unique == 0 &&
1103 (TargetName == NULL || TargetName->Length == 0))
1107 // This will ensure we perform a validation on the node
1110 pObjectInfoCB->FileType = AFS_FILE_TYPE_UNKNOWN;
1113 if( pObjectInfoCB->FileType == AFS_FILE_TYPE_UNKNOWN)
1116 SetFlag( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
1119 SetFlag( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
1122 if ( BooleanFlagOn( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY))
1125 pObjectInfoCB->CreationTime = DirEnumEntry->CreationTime;
1127 pObjectInfoCB->LastAccessTime = DirEnumEntry->LastAccessTime;
1129 pObjectInfoCB->LastWriteTime = DirEnumEntry->LastWriteTime;
1131 pObjectInfoCB->ChangeTime = DirEnumEntry->ChangeTime;
1133 pObjectInfoCB->EndOfFile = DirEnumEntry->EndOfFile;
1135 pObjectInfoCB->AllocationSize = DirEnumEntry->AllocationSize;
1137 pObjectInfoCB->EaSize = DirEnumEntry->EaSize;
1139 pObjectInfoCB->Links = DirEnumEntry->Links;
1141 pObjectInfoCB->Expiration = DirEnumEntry->Expiration;
1143 pObjectInfoCB->DataVersion = DirEnumEntry->DataVersion;
1145 ClearFlag( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
1149 // This reference count is either stored into the return DirectoryCB
1150 // or released before function exit.
1153 lCount = AFSObjectInfoIncrement( pObjectInfoCB,
1154 AFS_OBJECT_REFERENCE_DIRENTRY);
1156 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1157 AFS_TRACE_LEVEL_VERBOSE,
1158 "AFSInitDirEntry Increment count on object %p Cnt %d\n",
1162 KeQueryTickCount( &pObjectInfoCB->LastAccessCount);
1164 AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
1166 ntStatus = STATUS_SUCCESS;
1168 ulEntryLength = sizeof( AFSDirectoryCB) +
1171 if( TargetName != NULL)
1174 ulEntryLength += TargetName->Length;
1177 pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
1181 if( pDirNode == NULL)
1184 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1187 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1188 AFS_TRACE_LEVEL_VERBOSE,
1189 "AFSInitDirEntry AFS_DIR_ENTRY_TAG allocated %p\n",
1192 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
1193 sizeof( AFSNonPagedDirectoryCB),
1194 AFS_DIR_ENTRY_NP_TAG);
1196 if( pNonPagedDirEntry == NULL)
1199 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1202 RtlZeroMemory( pDirNode,
1205 RtlZeroMemory( pNonPagedDirEntry,
1206 sizeof( AFSNonPagedDirectoryCB));
1208 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
1210 pDirNode->NonPaged = pNonPagedDirEntry;
1212 pDirNode->ObjectInformation = pObjectInfoCB;
1215 // Set valid entry and NOT_IN_PARENT flag
1218 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1220 pDirNode->FileIndex = FileIndex;
1223 // Setup the names in the entry
1226 if( FileName->Length > 0)
1229 pDirNode->NameInformation.FileName.Length = FileName->Length;
1231 pDirNode->NameInformation.FileName.MaximumLength = FileName->Length;
1233 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
1235 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
1237 pDirNode->NameInformation.FileName.Length);
1240 // Create a CRC for the file
1243 pDirNode->CaseSensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1246 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1250 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1251 AFS_TRACE_LEVEL_VERBOSE,
1252 "AFSInitDirEntry Initialized DE %p for %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1255 ParentObjectInfo->FileId.Cell,
1256 ParentObjectInfo->FileId.Volume,
1257 ParentObjectInfo->FileId.Vnode,
1258 ParentObjectInfo->FileId.Unique));
1260 if( TargetName != NULL &&
1261 TargetName->Length > 0)
1264 pDirNode->NameInformation.TargetName.Length = TargetName->Length;
1266 pDirNode->NameInformation.TargetName.MaximumLength = pDirNode->NameInformation.TargetName.Length;
1268 pDirNode->NameInformation.TargetName.Buffer = (WCHAR *)((char *)pDirNode +
1269 sizeof( AFSDirectoryCB) +
1270 pDirNode->NameInformation.FileName.Length);
1272 RtlCopyMemory( pDirNode->NameInformation.TargetName.Buffer,
1274 pDirNode->NameInformation.TargetName.Length);
1280 if( !NT_SUCCESS( ntStatus))
1283 if( pNonPagedDirEntry != NULL)
1286 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
1288 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
1291 if( pDirNode != NULL)
1294 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1295 AFS_TRACE_LEVEL_VERBOSE,
1296 "AFSInitDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
1299 AFSExFreePoolWithTag( pDirNode, AFS_DIR_ENTRY_TAG);
1305 // Dereference our object info block if we have one
1308 if( pObjectInfoCB != NULL)
1311 AFSAcquireShared( pObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock,
1314 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
1315 AFS_OBJECT_REFERENCE_DIRENTRY);
1317 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1318 AFS_TRACE_LEVEL_VERBOSE,
1319 "AFSInitDirEntry Decrement count on object %p Cnt %d\n",
1323 AFSReleaseResource( pObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock);
1332 AFSCheckForReadOnlyAccess( IN ACCESS_MASK DesiredAccess,
1333 IN BOOLEAN DirectoryEntry)
1336 BOOLEAN bReturn = TRUE;
1337 ACCESS_MASK stAccessMask = 0;
1340 // Get rid of anything we don't know about
1343 DesiredAccess = (DesiredAccess &
1349 ACCESS_SYSTEM_SECURITY |
1353 FILE_READ_ATTRIBUTES |
1354 FILE_WRITE_ATTRIBUTES |
1355 FILE_LIST_DIRECTORY |
1361 // Our 'read only' access mask. These are the accesses we will
1362 // allow for a read only file
1365 stAccessMask = DELETE |
1370 ACCESS_SYSTEM_SECURITY |
1374 FILE_READ_ATTRIBUTES |
1375 FILE_WRITE_ATTRIBUTES |
1377 FILE_LIST_DIRECTORY |
1381 // For a directory, add in the directory specific accesses
1387 stAccessMask |= FILE_ADD_SUBDIRECTORY |
1392 if( FlagOn( DesiredAccess, ~stAccessMask))
1396 // A write access is set ...
1406 AFSEvaluateNode( IN GUID *AuthGroup,
1407 IN AFSDirectoryCB *DirEntry)
1410 NTSTATUS ntStatus = STATUS_SUCCESS;
1411 AFSDirEnumEntry *pDirEntry = NULL;
1412 UNICODE_STRING uniTargetName;
1417 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1422 if( !NT_SUCCESS( ntStatus))
1425 try_return( ntStatus);
1428 DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1430 DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1432 DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1434 DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1436 DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1438 DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1440 DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1442 DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1444 DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1446 DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1448 DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1450 if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1451 pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1454 DirEntry->ObjectInformation->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1457 if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK)
1460 if ( DirEntry->ObjectInformation->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1463 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1468 DirEntry->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1472 DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1474 DirEntry->ObjectInformation->Links = pDirEntry->Links;
1477 // If we have a target name then see if it needs updating ...
1480 if( pDirEntry->TargetNameLength > 0)
1484 // Update the target name information if needed
1487 uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1489 uniTargetName.MaximumLength = uniTargetName.Length;
1491 uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1493 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1496 if( DirEntry->NameInformation.TargetName.Length == 0 ||
1497 RtlCompareUnicodeString( &uniTargetName,
1498 &DirEntry->NameInformation.TargetName,
1503 // Update the target name
1506 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1508 uniTargetName.Buffer,
1509 uniTargetName.Length);
1511 if( !NT_SUCCESS( ntStatus))
1514 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1516 try_return( ntStatus);
1520 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1525 if( pDirEntry != NULL)
1528 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
1536 AFSValidateSymLink( IN GUID *AuthGroup,
1537 IN AFSDirectoryCB *DirEntry)
1540 NTSTATUS ntStatus = STATUS_SUCCESS;
1541 AFSDirEnumEntry *pDirEntry = NULL;
1542 UNICODE_STRING uniTargetName;
1547 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1552 if( !NT_SUCCESS( ntStatus))
1555 try_return( ntStatus);
1558 if( pDirEntry->FileType == AFS_FILE_TYPE_UNKNOWN ||
1559 pDirEntry->FileType == AFS_FILE_TYPE_INVALID)
1562 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1563 AFS_TRACE_LEVEL_VERBOSE_2,
1564 "AFSValidateSymLink Invalid type Status %08lX\n",
1565 STATUS_OBJECT_NAME_NOT_FOUND));
1567 try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
1570 DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1572 DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1574 DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1577 // Update the target name information if needed
1580 uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1582 uniTargetName.MaximumLength = uniTargetName.Length;
1584 uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1586 if( uniTargetName.Length > 0)
1589 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1592 if( DirEntry->NameInformation.TargetName.Length == 0 ||
1593 RtlCompareUnicodeString( &uniTargetName,
1594 &DirEntry->NameInformation.TargetName,
1599 // Update the target name
1602 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1604 uniTargetName.Buffer,
1605 uniTargetName.Length);
1607 if( !NT_SUCCESS( ntStatus))
1610 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1612 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1616 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1620 // If the FileType is the same then nothing to do since it IS
1624 if( pDirEntry->FileType == DirEntry->ObjectInformation->FileType)
1627 ASSERT( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK);
1629 try_return( ntStatus = STATUS_SUCCESS);
1632 DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1634 DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1636 DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1638 DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1640 DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1642 DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1644 DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1646 DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1648 if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1649 pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1652 DirEntry->ObjectInformation->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1655 if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK)
1658 if ( DirEntry->ObjectInformation->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1661 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1666 DirEntry->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1670 DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1672 DirEntry->ObjectInformation->Links = pDirEntry->Links;
1676 if( pDirEntry != NULL)
1679 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
1687 AFSInvalidateObject( IN OUT AFSObjectInfoCB **ppObjectInfo,
1691 NTSTATUS ntStatus = STATUS_SUCCESS;
1692 IO_STATUS_BLOCK stIoStatus;
1694 AFSObjectInfoCB * pParentObjectInfo = NULL;
1696 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1697 AFS_TRACE_LEVEL_VERBOSE,
1698 "AFSInvalidateObject Invalidation on node type %d for fid %08lX-%08lX-%08lX-%08lX Reason %d\n",
1699 (*ppObjectInfo)->FileType,
1700 (*ppObjectInfo)->FileId.Cell,
1701 (*ppObjectInfo)->FileId.Volume,
1702 (*ppObjectInfo)->FileId.Vnode,
1703 (*ppObjectInfo)->FileId.Unique,
1706 if ( BooleanFlagOn( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1709 pParentObjectInfo = AFSFindObjectInfo( (*ppObjectInfo)->VolumeCB,
1710 &(*ppObjectInfo)->ParentFileId,
1714 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_SYMLINK ||
1715 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DFSLINK ||
1716 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1719 // We only act on the mount point itself, not the target. If the
1720 // node has been deleted then mark it as such otherwise indicate
1721 // it requires verification
1724 if( Reason == AFS_INVALIDATE_DELETED)
1726 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
1731 if( Reason == AFS_INVALIDATE_FLUSHED)
1734 (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1736 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1739 (*ppObjectInfo)->Expiration.QuadPart = 0;
1741 (*ppObjectInfo)->TargetFileId.Vnode = 0;
1743 (*ppObjectInfo)->TargetFileId.Unique = 0;
1745 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1746 AFS_TRACE_LEVEL_VERBOSE,
1747 "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1748 (*ppObjectInfo)->FileId.Cell,
1749 (*ppObjectInfo)->FileId.Volume,
1750 (*ppObjectInfo)->FileId.Vnode,
1751 (*ppObjectInfo)->FileId.Unique));
1753 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1756 if ( pParentObjectInfo != NULL)
1759 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1761 if( Reason == AFS_INVALIDATE_CREDS)
1763 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1766 if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1767 Reason == AFS_INVALIDATE_FLUSHED)
1769 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1773 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1776 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1779 FILE_ACTION_MODIFIED);
1782 try_return( ntStatus);
1786 // Depending on the reason for invalidation then perform work on the node
1792 case AFS_INVALIDATE_DELETED:
1796 // Mark this node as invalid
1799 (*ppObjectInfo)->Links = 0;
1801 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_DELETED);
1803 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1804 AFS_TRACE_LEVEL_VERBOSE,
1805 "AFSInvalidateObject Set DELETE flag on fid %08lX-%08lX-%08lX-%08lX\n",
1806 (*ppObjectInfo)->FileId.Cell,
1807 (*ppObjectInfo)->FileId.Volume,
1808 (*ppObjectInfo)->FileId.Vnode,
1809 (*ppObjectInfo)->FileId.Unique));
1811 if( pParentObjectInfo != NULL)
1814 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1815 AFS_TRACE_LEVEL_VERBOSE,
1816 "AFSInvalidateObject Set VERIFY flag on parent fid %08lX-%08lX-%08lX-%08lX\n",
1817 pParentObjectInfo->FileId.Cell,
1818 pParentObjectInfo->FileId.Volume,
1819 pParentObjectInfo->FileId.Vnode,
1820 pParentObjectInfo->FileId.Unique));
1822 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1824 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1826 pParentObjectInfo->Expiration.QuadPart = 0;
1828 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1830 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1834 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1837 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1840 FILE_ACTION_REMOVED);
1843 if( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1846 (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1852 case AFS_INVALIDATE_FLUSHED:
1855 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1856 (*ppObjectInfo)->Fcb != NULL)
1859 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1860 AFS_TRACE_LEVEL_VERBOSE,
1861 "AFSInvalidateObject Flush/purge file fid %08lX-%08lX-%08lX-%08lX\n",
1862 (*ppObjectInfo)->FileId.Cell,
1863 (*ppObjectInfo)->FileId.Volume,
1864 (*ppObjectInfo)->FileId.Vnode,
1865 (*ppObjectInfo)->FileId.Unique));
1867 AFSAcquireExcl( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectResource,
1873 CcFlushCache( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1878 if( !NT_SUCCESS( stIoStatus.Status))
1881 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1882 AFS_TRACE_LEVEL_ERROR,
1883 "AFSInvalidateObject CcFlushCache failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1884 (*ppObjectInfo)->FileId.Cell,
1885 (*ppObjectInfo)->FileId.Volume,
1886 (*ppObjectInfo)->FileId.Vnode,
1887 (*ppObjectInfo)->FileId.Unique,
1889 stIoStatus.Information));
1891 ntStatus = stIoStatus.Status;
1895 if ( (*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
1898 if ( !CcPurgeCacheSection( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1904 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1905 AFS_TRACE_LEVEL_WARNING,
1906 "AFSInvalidateObject CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
1907 (*ppObjectInfo)->FileId.Cell,
1908 (*ppObjectInfo)->FileId.Volume,
1909 (*ppObjectInfo)->FileId.Vnode,
1910 (*ppObjectInfo)->FileId.Unique));
1912 SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1916 __except( EXCEPTION_EXECUTE_HANDLER)
1919 ntStatus = GetExceptionCode();
1923 "EXCEPTION - AFSInvalidateObject Cc FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
1924 (*ppObjectInfo)->FileId.Cell,
1925 (*ppObjectInfo)->FileId.Volume,
1926 (*ppObjectInfo)->FileId.Vnode,
1927 (*ppObjectInfo)->FileId.Unique,
1930 SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1933 AFSReleaseResource( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectResource);
1936 // Clear out the extents
1937 // Get rid of them (note this involves waiting
1938 // for any writes or reads to the cache to complete)
1941 AFSTearDownFcbExtents( (*ppObjectInfo)->Fcb,
1945 (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1948 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE)
1951 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1952 AFS_TRACE_LEVEL_VERBOSE,
1953 "AFSInvalidateObject Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
1954 (*ppObjectInfo)->FileId.Cell,
1955 (*ppObjectInfo)->FileId.Volume,
1956 (*ppObjectInfo)->FileId.Vnode,
1957 (*ppObjectInfo)->FileId.Unique));
1959 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1962 // Fall through to the default processing
1968 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1970 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1974 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1977 if( Reason == AFS_INVALIDATE_CREDS)
1979 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1982 if( Reason == AFS_INVALIDATE_DATA_VERSION)
1984 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1988 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1991 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1994 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo),
1997 FILE_ACTION_MODIFIED);
1999 else if ( pParentObjectInfo != NULL)
2002 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
2005 FILE_ACTION_MODIFIED);
2009 // Indicate this node requires re-evaluation for the remaining reasons
2012 (*ppObjectInfo)->Expiration.QuadPart = 0;
2014 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2015 AFS_TRACE_LEVEL_VERBOSE,
2016 "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
2017 (*ppObjectInfo)->FileId.Cell,
2018 (*ppObjectInfo)->FileId.Volume,
2019 (*ppObjectInfo)->FileId.Vnode,
2020 (*ppObjectInfo)->FileId.Unique));
2022 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
2024 if( Reason == AFS_INVALIDATE_DATA_VERSION ||
2025 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
2026 ( Reason == AFS_INVALIDATE_CALLBACK ||
2027 Reason == AFS_INVALIDATE_EXPIRED))
2029 if ( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
2030 AFS_INVALIDATE_DATA_VERSION)))
2033 (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
2043 if ( pParentObjectInfo != NULL)
2046 AFSReleaseObjectInfo( &pParentObjectInfo);
2053 AFSInvalidateCache( IN AFSInvalidateCacheCB *InvalidateCB)
2056 NTSTATUS ntStatus = STATUS_SUCCESS;
2057 AFSVolumeCB *pVolumeCB = NULL;
2058 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2059 ULONGLONG ullIndex = 0;
2060 AFSObjectInfoCB *pObjectInfo = NULL;
2066 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2067 AFS_TRACE_LEVEL_VERBOSE,
2068 "AFSInvalidateCache Invalidation FID %08lX-%08lX-%08lX-%08lX Type %d WholeVolume %d Reason %d\n",
2069 InvalidateCB->FileID.Cell,
2070 InvalidateCB->FileID.Volume,
2071 InvalidateCB->FileID.Vnode,
2072 InvalidateCB->FileID.Unique,
2073 InvalidateCB->FileType,
2074 InvalidateCB->WholeVolume,
2075 InvalidateCB->Reason));
2078 // Need to locate the Fcb for the directory to purge
2081 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2082 AFS_TRACE_LEVEL_VERBOSE,
2083 "AFSInvalidateCache Acquiring RDR VolumeTreeLock lock %p SHARED %08lX\n",
2084 &pDevExt->Specific.RDR.VolumeTreeLock,
2085 PsGetCurrentThread()));
2088 // Starve any exclusive waiters on this paticular call
2091 AFSAcquireSharedStarveExclusive( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2094 // Locate the volume node
2097 ullIndex = AFSCreateHighIndex( &InvalidateCB->FileID);
2099 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2101 (AFSBTreeEntry **)&pVolumeCB);
2103 if( pVolumeCB != NULL)
2106 lCount = AFSVolumeIncrement( pVolumeCB,
2107 AFS_VOLUME_REFERENCE_INVALIDATE);
2109 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2110 AFS_TRACE_LEVEL_VERBOSE,
2111 "AFSInvalidateCache Increment count on volume %p Cnt %d\n",
2116 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2118 if( !NT_SUCCESS( ntStatus) ||
2122 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2123 AFS_TRACE_LEVEL_WARNING,
2124 "AFSInvalidateCache Invalidation FAILURE Unable to locate volume node FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2125 InvalidateCB->FileID.Cell,
2126 InvalidateCB->FileID.Volume,
2127 InvalidateCB->FileID.Vnode,
2128 InvalidateCB->FileID.Unique,
2131 try_return( ntStatus = STATUS_SUCCESS);
2135 // If this is a whole volume invalidation then go do it now
2138 if( InvalidateCB->WholeVolume)
2141 ntStatus = AFSInvalidateVolume( pVolumeCB,
2142 InvalidateCB->Reason);
2144 try_return( ntStatus);
2147 AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
2150 if ( AFSIsVolumeFID( &InvalidateCB->FileID))
2153 pObjectInfo = &pVolumeCB->ObjectInformation;
2158 ullIndex = AFSCreateLowIndex( &InvalidateCB->FileID);
2160 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2162 (AFSBTreeEntry **)&pObjectInfo);
2165 if( pObjectInfo != NULL)
2169 // Reference the node so it won't be torn down
2172 lCount = AFSObjectInfoIncrement( pObjectInfo,
2173 AFS_OBJECT_REFERENCE_INVALIDATION);
2175 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2176 AFS_TRACE_LEVEL_VERBOSE,
2177 "AFSInvalidateCache Increment count on object %p Cnt %d\n",
2182 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2184 if( !NT_SUCCESS( ntStatus) ||
2185 pObjectInfo == NULL)
2188 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2189 AFS_TRACE_LEVEL_VERBOSE,
2190 "AFSInvalidateCache Invalidation FAILURE Unable to locate object FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2191 InvalidateCB->FileID.Cell,
2192 InvalidateCB->FileID.Volume,
2193 InvalidateCB->FileID.Vnode,
2194 InvalidateCB->FileID.Unique,
2197 try_return( ntStatus = STATUS_SUCCESS);
2200 AFSInvalidateObject( &pObjectInfo,
2201 InvalidateCB->Reason);
2205 if( pObjectInfo != NULL)
2208 lCount = AFSObjectInfoDecrement( pObjectInfo,
2209 AFS_OBJECT_REFERENCE_INVALIDATION);
2211 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2212 AFS_TRACE_LEVEL_VERBOSE,
2213 "AFSInvalidateCache Decrement count on object %p Cnt %d\n",
2218 if ( pVolumeCB != NULL)
2221 lCount = AFSVolumeDecrement( pVolumeCB,
2222 AFS_VOLUME_REFERENCE_INVALIDATE);
2224 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2225 AFS_TRACE_LEVEL_VERBOSE,
2226 "AFSInvalidateCache Decrement count on volume %p Cnt %d\n",
2236 AFSIsChildOfParent( IN AFSFcb *Dcb,
2240 BOOLEAN bIsChild = FALSE;
2241 AFSFcb *pCurrentFcb = Fcb;
2242 AFSObjectInfoCB * pParentObjectInfo = NULL;
2244 while( pCurrentFcb != NULL)
2247 if( BooleanFlagOn( pCurrentFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
2248 AFSIsEqualFID( &pCurrentFcb->ObjectInformation->ParentFileId, &Dcb->ObjectInformation->FileId))
2256 pParentObjectInfo = AFSFindObjectInfo( pCurrentFcb->ObjectInformation->VolumeCB,
2257 &pCurrentFcb->ObjectInformation->ParentFileId,
2260 if ( pParentObjectInfo != NULL)
2263 pCurrentFcb = pParentObjectInfo->Fcb;
2265 AFSReleaseObjectInfo( &pParentObjectInfo);
2279 AFSCreateHighIndex( IN AFSFileID *FileID)
2282 ULONGLONG ullIndex = 0;
2284 ullIndex = (((ULONGLONG)FileID->Cell << 32) | FileID->Volume);
2291 AFSCreateLowIndex( IN AFSFileID *FileID)
2294 ULONGLONG ullIndex = 0;
2296 ullIndex = (((ULONGLONG)FileID->Vnode << 32) | FileID->Unique);
2302 AFSCheckAccess( IN ACCESS_MASK DesiredAccess,
2303 IN ACCESS_MASK GrantedAccess,
2304 IN BOOLEAN DirectoryEntry)
2307 BOOLEAN bAccessGranted = TRUE;
2310 // Check if we are asking for read/write and granted only read only
2311 // NOTE: There will be more checks here
2314 if( !AFSCheckForReadOnlyAccess( DesiredAccess,
2316 AFSCheckForReadOnlyAccess( GrantedAccess,
2320 bAccessGranted = FALSE;
2323 return bAccessGranted;
2327 AFSGetDriverStatus( IN AFSDriverStatusRespCB *DriverStatus)
2330 NTSTATUS ntStatus = STATUS_SUCCESS;
2331 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2337 DriverStatus->Status = AFS_DRIVER_STATUS_READY;
2339 if( AFSGlobalRoot == NULL)
2346 DriverStatus->Status = AFS_DRIVER_STATUS_NOT_READY;
2349 if( pControlDevExt->Specific.Control.CommServiceCB.IrpPoolControlFlag != POOL_ACTIVE)
2356 DriverStatus->Status = AFS_DRIVER_STATUS_NO_SERVICE;
2363 AFSSubstituteSysName( IN UNICODE_STRING *ComponentName,
2364 IN UNICODE_STRING *SubstituteName,
2365 IN ULONG StringIndex)
2368 NTSTATUS ntStatus = STATUS_SUCCESS;
2369 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2370 AFSSysNameCB *pSysName = NULL;
2371 ERESOURCE *pSysNameLock = NULL;
2374 UNICODE_STRING uniSysName;
2381 if( IoIs32bitProcess( NULL))
2384 pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2386 pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2391 pSysNameLock = &pControlDevExt->Specific.Control.SysName64ListLock;
2393 pSysName = pControlDevExt->Specific.Control.SysName64ListHead;
2397 pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2399 pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2403 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2404 AFS_TRACE_LEVEL_VERBOSE,
2405 "AFSSubstituteSysName Acquiring SysName lock %p SHARED %08lX\n",
2407 PsGetCurrentThread()));
2409 AFSAcquireShared( pSysNameLock,
2413 // Find where we are in the list
2416 while( pSysName != NULL &&
2417 ulIndex < StringIndex)
2420 pSysName = pSysName->fLink;
2425 if( pSysName == NULL)
2428 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2429 AFS_TRACE_LEVEL_VERBOSE_2,
2430 "AFSSubstituteSysName No sysname %wZ Status %08lX\n",
2432 STATUS_OBJECT_NAME_NOT_FOUND));
2434 try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
2437 RtlInitUnicodeString( &uniSysName,
2440 // If it is a full component of @SYS then just substitue the
2444 if( RtlCompareUnicodeString( &uniSysName,
2449 SubstituteName->Length = pSysName->SysName.Length;
2450 SubstituteName->MaximumLength = SubstituteName->Length;
2452 SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2453 SubstituteName->Length,
2454 AFS_SUBST_BUFFER_TAG);
2456 if( SubstituteName->Buffer == NULL)
2459 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2462 RtlCopyMemory( SubstituteName->Buffer,
2463 pSysName->SysName.Buffer,
2464 pSysName->SysName.Length);
2471 while( ComponentName->Buffer[ usIndex] != L'@')
2477 SubstituteName->Length = (usIndex * sizeof( WCHAR)) + pSysName->SysName.Length;
2478 SubstituteName->MaximumLength = SubstituteName->Length;
2480 SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2481 SubstituteName->Length,
2482 AFS_SUBST_BUFFER_TAG);
2484 if( SubstituteName->Buffer == NULL)
2487 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2490 RtlCopyMemory( SubstituteName->Buffer,
2491 ComponentName->Buffer,
2492 usIndex * sizeof( WCHAR));
2494 RtlCopyMemory( &SubstituteName->Buffer[ usIndex],
2495 pSysName->SysName.Buffer,
2496 pSysName->SysName.Length);
2501 AFSReleaseResource( pSysNameLock);
2508 AFSSubstituteNameInPath( IN OUT UNICODE_STRING *FullPathName,
2509 IN OUT UNICODE_STRING *ComponentName,
2510 IN UNICODE_STRING *SubstituteName,
2511 IN OUT UNICODE_STRING *RemainingPath,
2512 IN BOOLEAN FreePathName)
2515 NTSTATUS ntStatus = STATUS_SUCCESS;
2516 UNICODE_STRING uniPathName;
2517 USHORT usPrefixNameLen = 0;
2518 SHORT sNameLenDelta = 0;
2524 // If the passed in name can handle the additional length
2525 // then just moves things around
2528 sNameLenDelta = SubstituteName->Length - ComponentName->Length;
2530 usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2532 if( FullPathName->MaximumLength > FullPathName->Length + sNameLenDelta)
2535 if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2538 RtlMoveMemory( &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + SubstituteName->Length)/sizeof( WCHAR))],
2539 &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + ComponentName->Length)/sizeof( WCHAR))],
2540 FullPathName->Length - usPrefixNameLen*sizeof( WCHAR) - ComponentName->Length);
2543 RtlCopyMemory( &FullPathName->Buffer[ usPrefixNameLen],
2544 SubstituteName->Buffer,
2545 SubstituteName->Length);
2547 FullPathName->Length += sNameLenDelta;
2549 ComponentName->Length += sNameLenDelta;
2551 ComponentName->MaximumLength = ComponentName->Length;
2553 if ( RemainingPath->Buffer)
2556 RemainingPath->Buffer += sNameLenDelta/sizeof( WCHAR);
2559 try_return( ntStatus);
2563 // Need to re-allocate the buffer
2566 uniPathName.Length = FullPathName->Length -
2567 ComponentName->Length +
2568 SubstituteName->Length;
2570 uniPathName.MaximumLength = FullPathName->MaximumLength + PAGE_SIZE;
2572 uniPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2573 uniPathName.MaximumLength,
2574 AFS_NAME_BUFFER_FOUR_TAG);
2576 if( uniPathName.Buffer == NULL)
2579 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2582 usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2584 usPrefixNameLen *= sizeof( WCHAR);
2586 RtlZeroMemory( uniPathName.Buffer,
2587 uniPathName.MaximumLength);
2589 RtlCopyMemory( uniPathName.Buffer,
2590 FullPathName->Buffer,
2593 RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen/sizeof( WCHAR))],
2594 SubstituteName->Buffer,
2595 SubstituteName->Length);
2597 if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2600 RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen + SubstituteName->Length)/sizeof( WCHAR)],
2601 &FullPathName->Buffer[ (usPrefixNameLen + ComponentName->Length)/sizeof( WCHAR)],
2602 FullPathName->Length - usPrefixNameLen - ComponentName->Length);
2605 ComponentName->Buffer = uniPathName.Buffer + (ComponentName->Buffer - FullPathName->Buffer);
2607 ComponentName->Length += sNameLenDelta;
2609 ComponentName->MaximumLength = ComponentName->Length;
2611 if ( RemainingPath->Buffer)
2614 RemainingPath->Buffer = uniPathName.Buffer
2615 + (RemainingPath->Buffer - FullPathName->Buffer)
2616 + sNameLenDelta/sizeof( WCHAR);
2621 AFSExFreePoolWithTag( FullPathName->Buffer, 0);
2624 *FullPathName = uniPathName;
2635 AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
2639 NTSTATUS ntStatus = STATUS_SUCCESS;
2640 AFSObjectInfoCB *pCurrentObject = NULL;
2641 AFSObjectInfoCB *pNextObject = NULL;
2647 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2648 AFS_TRACE_LEVEL_VERBOSE,
2649 "AFSInvalidateVolume Invalidate volume fid %08lX-%08lX-%08lX-%08lX Reason %08lX\n",
2650 VolumeCB->ObjectInformation.FileId.Cell,
2651 VolumeCB->ObjectInformation.FileId.Volume,
2652 VolumeCB->ObjectInformation.FileId.Vnode,
2653 VolumeCB->ObjectInformation.FileId.Unique,
2657 // Depending on the reason for invalidation then perform work on the node
2663 case AFS_INVALIDATE_DELETED:
2667 // Mark this volume as invalid
2670 SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
2672 SetFlag( VolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE);
2678 AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2682 // Invalidate the volume root directory
2685 pCurrentObject = &VolumeCB->ObjectInformation;
2687 if ( pCurrentObject )
2690 lCount = AFSObjectInfoIncrement( pCurrentObject,
2691 AFS_OBJECT_REFERENCE_INVALIDATION);
2693 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2694 AFS_TRACE_LEVEL_VERBOSE,
2695 "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2699 AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2701 AFSInvalidateObject( &pCurrentObject,
2704 AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2707 if ( pCurrentObject)
2710 lCount = AFSObjectInfoDecrement( pCurrentObject,
2711 AFS_OBJECT_REFERENCE_INVALIDATION);
2713 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2714 AFS_TRACE_LEVEL_VERBOSE,
2715 "AFSInvalidateVolumeObjects Decrement count on object %p Cnt %d\n",
2722 // Apply invalidation to all other volume objects
2725 pCurrentObject = VolumeCB->ObjectInfoListHead;
2727 if ( pCurrentObject)
2731 // Reference the node so it won't be torn down
2734 lCount = AFSObjectInfoIncrement( pCurrentObject,
2735 AFS_OBJECT_REFERENCE_INVALIDATION);
2737 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2738 AFS_TRACE_LEVEL_VERBOSE,
2739 "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2744 while( pCurrentObject != NULL)
2747 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2753 // Reference the node so it won't be torn down
2756 lCount = AFSObjectInfoIncrement( pNextObject,
2757 AFS_OBJECT_REFERENCE_INVALIDATION);
2759 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2760 AFS_TRACE_LEVEL_VERBOSE,
2761 "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2766 AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2768 AFSInvalidateObject( &pCurrentObject,
2771 AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2774 if ( pCurrentObject )
2777 lCount = AFSObjectInfoDecrement( pCurrentObject,
2778 AFS_OBJECT_REFERENCE_INVALIDATION);
2780 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2781 AFS_TRACE_LEVEL_VERBOSE,
2782 "AFSInvalidateVolumeObjects Decrement count on object %p Cnt %d\n",
2787 pCurrentObject = pNextObject;
2790 AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2797 AFSInvalidateAllVolumes( VOID)
2799 AFSVolumeCB *pVolumeCB = NULL;
2800 AFSVolumeCB *pNextVolumeCB = NULL;
2801 AFSDeviceExt *pRDRDeviceExt = NULL;
2804 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2806 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2807 AFS_TRACE_LEVEL_VERBOSE,
2808 "AFSInvalidateAllVolumes Acquiring RDR VolumeListLock lock %p SHARED %08lX\n",
2809 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2810 PsGetCurrentThread()));
2812 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2815 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
2820 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2821 AFS_TRACE_LEVEL_VERBOSE,
2822 "AFSInvalidateAllVolumes Acquiring VolumeRoot ObjectInfoTree lock %p SHARED %08lX\n",
2823 pVolumeCB->ObjectInfoTree.TreeLock,
2824 PsGetCurrentThread()));
2826 lCount = AFSVolumeIncrement( pVolumeCB,
2827 AFS_VOLUME_REFERENCE_INVALIDATE);
2829 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2830 AFS_TRACE_LEVEL_VERBOSE,
2831 "AFSInvalidateAllVolumes Increment count on volume %p Cnt %d\n",
2836 while( pVolumeCB != NULL)
2839 pNextVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2844 lCount = AFSVolumeIncrement( pNextVolumeCB,
2845 AFS_VOLUME_REFERENCE_INVALIDATE);
2847 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2848 AFS_TRACE_LEVEL_VERBOSE,
2849 "AFSInvalidateAllVolumes Increment count on volume %p Cnt %d\n",
2854 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2856 // do I need to hold the volume lock here?
2858 AFSInvalidateVolume( pVolumeCB, AFS_INVALIDATE_EXPIRED);
2860 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2863 lCount = AFSVolumeDecrement( pVolumeCB,
2864 AFS_VOLUME_REFERENCE_INVALIDATE);
2866 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2867 AFS_TRACE_LEVEL_VERBOSE,
2868 "AFSInvalidateAllVolumes Decrement count on volume %p Cnt %d\n",
2872 pVolumeCB = pNextVolumeCB;
2875 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2879 AFSVerifyEntry( IN GUID *AuthGroup,
2880 IN AFSDirectoryCB *DirEntry)
2883 NTSTATUS ntStatus = STATUS_SUCCESS;
2884 AFSDirEnumEntry *pDirEnumEntry = NULL;
2885 AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
2886 IO_STATUS_BLOCK stIoStatus;
2891 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2892 AFS_TRACE_LEVEL_VERBOSE_2,
2893 "AFSVerifyEntry Verifying entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2894 &DirEntry->NameInformation.FileName,
2895 pObjectInfo->FileId.Cell,
2896 pObjectInfo->FileId.Volume,
2897 pObjectInfo->FileId.Vnode,
2898 pObjectInfo->FileId.Unique));
2900 ntStatus = AFSEvaluateTargetByID( pObjectInfo,
2905 if( !NT_SUCCESS( ntStatus))
2908 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2909 AFS_TRACE_LEVEL_ERROR,
2910 "AFSVerifyEntry Evaluate Target failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2911 &DirEntry->NameInformation.FileName,
2912 pObjectInfo->FileId.Cell,
2913 pObjectInfo->FileId.Volume,
2914 pObjectInfo->FileId.Vnode,
2915 pObjectInfo->FileId.Unique,
2918 try_return( ntStatus);
2922 // Check the data version of the file
2925 if( pObjectInfo->DataVersion.QuadPart == pDirEnumEntry->DataVersion.QuadPart)
2927 if ( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2930 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2931 AFS_TRACE_LEVEL_VERBOSE,
2932 "AFSVerifyEntry No DV change %I64X for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2933 pObjectInfo->DataVersion.QuadPart,
2934 &DirEntry->NameInformation.FileName,
2935 pObjectInfo->FileId.Cell,
2936 pObjectInfo->FileId.Volume,
2937 pObjectInfo->FileId.Vnode,
2938 pObjectInfo->FileId.Unique));
2941 // We are ok, just get out
2944 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2946 try_return( ntStatus = STATUS_SUCCESS);
2951 // New data version so we will need to process the node based on the type
2954 switch( pDirEnumEntry->FileType)
2957 case AFS_FILE_TYPE_MOUNTPOINT:
2961 // For a mount point we need to ensure the target is the same
2964 if( !AFSIsEqualFID( &pObjectInfo->TargetFileId,
2965 &pDirEnumEntry->TargetFileId))
2971 // Update the metadata for the entry
2974 ntStatus = AFSUpdateMetaData( DirEntry,
2977 if( NT_SUCCESS( ntStatus))
2980 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2986 case AFS_FILE_TYPE_SYMLINK:
2990 // Update the metadata for the entry
2993 ntStatus = AFSUpdateMetaData( DirEntry,
2996 if( NT_SUCCESS( ntStatus))
2999 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3005 case AFS_FILE_TYPE_FILE:
3007 FILE_OBJECT * pCCFileObject = NULL;
3008 BOOLEAN bPurgeExtents = FALSE;
3010 if ( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
3013 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3014 AFS_TRACE_LEVEL_VERBOSE,
3015 "AFSVerifyEntry DV Change %wZ FID %08lX-%08lX-%08lX-%08lX (%08lX != %08lX)\n",
3016 &DirEntry->NameInformation.FileName,
3017 pObjectInfo->FileId.Cell,
3018 pObjectInfo->FileId.Volume,
3019 pObjectInfo->FileId.Vnode,
3020 pObjectInfo->FileId.Unique,
3021 pObjectInfo->DataVersion.LowPart,
3022 pDirEnumEntry->DataVersion.LowPart));
3024 bPurgeExtents = TRUE;
3027 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
3030 bPurgeExtents = TRUE;
3032 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3033 AFS_TRACE_LEVEL_VERBOSE,
3034 "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3035 &DirEntry->NameInformation.FileName,
3036 pObjectInfo->FileId.Cell,
3037 pObjectInfo->FileId.Volume,
3038 pObjectInfo->FileId.Vnode,
3039 pObjectInfo->FileId.Unique));
3041 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
3044 if( pObjectInfo->Fcb != NULL)
3047 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3048 AFS_TRACE_LEVEL_VERBOSE,
3049 "AFSVerifyEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3050 &DirEntry->NameInformation.FileName,
3051 pObjectInfo->FileId.Cell,
3052 pObjectInfo->FileId.Volume,
3053 pObjectInfo->FileId.Vnode,
3054 pObjectInfo->FileId.Unique));
3056 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3062 CcFlushCache( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
3067 if( !NT_SUCCESS( stIoStatus.Status))
3070 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
3071 AFS_TRACE_LEVEL_ERROR,
3072 "AFSVerifyEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
3073 &DirEntry->NameInformation.FileName,
3074 pObjectInfo->FileId.Cell,
3075 pObjectInfo->FileId.Volume,
3076 pObjectInfo->FileId.Vnode,
3077 pObjectInfo->FileId.Unique,
3079 stIoStatus.Information));
3081 ntStatus = stIoStatus.Status;
3084 if ( bPurgeExtents &&
3085 pObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
3088 if ( !CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
3094 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
3095 AFS_TRACE_LEVEL_WARNING,
3096 "AFSVerifyEntry CcPurgeCacheSection failure %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3097 &DirEntry->NameInformation.FileName,
3098 pObjectInfo->FileId.Cell,
3099 pObjectInfo->FileId.Volume,
3100 pObjectInfo->FileId.Vnode,
3101 pObjectInfo->FileId.Unique));
3103 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
3107 __except( EXCEPTION_EXECUTE_HANDLER)
3109 ntStatus = GetExceptionCode();
3113 "EXCEPTION - AFSVerifyEntry CcFlushCache or CcPurgeCacheSection %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
3114 &DirEntry->NameInformation.FileName,
3115 pObjectInfo->FileId.Cell,
3116 pObjectInfo->FileId.Volume,
3117 pObjectInfo->FileId.Vnode,
3118 pObjectInfo->FileId.Unique,
3121 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
3124 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
3128 AFSFlushExtents( pObjectInfo->Fcb,
3133 // Reacquire the Fcb to purge the cache
3136 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3137 AFS_TRACE_LEVEL_VERBOSE,
3138 "AFSVerifyEntry Acquiring Fcb lock %p EXCL %08lX\n",
3139 &pObjectInfo->Fcb->NPFcb->Resource,
3140 PsGetCurrentThread()));
3142 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
3146 // Update the metadata for the entry
3149 ntStatus = AFSUpdateMetaData( DirEntry,
3152 if( !NT_SUCCESS( ntStatus))
3155 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3156 AFS_TRACE_LEVEL_ERROR,
3157 "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
3158 &DirEntry->NameInformation.FileName,
3159 pObjectInfo->FileId.Cell,
3160 pObjectInfo->FileId.Volume,
3161 pObjectInfo->FileId.Vnode,
3162 pObjectInfo->FileId.Unique,
3169 // Update file sizes
3172 pObjectInfo->Fcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart;
3173 pObjectInfo->Fcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart;
3174 pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
3176 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3177 AFS_TRACE_LEVEL_VERBOSE,
3178 "AFSVerifyEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
3179 &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3180 PsGetCurrentThread()));
3182 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3185 pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
3187 if ( pCCFileObject != NULL)
3189 CcSetFileSizes( pCCFileObject,
3190 (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
3193 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3194 AFS_TRACE_LEVEL_VERBOSE,
3195 "AFSVerifyEntry Releasing Fcb SectionObject lock %p EXCL %08lX\n",
3196 &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3197 PsGetCurrentThread()));
3199 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
3201 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
3207 // Update the metadata for the entry
3210 ntStatus = AFSUpdateMetaData( DirEntry,
3213 if( !NT_SUCCESS( ntStatus))
3216 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3217 AFS_TRACE_LEVEL_ERROR,
3218 "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
3219 &DirEntry->NameInformation.FileName,
3220 pObjectInfo->FileId.Cell,
3221 pObjectInfo->FileId.Volume,
3222 pObjectInfo->FileId.Vnode,
3223 pObjectInfo->FileId.Unique,
3229 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3230 AFS_TRACE_LEVEL_WARNING,
3231 "AFSVerifyEntry Fcb NULL %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3232 &DirEntry->NameInformation.FileName,
3233 pObjectInfo->FileId.Cell,
3234 pObjectInfo->FileId.Volume,
3235 pObjectInfo->FileId.Vnode,
3236 pObjectInfo->FileId.Unique));
3239 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3244 case AFS_FILE_TYPE_DIRECTORY:
3248 // For a directory or root entry flush the content of
3249 // the directory enumeration.
3252 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3255 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3256 AFS_TRACE_LEVEL_VERBOSE_2,
3257 "AFSVerifyEntry Validating directory content for entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3258 &DirEntry->NameInformation.FileName,
3259 pObjectInfo->FileId.Cell,
3260 pObjectInfo->FileId.Volume,
3261 pObjectInfo->FileId.Vnode,
3262 pObjectInfo->FileId.Unique));
3264 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3267 ntStatus = AFSValidateDirectoryCache( pObjectInfo,
3270 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3272 if ( !NT_SUCCESS( ntStatus))
3275 try_return( ntStatus);
3280 // Update the metadata for the entry
3283 ntStatus = AFSUpdateMetaData( DirEntry,
3286 if( NT_SUCCESS( ntStatus))
3289 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3295 case AFS_FILE_TYPE_DFSLINK:
3298 UNICODE_STRING uniTargetName;
3301 // For a DFS link need to check the target name has not changed
3304 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
3306 uniTargetName.MaximumLength = uniTargetName.Length;
3308 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
3310 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3313 if( DirEntry->NameInformation.TargetName.Length == 0 ||
3314 RtlCompareUnicodeString( &uniTargetName,
3315 &DirEntry->NameInformation.TargetName,
3320 // Update the target name
3323 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3325 uniTargetName.Buffer,
3326 uniTargetName.Length);
3328 if( !NT_SUCCESS( ntStatus))
3331 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3337 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3340 // Update the metadata for the entry
3343 ntStatus = AFSUpdateMetaData( DirEntry,
3346 if( NT_SUCCESS( ntStatus))
3349 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3357 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3358 AFS_TRACE_LEVEL_WARNING,
3359 "AFSVerifyEntry Attempt to verify node of type %d %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3360 pObjectInfo->FileType,
3361 &DirEntry->NameInformation.FileName,
3362 pObjectInfo->FileId.Cell,
3363 pObjectInfo->FileId.Volume,
3364 pObjectInfo->FileId.Vnode,
3365 pObjectInfo->FileId.Unique));
3372 if( pDirEnumEntry != NULL)
3375 AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_2_TAG);
3383 AFSSetVolumeState( IN AFSVolumeStatusCB *VolumeStatus)
3386 NTSTATUS ntStatus = STATUS_SUCCESS;
3387 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
3388 ULONGLONG ullIndex = 0;
3389 AFSVolumeCB *pVolumeCB = NULL;
3395 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3396 AFS_TRACE_LEVEL_VERBOSE,
3397 "AFSSetVolumeState Marking volume state %d Volume Cell %08lX Volume %08lX\n",
3398 VolumeStatus->Online,
3399 VolumeStatus->FileID.Cell,
3400 VolumeStatus->FileID.Volume));
3403 // Need to locate the Fcb for the directory to purge
3406 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3407 AFS_TRACE_LEVEL_VERBOSE,
3408 "AFSSetVolumeState Acquiring RDR VolumeTreeLock lock %p SHARED %08lX\n",
3409 &pDevExt->Specific.RDR.VolumeTreeLock,
3410 PsGetCurrentThread()));
3412 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
3415 // Locate the volume node
3418 ullIndex = AFSCreateHighIndex( &VolumeStatus->FileID);
3420 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
3422 (AFSBTreeEntry **)&pVolumeCB);
3424 if( pVolumeCB != NULL)
3427 lCount = AFSVolumeIncrement( pVolumeCB,
3428 AFS_VOLUME_REFERENCE_INVALIDATE);
3430 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3431 AFS_TRACE_LEVEL_VERBOSE,
3432 "AFSSetVolumeState Increment count on volume %p Cnt %d\n",
3436 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3439 // Set the volume state accordingly
3442 if( VolumeStatus->Online)
3445 InterlockedAnd( (LONG *)&(pVolumeCB->Flags), ~AFS_VOLUME_FLAGS_OFFLINE);
3450 InterlockedOr( (LONG *)&(pVolumeCB->Flags), AFS_VOLUME_FLAGS_OFFLINE);
3459 AFSSetNetworkState( IN AFSNetworkStatusCB *NetworkStatus)
3462 NTSTATUS ntStatus = STATUS_SUCCESS;
3467 if( AFSGlobalRoot == NULL)
3470 try_return( ntStatus);
3473 AFSAcquireExcl( AFSGlobalRoot->VolumeLock,
3477 // Set the network state according to the information
3480 if( NetworkStatus->Online)
3483 ClearFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3488 SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3491 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3502 AFSValidateDirectoryCache( IN AFSObjectInfoCB *ObjectInfo,
3506 NTSTATUS ntStatus = STATUS_SUCCESS;
3507 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3508 BOOLEAN bAcquiredLock = FALSE;
3509 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
3514 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3515 AFS_TRACE_LEVEL_VERBOSE,
3516 "AFSValidateDirectoryCache Validating content for FID %08lX-%08lX-%08lX-%08lX\n",
3517 ObjectInfo->FileId.Cell,
3518 ObjectInfo->FileId.Volume,
3519 ObjectInfo->FileId.Vnode,
3520 ObjectInfo->FileId.Unique));
3522 if( !ExIsResourceAcquiredLite( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock))
3525 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3526 AFS_TRACE_LEVEL_VERBOSE,
3527 "AFSValidateDirectoryCache Acquiring DirectoryNodeHdr.TreeLock lock %p EXCL %08lX\n",
3528 ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3529 PsGetCurrentThread()));
3531 AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3534 bAcquiredLock = TRUE;
3538 // Check for inconsistency between DirectoryNodeList and DirectoryNodeCount
3541 if ( ObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL &&
3542 ObjectInfo->Specific.Directory.DirectoryNodeCount > 0)
3545 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3546 AFS_TRACE_LEVEL_ERROR,
3547 "AFSValidateDirectoryCache Empty Node List but Non-Zero Node Count %d for dir FID %08lX-%08lX-%08lX-%08lX\n",
3548 ObjectInfo->Specific.Directory.DirectoryNodeCount,
3549 ObjectInfo->FileId.Cell,
3550 ObjectInfo->FileId.Volume,
3551 ObjectInfo->FileId.Vnode,
3552 ObjectInfo->FileId.Unique));
3556 // Reset the directory list information by clearing all valid entries
3559 pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3561 while( pCurrentDirEntry != NULL)
3564 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3566 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
3570 // If this entry has been deleted then process it here
3573 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
3574 pCurrentDirEntry->DirOpenReferenceCount <= 0 &&
3575 pCurrentDirEntry->NameArrayReferenceCount <= 0)
3578 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3579 AFS_TRACE_LEVEL_VERBOSE,
3580 "AFSValidateDirectoryCache Deleting dir entry %p name %wZ\n",
3582 &pCurrentDirEntry->NameInformation.FileName));
3584 AFSDeleteDirEntry( ObjectInfo,
3590 ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID);
3592 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3593 AFS_TRACE_LEVEL_VERBOSE,
3594 "AFSValidateDirectoryCache Clear VALID flag on DE %p Reference count %d\n",
3596 pCurrentDirEntry->DirOpenReferenceCount));
3599 // We pull the short name from the parent tree since it could change below
3602 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
3605 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3606 AFS_TRACE_LEVEL_VERBOSE,
3607 "AFSValidateDirectoryCache Removing DE %p (%08lX) from shortname tree for %wZ\n",
3609 pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3610 &pCurrentDirEntry->NameInformation.FileName));
3612 AFSRemoveShortNameDirEntry( &ObjectInfo->Specific.Directory.ShortNameTree,
3615 ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3620 pCurrentDirEntry = pNextDirEntry;
3624 // Reget the directory contents
3627 ntStatus = AFSVerifyDirectoryContent( ObjectInfo,
3630 if ( !NT_SUCCESS( ntStatus))
3632 try_return( ntStatus);
3636 // Now start again and tear down any entries not valid
3639 pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3641 while( pCurrentDirEntry != NULL)
3644 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3646 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID))
3649 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3650 !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME) &&
3651 pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex > 0)
3654 if( ObjectInfo->Specific.Directory.ShortNameTree == NULL)
3657 ObjectInfo->Specific.Directory.ShortNameTree = pCurrentDirEntry;
3659 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3660 AFS_TRACE_LEVEL_VERBOSE,
3661 "AFSValidateDirectoryCache Insert DE %p to head of shortname tree for %wZ\n",
3663 &pCurrentDirEntry->NameInformation.FileName));
3665 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3670 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfo->Specific.Directory.ShortNameTree,
3673 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3674 AFS_TRACE_LEVEL_VERBOSE,
3675 "AFSValidateDirectoryCache Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
3677 pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3678 &pCurrentDirEntry->NameInformation.FileName));
3682 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3684 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3685 AFS_TRACE_LEVEL_VERBOSE,
3686 "AFSValidateDirectoryCache Insert DE %p to shortname tree for %wZ\n",
3688 &pCurrentDirEntry->NameInformation.FileName));
3693 pCurrentDirEntry = pNextDirEntry;
3698 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3699 AFS_TRACE_LEVEL_VERBOSE,
3700 "AFSValidateDirectoryCache Processing INVALID DE %p Reference count %d\n",
3702 pCurrentDirEntry->DirOpenReferenceCount));
3704 if( pCurrentDirEntry->DirOpenReferenceCount <= 0 &&
3705 pCurrentDirEntry->NameArrayReferenceCount <= 0)
3708 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3709 AFS_TRACE_LEVEL_VERBOSE,
3710 "AFSValidateDirectoryCache Deleting dir entry %wZ from parent FID %08lX-%08lX-%08lX-%08lX\n",
3711 &pCurrentDirEntry->NameInformation.FileName,
3712 ObjectInfo->FileId.Cell,
3713 ObjectInfo->FileId.Volume,
3714 ObjectInfo->FileId.Vnode,
3715 ObjectInfo->FileId.Unique));
3717 AFSDeleteDirEntry( ObjectInfo,
3723 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3724 AFS_TRACE_LEVEL_VERBOSE,
3725 "AFSValidateDirectoryCache Setting dir entry %p Name %wZ DELETED in parent FID %08lX-%08lX-%08lX-%08lX\n",
3727 &pCurrentDirEntry->NameInformation.FileName,
3728 ObjectInfo->FileId.Cell,
3729 ObjectInfo->FileId.Volume,
3730 ObjectInfo->FileId.Vnode,
3731 ObjectInfo->FileId.Unique));
3733 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
3735 AFSRemoveNameEntry( ObjectInfo,
3739 pCurrentDirEntry = pNextDirEntry;
3743 if( !AFSValidateDirList( ObjectInfo))
3746 AFSPrint("AFSValidateDirectoryCache Invalid count ...\n");
3755 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3763 AFSIsVolumeFID( IN AFSFileID *FileID)
3766 BOOLEAN bIsVolume = FALSE;
3768 if( FileID->Vnode == 1 &&
3769 FileID->Unique == 1)
3779 AFSIsFinalNode( IN AFSFcb *Fcb)
3782 BOOLEAN bIsFinalNode = FALSE;
3784 if( Fcb->Header.NodeTypeCode == AFS_ROOT_FCB ||
3785 Fcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB ||
3786 Fcb->Header.NodeTypeCode == AFS_FILE_FCB ||
3787 Fcb->Header.NodeTypeCode == AFS_DFS_LINK_FCB ||
3788 Fcb->Header.NodeTypeCode == AFS_INVALID_FCB )
3791 bIsFinalNode = TRUE;
3796 ASSERT( Fcb->Header.NodeTypeCode == AFS_MOUNT_POINT_FCB ||
3797 Fcb->Header.NodeTypeCode == AFS_SYMBOLIC_LINK_FCB);
3800 return bIsFinalNode;
3804 AFSUpdateMetaData( IN AFSDirectoryCB *DirEntry,
3805 IN AFSDirEnumEntry *DirEnumEntry)
3808 NTSTATUS ntStatus = STATUS_SUCCESS;
3809 UNICODE_STRING uniTargetName;
3810 AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
3815 pObjectInfo->TargetFileId = DirEnumEntry->TargetFileId;
3817 pObjectInfo->Expiration = DirEnumEntry->Expiration;
3819 pObjectInfo->DataVersion = DirEnumEntry->DataVersion;
3821 pObjectInfo->FileType = DirEnumEntry->FileType;
3823 pObjectInfo->CreationTime = DirEnumEntry->CreationTime;
3825 pObjectInfo->LastAccessTime = DirEnumEntry->LastAccessTime;
3827 pObjectInfo->LastWriteTime = DirEnumEntry->LastWriteTime;
3829 pObjectInfo->ChangeTime = DirEnumEntry->ChangeTime;
3831 pObjectInfo->EndOfFile = DirEnumEntry->EndOfFile;
3833 pObjectInfo->AllocationSize = DirEnumEntry->AllocationSize;
3835 pObjectInfo->FileAttributes = DirEnumEntry->FileAttributes;
3837 if( pObjectInfo->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
3838 pObjectInfo->FileType == AFS_FILE_TYPE_DFSLINK)
3841 pObjectInfo->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
3844 if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK)
3847 if ( pObjectInfo->FileAttributes == FILE_ATTRIBUTE_NORMAL)
3850 pObjectInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
3855 pObjectInfo->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
3859 pObjectInfo->EaSize = DirEnumEntry->EaSize;
3861 pObjectInfo->Links = DirEnumEntry->Links;
3863 if( DirEnumEntry->TargetNameLength > 0 &&
3864 ( DirEntry->NameInformation.TargetName.Length != DirEnumEntry->TargetNameLength ||
3865 DirEntry->ObjectInformation->DataVersion.QuadPart != DirEnumEntry->DataVersion.QuadPart))
3869 // Update the target name information if needed
3872 uniTargetName.Length = (USHORT)DirEnumEntry->TargetNameLength;
3874 uniTargetName.MaximumLength = uniTargetName.Length;
3876 uniTargetName.Buffer = (WCHAR *)((char *)DirEnumEntry + DirEnumEntry->TargetNameOffset);
3878 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3881 if( DirEntry->NameInformation.TargetName.Length == 0 ||
3882 RtlCompareUnicodeString( &uniTargetName,
3883 &DirEntry->NameInformation.TargetName,
3888 // Update the target name
3891 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3893 uniTargetName.Buffer,
3894 uniTargetName.Length);
3896 if( !NT_SUCCESS( ntStatus))
3899 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3901 try_return( ntStatus);
3905 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3907 else if( DirEntry->NameInformation.TargetName.Length > 0 &&
3908 DirEntry->ObjectInformation->DataVersion.QuadPart != DirEnumEntry->DataVersion.QuadPart)
3911 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3914 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER) &&
3915 DirEntry->NameInformation.TargetName.Buffer != NULL)
3917 AFSExFreePoolWithTag( DirEntry->NameInformation.TargetName.Buffer, AFS_NAME_BUFFER_FIVE_TAG);
3920 ClearFlag( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER);
3922 DirEntry->NameInformation.TargetName.Length = 0;
3923 DirEntry->NameInformation.TargetName.MaximumLength = 0;
3924 DirEntry->NameInformation.TargetName.Buffer = NULL;
3926 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3938 AFSValidateEntry( IN AFSDirectoryCB *DirEntry,
3940 IN BOOLEAN FastCall,
3941 IN BOOLEAN bSafeToPurge)
3944 NTSTATUS ntStatus = STATUS_SUCCESS;
3945 LARGE_INTEGER liSystemTime;
3946 AFSDirEnumEntry *pDirEnumEntry = NULL;
3947 AFSFcb *pCurrentFcb = NULL;
3948 BOOLEAN bReleaseFcb = FALSE;
3949 AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
3955 // If we have an Fcb hanging off the directory entry then be sure to acquire the locks in the
3959 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3960 AFS_TRACE_LEVEL_VERBOSE_2,
3961 "AFSValidateEntry Validating entry %wZ FID %08lX-%08lX-%08lX-%08lX FastCall %u\n",
3962 &DirEntry->NameInformation.FileName,
3963 pObjectInfo->FileId.Cell,
3964 pObjectInfo->FileId.Volume,
3965 pObjectInfo->FileId.Vnode,
3966 pObjectInfo->FileId.Unique,
3970 // If this is a fake node then bail since the service knows nothing about it
3973 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_FAKE))
3976 try_return( ntStatus);
3980 // This routine ensures that the current entry is valid by:
3982 // 1) Checking that the expiration time is non-zero and after where we
3986 KeQuerySystemTime( &liSystemTime);
3988 if( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) &&
3989 !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
3990 !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA) &&
3991 pObjectInfo->Expiration.QuadPart >= liSystemTime.QuadPart)
3994 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3995 AFS_TRACE_LEVEL_VERBOSE_2,
3996 "AFSValidateEntry Directory entry %wZ FID %08lX-%08lX-%08lX-%08lX VALID\n",
3997 &DirEntry->NameInformation.FileName,
3998 pObjectInfo->FileId.Cell,
3999 pObjectInfo->FileId.Volume,
4000 pObjectInfo->FileId.Vnode,
4001 pObjectInfo->FileId.Unique));
4003 try_return( ntStatus);
4007 // This node requires updating
4010 ntStatus = AFSEvaluateTargetByID( pObjectInfo,
4015 if( !NT_SUCCESS( ntStatus))
4018 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4019 AFS_TRACE_LEVEL_ERROR,
4020 "AFSValidateEntry Failed to evaluate entry FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4022 &DirEntry->NameInformation.FileName,
4023 pObjectInfo->FileId.Cell,
4024 pObjectInfo->FileId.Volume,
4025 pObjectInfo->FileId.Vnode,
4026 pObjectInfo->FileId.Unique,
4030 // Failed validation of node so return access-denied
4033 try_return( ntStatus);
4036 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4037 AFS_TRACE_LEVEL_VERBOSE,
4038 "AFSValidateEntry Validating entry FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX DV %I64X returned DV %I64X FT %d\n",
4040 &DirEntry->NameInformation.FileName,
4041 pObjectInfo->FileId.Cell,
4042 pObjectInfo->FileId.Volume,
4043 pObjectInfo->FileId.Vnode,
4044 pObjectInfo->FileId.Unique,
4045 pObjectInfo->DataVersion.QuadPart,
4046 pDirEnumEntry->DataVersion.QuadPart,
4047 pDirEnumEntry->FileType));
4051 // Based on the file type, process the node
4054 switch( pDirEnumEntry->FileType)
4057 case AFS_FILE_TYPE_MOUNTPOINT:
4061 // Update the metadata for the entry
4064 ntStatus = AFSUpdateMetaData( DirEntry,
4067 if( NT_SUCCESS( ntStatus))
4070 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
4076 case AFS_FILE_TYPE_SYMLINK:
4077 case AFS_FILE_TYPE_DFSLINK:
4081 // Update the metadata for the entry
4084 ntStatus = AFSUpdateMetaData( DirEntry,
4087 if( NT_SUCCESS( ntStatus))
4090 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
4096 case AFS_FILE_TYPE_FILE:
4099 BOOLEAN bPurgeExtents = FALSE;
4102 // For a file where the data version has become invalid we need to
4103 // fail any current extent requests and purge the cache for the file
4104 // Can't hold the Fcb resource while doing this
4107 if( pObjectInfo->Fcb != NULL &&
4108 (pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart ||
4109 BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA)))
4112 pCurrentFcb = pObjectInfo->Fcb;
4114 if( !ExIsResourceAcquiredLite( &pCurrentFcb->NPFcb->Resource))
4117 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4118 AFS_TRACE_LEVEL_VERBOSE,
4119 "AFSValidateEntry Acquiring Fcb lock %p EXCL %08lX\n",
4120 &pCurrentFcb->NPFcb->Resource,
4121 PsGetCurrentThread()));
4123 AFSAcquireExcl( &pCurrentFcb->NPFcb->Resource,
4129 if( pCurrentFcb != NULL)
4132 IO_STATUS_BLOCK stIoStatus;
4134 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4135 AFS_TRACE_LEVEL_VERBOSE_2,
4136 "AFSValidateEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4137 &DirEntry->NameInformation.FileName,
4138 pObjectInfo->FileId.Cell,
4139 pObjectInfo->FileId.Volume,
4140 pObjectInfo->FileId.Vnode,
4141 pObjectInfo->FileId.Unique));
4143 if ( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
4146 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4147 AFS_TRACE_LEVEL_VERBOSE,
4148 "AFSValidateEntry DV Change %wZ FID %08lX-%08lX-%08lX-%08lX (%08lX != %08lX)\n",
4149 &DirEntry->NameInformation.FileName,
4150 pObjectInfo->FileId.Cell,
4151 pObjectInfo->FileId.Volume,
4152 pObjectInfo->FileId.Vnode,
4153 pObjectInfo->FileId.Unique,
4154 pObjectInfo->DataVersion.LowPart,
4155 pDirEnumEntry->DataVersion.LowPart));
4157 bPurgeExtents = TRUE;
4163 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
4165 bPurgeExtents = TRUE;
4167 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4168 AFS_TRACE_LEVEL_VERBOSE,
4169 "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4170 &DirEntry->NameInformation.FileName,
4171 pObjectInfo->FileId.Cell,
4172 pObjectInfo->FileId.Volume,
4173 pObjectInfo->FileId.Vnode,
4174 pObjectInfo->FileId.Unique));
4176 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
4179 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4180 AFS_TRACE_LEVEL_VERBOSE,
4181 "AFSValidateEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
4182 &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
4183 PsGetCurrentThread()));
4185 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
4189 // Release Fcb->Resource to avoid Trend Micro deadlock
4192 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
4197 CcFlushCache( &pCurrentFcb->NPFcb->SectionObjectPointers,
4202 if( !NT_SUCCESS( stIoStatus.Status))
4205 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
4206 AFS_TRACE_LEVEL_ERROR,
4207 "AFSValidateEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
4208 &DirEntry->NameInformation.FileName,
4209 pObjectInfo->FileId.Cell,
4210 pObjectInfo->FileId.Volume,
4211 pObjectInfo->FileId.Vnode,
4212 pObjectInfo->FileId.Unique,
4214 stIoStatus.Information));
4216 ntStatus = stIoStatus.Status;
4219 if ( bPurgeExtents &&
4220 pObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
4223 if ( !CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
4229 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
4230 AFS_TRACE_LEVEL_WARNING,
4231 "AFSValidateEntry CcPurgeCacheSection failure %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4232 &DirEntry->NameInformation.FileName,
4233 pObjectInfo->FileId.Cell,
4234 pObjectInfo->FileId.Volume,
4235 pObjectInfo->FileId.Vnode,
4236 pObjectInfo->FileId.Unique));
4238 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
4242 __except( EXCEPTION_EXECUTE_HANDLER)
4244 ntStatus = GetExceptionCode();
4248 "EXCEPTION - AFSValidateEntry CcFlushCache or CcPurgeCacheSection %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
4249 &DirEntry->NameInformation.FileName,
4250 pObjectInfo->FileId.Cell,
4251 pObjectInfo->FileId.Volume,
4252 pObjectInfo->FileId.Vnode,
4253 pObjectInfo->FileId.Unique,
4256 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
4259 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4260 AFS_TRACE_LEVEL_VERBOSE,
4261 "AFSValidateEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
4262 &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
4263 PsGetCurrentThread()));
4265 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
4267 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
4276 SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
4281 AFSReleaseResource( &pCurrentFcb->NPFcb->Resource);
4283 bReleaseFcb = FALSE;
4285 if ( bPurgeExtents &&
4288 AFSFlushExtents( pCurrentFcb,
4295 // Update the metadata for the entry but only if it is safe to do so.
4296 // If it was determined that a data version change has occurred or
4297 // that a pending data verification was required, do not update the
4298 // ObjectInfo meta data or the FileObject size information. That
4299 // way it is consistent for the next time that the data is verified
4303 if ( !(bPurgeExtents && bSafeToPurge))
4306 ntStatus = AFSUpdateMetaData( DirEntry,
4309 if( !NT_SUCCESS( ntStatus))
4312 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4313 AFS_TRACE_LEVEL_ERROR,
4314 "AFSValidateEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
4315 &DirEntry->NameInformation.FileName,
4316 pObjectInfo->FileId.Cell,
4317 pObjectInfo->FileId.Volume,
4318 pObjectInfo->FileId.Vnode,
4319 pObjectInfo->FileId.Unique,
4325 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
4328 // Update file sizes
4331 if( pObjectInfo->Fcb != NULL)
4333 FILE_OBJECT *pCCFileObject;
4335 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4336 AFS_TRACE_LEVEL_VERBOSE,
4337 "AFSValidateEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
4338 &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
4339 PsGetCurrentThread()));
4341 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
4344 pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
4346 pObjectInfo->Fcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart;
4347 pObjectInfo->Fcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart;
4348 pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
4350 if ( pCCFileObject != NULL)
4352 CcSetFileSizes( pCCFileObject,
4353 (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
4356 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4357 AFS_TRACE_LEVEL_VERBOSE,
4358 "AFSValidateEntry Releasing Fcb SectionObject lock %p EXCL %08lX\n",
4359 &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
4360 PsGetCurrentThread()));
4362 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
4368 case AFS_FILE_TYPE_DIRECTORY:
4371 if( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
4375 // For a directory or root entry flush the content of
4376 // the directory enumeration.
4379 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4380 AFS_TRACE_LEVEL_VERBOSE,
4381 "AFSValidateEntry Acquiring DirectoryNodeHdr.TreeLock lock %p EXCL %08lX\n",
4382 pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
4383 PsGetCurrentThread()));
4385 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
4388 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4389 AFS_TRACE_LEVEL_VERBOSE_2,
4390 "AFSValidateEntry Validating directory content for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4391 &DirEntry->NameInformation.FileName,
4392 pObjectInfo->FileId.Cell,
4393 pObjectInfo->FileId.Volume,
4394 pObjectInfo->FileId.Vnode,
4395 pObjectInfo->FileId.Unique));
4397 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
4400 ntStatus = AFSValidateDirectoryCache( pObjectInfo,
4403 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
4406 if( !NT_SUCCESS( ntStatus))
4409 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4410 AFS_TRACE_LEVEL_ERROR,
4411 "AFSValidateEntry Failed to re-enumerate %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4412 &DirEntry->NameInformation.FileName,
4413 pObjectInfo->FileId.Cell,
4414 pObjectInfo->FileId.Volume,
4415 pObjectInfo->FileId.Vnode,
4416 pObjectInfo->FileId.Unique,
4424 // Update the metadata for the entry
4427 ntStatus = AFSUpdateMetaData( DirEntry,
4430 if( NT_SUCCESS( ntStatus))
4433 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
4441 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4442 AFS_TRACE_LEVEL_WARNING,
4443 "AFSValidateEntry Attempt to verify node of type %d FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4444 pObjectInfo->FileType,
4446 &DirEntry->NameInformation.FileName,
4447 pObjectInfo->FileId.Cell,
4448 pObjectInfo->FileId.Volume,
4449 pObjectInfo->FileId.Vnode,
4450 pObjectInfo->FileId.Unique));
4460 AFSReleaseResource( &pCurrentFcb->NPFcb->Resource);
4463 if( pDirEnumEntry != NULL)
4466 AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_2_TAG);
4474 AFSInitializeSpecialShareNameList()
4477 NTSTATUS ntStatus = STATUS_SUCCESS;
4478 AFSDirectoryCB *pDirNode = NULL, *pLastDirNode = NULL;
4479 AFSObjectInfoCB *pObjectInfoCB = NULL;
4480 UNICODE_STRING uniShareName;
4481 ULONG ulEntryLength = 0;
4482 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
4488 RtlInitUnicodeString( &uniShareName,
4491 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
4494 if( pObjectInfoCB == NULL)
4497 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4500 lCount = AFSObjectInfoIncrement( pObjectInfoCB,
4501 AFS_OBJECT_REFERENCE_GLOBAL);
4503 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4504 AFS_TRACE_LEVEL_VERBOSE,
4505 "AFSInitializeSpecialShareNameList (srvsvc) Increment count on object %p Cnt %d\n",
4509 pObjectInfoCB->FileType = (ULONG) AFS_FILE_TYPE_SPECIAL_SHARE_NAME;
4511 ulEntryLength = sizeof( AFSDirectoryCB) +
4512 uniShareName.Length;
4514 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
4518 if( pDirNode == NULL)
4521 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
4522 AFS_OBJECT_REFERENCE_GLOBAL);
4524 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4525 AFS_TRACE_LEVEL_VERBOSE,
4526 "AFSInitializeSpecialShareNameList Decrement count on object %p Cnt %d\n",
4533 AFSDeleteObjectInfo( &pObjectInfoCB);
4536 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4539 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
4540 AFS_TRACE_LEVEL_VERBOSE,
4541 "AFSInitializeSpecialShareNameList (srvsvc) AFS_DIR_ENTRY_TAG allocated %p\n",
4544 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
4545 sizeof( AFSNonPagedDirectoryCB),
4546 AFS_DIR_ENTRY_NP_TAG);
4548 if( pNonPagedDirEntry == NULL)
4551 ExFreePool( pDirNode);
4553 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
4554 AFS_OBJECT_REFERENCE_GLOBAL);
4556 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4557 AFS_TRACE_LEVEL_VERBOSE,
4558 "AFSInitializeSpecialShareNameList Decrement count on object %p Cnt %d\n",
4565 AFSDeleteObjectInfo( &pObjectInfoCB);
4568 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4571 RtlZeroMemory( pDirNode,
4574 RtlZeroMemory( pNonPagedDirEntry,
4575 sizeof( AFSNonPagedDirectoryCB));
4577 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
4579 pDirNode->NonPaged = pNonPagedDirEntry;
4581 pDirNode->ObjectInformation = pObjectInfoCB;
4587 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_PIPE_SERVICE);
4589 pDirNode->NameInformation.FileName.Length = uniShareName.Length;
4591 pDirNode->NameInformation.FileName.MaximumLength = uniShareName.Length;
4593 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
4595 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
4596 uniShareName.Buffer,
4597 pDirNode->NameInformation.FileName.Length);
4599 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
4602 AFSSpecialShareNames = pDirNode;
4604 pLastDirNode = pDirNode;
4607 RtlInitUnicodeString( &uniShareName,
4610 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
4613 if( pObjectInfoCB == NULL)
4616 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4619 lCount = AFSObjectInfoIncrement( pObjectInfoCB,
4620 AFS_OBJECT_REFERENCE_GLOBAL);
4622 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4623 AFS_TRACE_LEVEL_VERBOSE,
4624 "AFSInitializeSpecialShareNameList (ipc$) Incrementing count on object %p Cnt %d\n",
4628 pObjectInfoCB->FileType = (ULONG) AFS_FILE_TYPE_SPECIAL_SHARE_NAME;
4630 ulEntryLength = sizeof( AFSDirectoryCB) +
4631 uniShareName.Length;
4633 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
4637 if( pDirNode == NULL)
4640 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
4641 AFS_OBJECT_REFERENCE_GLOBAL);
4643 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4644 AFS_TRACE_LEVEL_VERBOSE,
4645 "AFSInitializeSpecialShareNameList Decrement count on object %p Cnt %d\n",
4652 AFSDeleteObjectInfo( &pObjectInfoCB);
4655 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4658 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
4659 AFS_TRACE_LEVEL_VERBOSE,
4660 "AFSInitializeSpecialShareNameList (ipc$) AFS_DIR_ENTRY_TAG allocated %p\n",
4663 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
4664 sizeof( AFSNonPagedDirectoryCB),
4665 AFS_DIR_ENTRY_NP_TAG);
4667 if( pNonPagedDirEntry == NULL)
4670 ExFreePool( pDirNode);
4672 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
4673 AFS_OBJECT_REFERENCE_GLOBAL);
4675 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4676 AFS_TRACE_LEVEL_VERBOSE,
4677 "AFSInitializeSpecialShareNameList Decrement count on object %p Cnt %d\n",
4684 AFSDeleteObjectInfo( &pObjectInfoCB);
4687 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4690 RtlZeroMemory( pDirNode,
4693 RtlZeroMemory( pNonPagedDirEntry,
4694 sizeof( AFSNonPagedDirectoryCB));
4696 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
4698 pDirNode->NonPaged = pNonPagedDirEntry;
4700 pDirNode->ObjectInformation = pObjectInfoCB;
4706 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_IPC);
4708 pDirNode->NameInformation.FileName.Length = uniShareName.Length;
4710 pDirNode->NameInformation.FileName.MaximumLength = uniShareName.Length;
4712 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
4714 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
4715 uniShareName.Buffer,
4716 pDirNode->NameInformation.FileName.Length);
4718 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
4721 pLastDirNode->ListEntry.fLink = pDirNode;
4723 pDirNode->ListEntry.bLink = pLastDirNode;
4727 if( !NT_SUCCESS( ntStatus))
4730 if( AFSSpecialShareNames != NULL)
4733 pDirNode = AFSSpecialShareNames;
4735 while( pDirNode != NULL)
4738 pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
4740 lCount = AFSObjectInfoDecrement( pDirNode->ObjectInformation,
4741 AFS_OBJECT_REFERENCE_GLOBAL);
4743 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4744 AFS_TRACE_LEVEL_VERBOSE,
4745 "AFSInitializeSpecialShareNameList Decrement count on object %p Cnt %d\n",
4746 pDirNode->ObjectInformation,
4752 AFSDeleteObjectInfo( &pDirNode->ObjectInformation);
4755 ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
4757 ExFreePool( pDirNode->NonPaged);
4759 ExFreePool( pDirNode);
4761 pDirNode = pLastDirNode;
4764 AFSSpecialShareNames = NULL;
4773 AFSGetSpecialShareNameEntry( IN UNICODE_STRING *ShareName,
4774 IN UNICODE_STRING *SecondaryName)
4777 AFSDirectoryCB *pDirectoryCB = NULL;
4778 ULONGLONG ullHash = 0;
4779 UNICODE_STRING uniFullShareName;
4785 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4786 AFS_TRACE_LEVEL_VERBOSE_2,
4787 "AFSGetSpecialShareNameEntry share name %wZ secondary name %wZ\n",
4791 uniFullShareName = *ShareName;
4794 // Generate our hash value
4797 ullHash = AFSGenerateCRC( &uniFullShareName,
4801 // Loop through our special share names to see if this is one of them
4804 pDirectoryCB = AFSSpecialShareNames;
4806 while( pDirectoryCB != NULL)
4809 if( ullHash == pDirectoryCB->CaseInsensitiveTreeEntry.HashIndex)
4815 pDirectoryCB = (AFSDirectoryCB *)pDirectoryCB->ListEntry.fLink;
4819 return pDirectoryCB;
4823 AFSWaitOnQueuedFlushes( IN AFSFcb *Fcb)
4827 // Block on the queue flush event
4830 KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
4840 AFSWaitOnQueuedReleases()
4843 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
4846 // Block on the queue flush event
4849 KeWaitForSingleObject( &pRDRDeviceExt->Specific.RDR.QueuedReleaseExtentEvent,
4859 AFSIsEqualFID( IN AFSFileID *FileId1,
4860 IN AFSFileID *FileId2)
4863 BOOLEAN bIsEqual = FALSE;
4865 if( FileId1->Hash == FileId2->Hash &&
4866 FileId1->Unique == FileId2->Unique &&
4867 FileId1->Vnode == FileId2->Vnode &&
4868 FileId1->Volume == FileId2->Volume &&
4869 FileId1->Cell == FileId2->Cell)
4879 AFSResetDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB)
4882 NTSTATUS ntStatus = STATUS_SUCCESS;
4883 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
4888 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
4891 // Reset the directory list information
4894 pCurrentDirEntry = ObjectInfoCB->Specific.Directory.DirectoryNodeListHead;
4896 while( pCurrentDirEntry != NULL)
4899 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
4901 if( pCurrentDirEntry->DirOpenReferenceCount <= 0 &&
4902 pCurrentDirEntry->NameArrayReferenceCount <= 0)
4905 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
4906 AFS_TRACE_LEVEL_VERBOSE,
4907 "AFSResetDirectoryContent Deleting dir entry %p for %wZ\n",
4909 &pCurrentDirEntry->NameInformation.FileName));
4911 AFSDeleteDirEntry( ObjectInfoCB,
4917 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
4918 AFS_TRACE_LEVEL_VERBOSE,
4919 "AFSResetDirectoryContent Setting DELETE flag in dir entry %p for %wZ\n",
4921 &pCurrentDirEntry->NameInformation.FileName));
4923 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
4925 AFSRemoveNameEntry( ObjectInfoCB,
4929 pCurrentDirEntry = pNextDirEntry;
4932 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = NULL;
4934 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = NULL;
4936 ObjectInfoCB->Specific.Directory.ShortNameTree = NULL;
4938 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = NULL;
4940 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = NULL;
4942 ObjectInfoCB->Specific.Directory.DirectoryNodeCount = 0;
4944 AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
4945 AFS_TRACE_LEVEL_VERBOSE,
4946 "AFSResetDirectoryContent Reset count to 0 on parent FID %08lX-%08lX-%08lX-%08lX\n",
4947 ObjectInfoCB->FileId.Cell,
4948 ObjectInfoCB->FileId.Volume,
4949 ObjectInfoCB->FileId.Vnode,
4950 ObjectInfoCB->FileId.Unique));
4957 AFSEnumerateGlobalRoot( IN GUID *AuthGroup)
4960 NTSTATUS ntStatus = STATUS_SUCCESS;
4961 AFSDirectoryCB *pDirGlobalDirNode = NULL;
4962 UNICODE_STRING uniFullName;
4967 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4968 AFS_TRACE_LEVEL_VERBOSE,
4969 "AFSEnumerateGlobalRoot Acquiring GlobalRoot DirectoryNodeHdr.TreeLock lock %p EXCL %08lX\n",
4970 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4971 PsGetCurrentThread()));
4973 AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4976 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
4979 try_return( ntStatus);
4983 // Initialize the root information
4986 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.ContentIndex = 1;
4989 // Enumerate the shares in the volume
4992 ntStatus = AFSEnumerateDirectory( AuthGroup,
4993 &AFSGlobalRoot->ObjectInformation,
4996 if( !NT_SUCCESS( ntStatus))
4999 try_return( ntStatus);
5002 pDirGlobalDirNode = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead;
5004 uniFullName.MaximumLength = PAGE_SIZE;
5005 uniFullName.Length = 0;
5007 uniFullName.Buffer = (WCHAR *)AFSLibExAllocatePoolWithTag( PagedPool,
5008 uniFullName.MaximumLength,
5009 AFS_GENERIC_MEMORY_12_TAG);
5011 if( uniFullName.Buffer == NULL)
5015 // Reset the directory content
5018 AFSResetDirectoryContent( &AFSGlobalRoot->ObjectInformation);
5020 ClearFlag( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
5022 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5026 // Populate our list of entries in the NP enumeration list
5029 while( pDirGlobalDirNode != NULL)
5032 uniFullName.Buffer[ 0] = L'\\';
5033 uniFullName.Buffer[ 1] = L'\\';
5035 uniFullName.Length = 2 * sizeof( WCHAR);
5037 RtlCopyMemory( &uniFullName.Buffer[ 2],
5038 AFSServerName.Buffer,
5039 AFSServerName.Length);
5041 uniFullName.Length += AFSServerName.Length;
5043 uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)] = L'\\';
5045 uniFullName.Length += sizeof( WCHAR);
5047 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
5048 pDirGlobalDirNode->NameInformation.FileName.Buffer,
5049 pDirGlobalDirNode->NameInformation.FileName.Length);
5051 uniFullName.Length += pDirGlobalDirNode->NameInformation.FileName.Length;
5053 AFSAddConnectionEx( &uniFullName,
5054 RESOURCEDISPLAYTYPE_SHARE,
5057 pDirGlobalDirNode = (AFSDirectoryCB *)pDirGlobalDirNode->ListEntry.fLink;
5060 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
5064 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
5071 AFSIsRelativeName( IN UNICODE_STRING *Name)
5074 BOOLEAN bIsRelative = FALSE;
5076 if( Name->Length > 0 &&
5077 Name->Buffer[ 0] != L'\\')
5087 AFSIsAbsoluteAFSName( IN UNICODE_STRING *Name)
5089 UNICODE_STRING uniTempName;
5090 BOOLEAN bIsAbsolute = FALSE;
5093 // An absolute AFS path must begin with \afs\... or equivalent
5096 if ( Name->Length == 0 ||
5097 Name->Length <= AFSMountRootName.Length + sizeof( WCHAR) ||
5098 Name->Buffer[ 0] != L'\\' ||
5099 Name->Buffer[ AFSMountRootName.Length/sizeof( WCHAR)] != L'\\')
5105 uniTempName.Length = AFSMountRootName.Length;
5106 uniTempName.MaximumLength = AFSMountRootName.Length;
5108 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5109 uniTempName.MaximumLength,
5110 AFS_NAME_BUFFER_TWO_TAG);
5112 if( uniTempName.Buffer == NULL)
5118 RtlCopyMemory( uniTempName.Buffer,
5120 AFSMountRootName.Length);
5122 bIsAbsolute = (0 == RtlCompareUnicodeString( &uniTempName,
5126 AFSExFreePoolWithTag( uniTempName.Buffer,
5127 AFS_NAME_BUFFER_TWO_TAG);
5134 AFSUpdateName( IN UNICODE_STRING *Name)
5139 while( usIndex < Name->Length/sizeof( WCHAR))
5142 if( Name->Buffer[ usIndex] == L'/')
5145 Name->Buffer[ usIndex] = L'\\';
5155 AFSUpdateTargetName( IN OUT UNICODE_STRING *TargetName,
5156 IN OUT ULONG *Flags,
5157 IN WCHAR *NameBuffer,
5158 IN USHORT NameLength)
5161 NTSTATUS ntStatus = STATUS_SUCCESS;
5162 WCHAR *pTmpBuffer = NULL;
5168 // If we have enough space then just move in the name otherwise
5169 // allocate a new buffer
5172 if( TargetName->Length < NameLength)
5175 pTmpBuffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5177 AFS_NAME_BUFFER_FIVE_TAG);
5179 if( pTmpBuffer == NULL)
5182 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5185 if( BooleanFlagOn( *Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
5188 AFSExFreePoolWithTag( TargetName->Buffer, AFS_NAME_BUFFER_FIVE_TAG);
5191 TargetName->MaximumLength = NameLength;
5193 TargetName->Buffer = pTmpBuffer;
5195 SetFlag( *Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER);
5198 TargetName->Length = NameLength;
5200 RtlCopyMemory( TargetName->Buffer,
5202 TargetName->Length);
5205 // Update the name in the buffer
5208 AFSUpdateName( TargetName);
5219 AFSSetEnumerationEvent( IN AFSFcb *Fcb)
5224 // Depending on the type of node, set the event
5227 switch( Fcb->Header.NodeTypeCode)
5230 case AFS_DIRECTORY_FCB:
5235 lCount = InterlockedIncrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
5245 AFSClearEnumerationEvent( IN AFSFcb *Fcb)
5251 // Depending on the type of node, set the event
5254 switch( Fcb->Header.NodeTypeCode)
5257 case AFS_DIRECTORY_FCB:
5262 ASSERT( Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0);
5264 lCount = InterlockedDecrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
5274 AFSIsEnumerationInProcess( IN AFSObjectInfoCB *ObjectInfo)
5277 BOOLEAN bIsInProcess = FALSE;
5282 if( ObjectInfo->Fcb == NULL)
5285 try_return( bIsInProcess);
5288 switch( ObjectInfo->Fcb->Header.NodeTypeCode)
5291 case AFS_DIRECTORY_FCB:
5296 if( ObjectInfo->Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0)
5299 bIsInProcess = TRUE;
5311 return bIsInProcess;
5315 AFSVerifyVolume( IN ULONGLONG ProcessId,
5316 IN AFSVolumeCB *VolumeCB)
5319 UNREFERENCED_PARAMETER(ProcessId);
5320 UNREFERENCED_PARAMETER(VolumeCB);
5321 NTSTATUS ntStatus = STATUS_SUCCESS;
5328 AFSInitPIOCtlDirectoryCB( IN AFSObjectInfoCB *ParentObjectInfo)
5331 NTSTATUS ntStatus = STATUS_SUCCESS;
5332 AFSObjectInfoCB *pObjectInfoCB = NULL;
5333 AFSDirectoryCB *pDirNode = NULL;
5334 ULONG ulEntryLength = 0;
5335 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
5341 AFSAcquireExcl( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
5344 pObjectInfoCB = AFSAllocateObjectInfo( ParentObjectInfo,
5347 if( pObjectInfoCB == NULL)
5350 AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
5352 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5355 lCount = AFSObjectInfoIncrement( pObjectInfoCB,
5356 AFS_OBJECT_REFERENCE_PIOCTL);
5358 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
5359 AFS_TRACE_LEVEL_VERBOSE,
5360 "AFSInitPIOCtlDirectoryCB Increment count on object %p Cnt %d\n",
5364 AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
5366 pObjectInfoCB->FileType = (ULONG) AFS_FILE_TYPE_PIOCTL;
5368 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
5370 ulEntryLength = sizeof( AFSDirectoryCB) + AFSPIOCtlName.Length;
5372 pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
5376 if( pDirNode == NULL)
5379 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5382 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
5383 AFS_TRACE_LEVEL_VERBOSE,
5384 "AFSInitPIOCtlDirectoryCB AFS_DIR_ENTRY_TAG allocated %p\n",
5387 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
5388 sizeof( AFSNonPagedDirectoryCB),
5389 AFS_DIR_ENTRY_NP_TAG);
5391 if( pNonPagedDirEntry == NULL)
5394 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5397 RtlZeroMemory( pDirNode,
5400 RtlZeroMemory( pNonPagedDirEntry,
5401 sizeof( AFSNonPagedDirectoryCB));
5403 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
5405 pDirNode->NonPaged = pNonPagedDirEntry;
5407 pDirNode->ObjectInformation = pObjectInfoCB;
5409 pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_PIOCTL_INDEX;
5415 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_FAKE);
5417 pDirNode->NameInformation.FileName.Length = AFSPIOCtlName.Length;
5419 pDirNode->NameInformation.FileName.MaximumLength = AFSPIOCtlName.Length;
5421 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
5423 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
5424 AFSPIOCtlName.Buffer,
5425 pDirNode->NameInformation.FileName.Length);
5427 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
5430 if ( InterlockedCompareExchangePointer( (PVOID *)&ParentObjectInfo->Specific.Directory.PIOCtlDirectoryCB, pDirNode, NULL) != NULL)
5433 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5434 AFS_TRACE_LEVEL_WARNING,
5435 "AFSInitPIOCtlDirectoryCB Raced PIOCtlDirectoryCB %p pFcb %p\n",
5436 ParentObjectInfo->Specific.Directory.PIOCtlDirectoryCB,
5439 try_return( ntStatus = STATUS_REPARSE);
5444 if ( ntStatus != STATUS_SUCCESS)
5447 if ( pDirNode != NULL)
5450 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
5451 AFS_TRACE_LEVEL_VERBOSE,
5452 "AFSInitPIOCtlDirectoryCB AFS_DIR_ENTRY_TAG deallocating %p\n",
5455 AFSExFreePoolWithTag( pDirNode, AFS_DIR_ENTRY_TAG);
5458 if( pNonPagedDirEntry != NULL)
5461 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
5463 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
5466 if ( pObjectInfoCB != NULL)
5469 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
5470 AFS_OBJECT_REFERENCE_PIOCTL);
5472 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
5473 AFS_TRACE_LEVEL_VERBOSE,
5474 "AFSInitPIOCtlDirectoryCB Decrement count on object %p Cnt %d\n",
5481 AFSDeleteObjectInfo( &pObjectInfoCB);
5491 AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB,
5492 IN AFSDirectoryCB *DirectoryCB,
5493 IN UNICODE_STRING *ParentPathName,
5494 IN AFSNameArrayHdr *RelatedNameArray,
5496 OUT AFSFileInfoCB *FileInfo)
5499 NTSTATUS ntStatus = STATUS_SUCCESS;
5500 AFSDirEnumEntry *pDirEntry = NULL;
5501 UNICODE_STRING uniFullPathName = {0};
5502 AFSNameArrayHdr *pNameArray = NULL;
5503 AFSVolumeCB *pVolumeCB = NULL;
5504 LONG VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
5505 AFSVolumeCB *pNewVolumeCB = NULL;
5506 LONG NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
5507 AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
5508 AFSDirectoryCB *pNewParentDirEntry = NULL;
5509 WCHAR *pwchBuffer = NULL;
5510 UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
5511 ULONG ulNameDifference = 0;
5518 // Retrieve a target name for the entry
5521 AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
5524 if( DirectoryCB->NameInformation.TargetName.Length == 0)
5527 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5529 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
5534 if( !NT_SUCCESS( ntStatus) ||
5535 pDirEntry->TargetNameLength == 0)
5538 if( pDirEntry != NULL)
5541 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
5544 try_return( ntStatus);
5547 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
5550 if( DirectoryCB->NameInformation.TargetName.Length == 0)
5554 // Update the target name
5557 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
5558 &DirectoryCB->Flags,
5559 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
5560 (USHORT)pDirEntry->TargetNameLength);
5562 if( !NT_SUCCESS( ntStatus))
5565 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5567 try_return( ntStatus);
5571 AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
5575 // Need to pass the full path in for parsing.
5578 if( AFSIsRelativeName( &DirectoryCB->NameInformation.TargetName))
5581 uniFullPathName.Length = 0;
5582 uniFullPathName.MaximumLength = ParentPathName->Length +
5584 DirectoryCB->NameInformation.TargetName.Length;
5586 uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5587 uniFullPathName.MaximumLength,
5588 AFS_NAME_BUFFER_SIX_TAG);
5590 if( uniFullPathName.Buffer == NULL)
5593 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5595 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5598 pwchBuffer = uniFullPathName.Buffer;
5600 RtlZeroMemory( uniFullPathName.Buffer,
5601 uniFullPathName.MaximumLength);
5603 RtlCopyMemory( uniFullPathName.Buffer,
5604 ParentPathName->Buffer,
5605 ParentPathName->Length);
5607 uniFullPathName.Length = ParentPathName->Length;
5609 if( uniFullPathName.Buffer[ (uniFullPathName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
5610 DirectoryCB->NameInformation.TargetName.Buffer[ 0] != L'\\')
5613 uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)] = L'\\';
5615 uniFullPathName.Length += sizeof( WCHAR);
5618 RtlCopyMemory( &uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)],
5619 DirectoryCB->NameInformation.TargetName.Buffer,
5620 DirectoryCB->NameInformation.TargetName.Length);
5622 uniFullPathName.Length += DirectoryCB->NameInformation.TargetName.Length;
5624 uniParsedName.Length = uniFullPathName.Length - ParentPathName->Length;
5625 uniParsedName.MaximumLength = uniParsedName.Length;
5627 uniParsedName.Buffer = &uniFullPathName.Buffer[ ParentPathName->Length/sizeof( WCHAR)];
5629 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5632 // We populate up to the current parent
5635 if( RelatedNameArray != NULL)
5638 pNameArray = AFSInitNameArray( NULL,
5639 RelatedNameArray->MaxElementCount);
5641 if( pNameArray == NULL)
5644 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5647 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
5654 pNameArray = AFSInitNameArray( NULL,
5657 if( pNameArray == NULL)
5660 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5663 ntStatus = AFSPopulateNameArray( pNameArray,
5668 if( !NT_SUCCESS( ntStatus))
5671 try_return( ntStatus);
5674 pVolumeCB = ParentDirectoryCB->ObjectInformation->VolumeCB;
5676 pParentDirEntry = ParentDirectoryCB;
5681 uniFullPathName.Length = 0;
5682 uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
5684 uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5685 uniFullPathName.MaximumLength,
5686 AFS_NAME_BUFFER_SEVEN_TAG);
5688 if( uniFullPathName.Buffer == NULL)
5691 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5693 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5696 pwchBuffer = uniFullPathName.Buffer;
5698 RtlZeroMemory( uniFullPathName.Buffer,
5699 uniFullPathName.MaximumLength);
5701 RtlCopyMemory( uniFullPathName.Buffer,
5702 DirectoryCB->NameInformation.TargetName.Buffer,
5703 DirectoryCB->NameInformation.TargetName.Length);
5705 uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
5708 // This name should begin with the \afs server so parse it off and check it
5711 FsRtlDissectName( uniFullPathName,
5715 if( RtlCompareUnicodeString( &uniComponentName,
5720 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5722 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5723 AFS_TRACE_LEVEL_ERROR,
5724 "AFSRetrieveFileAttributes Name %wZ contains invalid server name\n",
5727 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
5730 uniFullPathName = uniRemainingPath;
5732 uniParsedName = uniFullPathName;
5734 ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
5736 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5742 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
5745 if( pNameArray == NULL)
5748 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5751 pVolumeCB = AFSGlobalRoot;
5753 pParentDirEntry = AFSGlobalRoot->DirectoryCB;
5757 // Increment the ref count on the volume and dir entry for correct processing below
5760 VolumeReferenceReason = AFS_VOLUME_REFERENCE_FILE_ATTRS;
5762 lCount = AFSVolumeIncrement( pVolumeCB,
5763 VolumeReferenceReason);
5765 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
5766 AFS_TRACE_LEVEL_VERBOSE,
5767 "AFSRetrieveFileAttributes Increment count on volume %p Reason %u Cnt %d\n",
5769 VolumeReferenceReason,
5772 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
5774 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5775 AFS_TRACE_LEVEL_VERBOSE,
5776 "AFSRetrieveFileAttributes Increment count on %wZ DE %p Ccb %p Cnt %d\n",
5777 &pParentDirEntry->NameInformation.FileName,
5782 ntStatus = AFSLocateNameEntry( NULL,
5787 AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL,
5791 &NewVolumeReferenceReason,
5792 &pNewParentDirEntry,
5796 if ( pNewVolumeCB != NULL)
5799 // AFSLocateNameEntry returns pNewVolumeCB with a reference held
5800 // even if pVolumeCB == pNewVolumeCB. It is always safe to release
5801 // the reference on pVolumeCB that was held prior to the call.
5802 // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
5803 // will be released second.
5806 lCount = AFSVolumeDecrement( pVolumeCB,
5807 VolumeReferenceReason);
5809 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
5810 AFS_TRACE_LEVEL_VERBOSE,
5811 "AFSRetrieveFileAttributes Decrement count on volume %p Reason %u Cnt %d\n",
5813 VolumeReferenceReason,
5816 pVolumeCB = pNewVolumeCB;
5818 pNewVolumeCB = NULL;
5820 VolumeReferenceReason = NewVolumeReferenceReason;
5822 NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
5826 // AFSLocateNameEntry does not alter the reference count of
5827 // pParentDirectoryCB and it returns pNewParentDirectoryCB with
5828 // a reference held.
5831 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
5833 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5834 AFS_TRACE_LEVEL_VERBOSE,
5835 "AFSRetrieveFileAttributes DecrementX count on %wZ DE %p Cnt %d\n",
5836 &pParentDirEntry->NameInformation.FileName,
5840 pParentDirEntry = pNewParentDirEntry;
5842 pNewParentDirEntry = NULL;
5844 if( !NT_SUCCESS( ntStatus) ||
5845 ntStatus == STATUS_REPARSE)
5848 try_return( ntStatus);
5852 // Store off the information
5855 FileInfo->FileAttributes = pDirectoryEntry->ObjectInformation->FileAttributes;
5858 // Check for the mount point being returned
5861 if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
5862 pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DFSLINK)
5865 FileInfo->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
5867 else if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
5870 if ( FileInfo->FileAttributes == FILE_ATTRIBUTE_NORMAL)
5873 FileInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
5878 FileInfo->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
5882 FileInfo->AllocationSize = pDirectoryEntry->ObjectInformation->AllocationSize;
5884 FileInfo->EndOfFile = pDirectoryEntry->ObjectInformation->EndOfFile;
5886 FileInfo->CreationTime = pDirectoryEntry->ObjectInformation->CreationTime;
5888 FileInfo->LastAccessTime = pDirectoryEntry->ObjectInformation->LastAccessTime;
5890 FileInfo->LastWriteTime = pDirectoryEntry->ObjectInformation->LastWriteTime;
5892 FileInfo->ChangeTime = pDirectoryEntry->ObjectInformation->ChangeTime;
5896 if( pDirEntry != NULL)
5899 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
5902 if( pDirectoryEntry != NULL)
5905 lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
5907 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5908 AFS_TRACE_LEVEL_VERBOSE,
5909 "AFSRetrieveFileAttributes Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
5910 &pDirectoryEntry->NameInformation.FileName,
5915 ASSERT( lCount >= 0);
5918 if ( pParentDirEntry != NULL)
5921 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
5923 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5924 AFS_TRACE_LEVEL_VERBOSE,
5925 "AFSRetrieveFileAttributes Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
5926 &pParentDirEntry->NameInformation.FileName,
5931 ASSERT( lCount >= 0);
5934 if( pVolumeCB != NULL)
5937 lCount = AFSVolumeDecrement( pVolumeCB,
5938 VolumeReferenceReason);
5940 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
5941 AFS_TRACE_LEVEL_VERBOSE,
5942 "AFSRetrieveFileAttributes Decrement2 count on volume %p Reason %u Cnt %d\n",
5944 VolumeReferenceReason,
5948 if( pNameArray != NULL)
5951 AFSFreeNameArray( pNameArray);
5954 if( pwchBuffer != NULL)
5958 // Always free the buffer that we allocated as AFSLocateNameEntry
5959 // will not free it. If uniFullPathName.Buffer was allocated by
5960 // AFSLocateNameEntry, then we must free that as well.
5961 // Check that the uniFullPathName.Buffer in the string is not the same
5962 // offset by the length of the server name
5965 if( uniFullPathName.Length > 0 &&
5966 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
5969 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
5972 AFSExFreePoolWithTag( pwchBuffer, 0);
5980 AFSAllocateObjectInfo( IN AFSObjectInfoCB *ParentObjectInfo,
5981 IN ULONGLONG HashIndex)
5984 NTSTATUS ntStatus = STATUS_SUCCESS;
5985 AFSObjectInfoCB *pObjectInfo = NULL;
5991 pObjectInfo = (AFSObjectInfoCB *)AFSExAllocatePoolWithTag( PagedPool,
5992 sizeof( AFSObjectInfoCB),
5993 AFS_OBJECT_INFO_TAG);
5995 if( pObjectInfo == NULL)
5998 try_return( pObjectInfo);
6001 RtlZeroMemory( pObjectInfo,
6002 sizeof( AFSObjectInfoCB));
6004 pObjectInfo->NonPagedInfo = (AFSNonPagedObjectInfoCB *)AFSExAllocatePoolWithTag( NonPagedPool,
6005 sizeof( AFSNonPagedObjectInfoCB),
6006 AFS_NP_OBJECT_INFO_TAG);
6008 if( pObjectInfo->NonPagedInfo == NULL)
6011 AFSExFreePoolWithTag( pObjectInfo, AFS_OBJECT_INFO_TAG);
6013 try_return( pObjectInfo = NULL);
6016 ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6018 ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
6020 pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock = &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock;
6022 if( ParentObjectInfo != NULL)
6025 pObjectInfo->VolumeCB = ParentObjectInfo->VolumeCB;
6027 pObjectInfo->ParentFileId = ParentObjectInfo->FileId;
6029 SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID);
6031 AFSAcquireShared( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
6034 lCount = AFSObjectInfoIncrement( ParentObjectInfo,
6035 AFS_OBJECT_REFERENCE_CHILD);
6037 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
6038 AFS_TRACE_LEVEL_VERBOSE,
6039 "AFSAllocateObjectInfo Increment count on parent object %p Cnt %d\n",
6043 AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
6047 // Initialize the access time
6050 KeQueryTickCount( &pObjectInfo->LastAccessCount);
6055 ASSERT( ParentObjectInfo);
6058 // Insert the entry into the object tree and list
6061 pObjectInfo->TreeEntry.HashIndex = HashIndex;
6063 if( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead == NULL)
6066 ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead = &pObjectInfo->TreeEntry;
6071 ntStatus = AFSInsertHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
6072 &pObjectInfo->TreeEntry);
6074 ASSERT( NT_SUCCESS( ntStatus));
6078 // And the object list in the volume
6081 if( ParentObjectInfo->VolumeCB->ObjectInfoListHead == NULL)
6084 ParentObjectInfo->VolumeCB->ObjectInfoListHead = pObjectInfo;
6089 ParentObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = (void *)pObjectInfo;
6091 pObjectInfo->ListEntry.bLink = (void *)ParentObjectInfo->VolumeCB->ObjectInfoListTail;
6094 ParentObjectInfo->VolumeCB->ObjectInfoListTail = pObjectInfo;
6097 // Indicate the object is in the hash tree and linked list in the volume
6100 SetFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE | AFS_OBJECT_INSERTED_VOLUME_LIST);
6112 AFSObjectInfoIncrement( IN AFSObjectInfoCB *ObjectInfo,
6118 if ( ObjectInfo->ObjectReferenceCount == 0)
6121 AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6124 lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6129 AFSAcquireShared( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6132 lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6137 AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6139 AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6144 InterlockedIncrement( &ObjectInfo->ObjectReferences[ Reason]);
6146 AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6152 AFSObjectInfoDecrement( IN AFSObjectInfoCB *ObjectInfo,
6156 LONG lCount, lCount2;
6158 AFSAcquireShared( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6161 lCount = InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);
6166 lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6168 AFSReleaseResource(&ObjectInfo->NonPagedInfo->ObjectInfoLock);
6170 AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6173 lCount = InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);
6176 lCount2 = InterlockedDecrement( &ObjectInfo->ObjectReferences[ Reason]);
6178 ASSERT( lCount2 >= 0);
6180 AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6186 AFSFindObjectInfo( IN AFSVolumeCB *VolumeCB,
6187 IN AFSFileID *FileId,
6188 IN BOOLEAN bUpdateLastUse)
6190 DWORD ntStatus = STATUS_SUCCESS;
6192 AFSObjectInfoCB *pObjectInfo = NULL;
6195 ullIndex = AFSCreateLowIndex( FileId);
6197 AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
6200 if ( AFSIsEqualFID( &VolumeCB->ObjectInformation.FileId, FileId))
6203 pObjectInfo = &VolumeCB->ObjectInformation;
6208 ntStatus = AFSLocateHashEntry( VolumeCB->ObjectInfoTree.TreeHead,
6210 (AFSBTreeEntry **)&pObjectInfo);
6213 if ( NT_SUCCESS( ntStatus)) {
6215 lCount = AFSObjectInfoIncrement( pObjectInfo,
6216 AFS_OBJECT_REFERENCE_FIND);
6218 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
6219 AFS_TRACE_LEVEL_VERBOSE,
6220 "AFSFindObjectInfo Decrement count on object %p Cnt %d\n",
6224 if ( bUpdateLastUse)
6227 KeQueryTickCount( &pObjectInfo->LastAccessCount);
6231 AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
6237 AFSReleaseObjectInfo( IN AFSObjectInfoCB **ppObjectInfo)
6241 lCount = AFSObjectInfoDecrement( *ppObjectInfo,
6242 AFS_OBJECT_REFERENCE_FIND);
6244 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
6245 AFS_TRACE_LEVEL_VERBOSE,
6246 "AFSReleaseObjectInfo Decrement count on object %p Cnt %d\n",
6250 *ppObjectInfo = NULL;
6254 AFSDeleteObjectInfo( IN AFSObjectInfoCB **ppObjectInfo)
6256 BOOLEAN bAcquiredTreeLock = FALSE;
6257 AFSObjectInfoCB *pObjectInfo = NULL;
6258 AFSVolumeCB * pVolume = NULL;
6259 BOOLEAN bHeldInService;
6260 AFSObjectInfoCB * pParentObjectInfo = NULL;
6266 if ( BooleanFlagOn( (*ppObjectInfo)->Flags, AFS_OBJECT_ROOT_VOLUME))
6270 // AFSDeleteObjectInfo should never be called on the ObjectInformationCB
6271 // embedded in the VolumeCB.
6279 pVolume = (*ppObjectInfo)->VolumeCB;
6281 if( !ExIsResourceAcquiredExclusiveLite( pVolume->ObjectInfoTree.TreeLock))
6284 ASSERT( !ExIsResourceAcquiredLite( pVolume->ObjectInfoTree.TreeLock));
6286 AFSAcquireExcl( pVolume->ObjectInfoTree.TreeLock,
6289 bAcquiredTreeLock = TRUE;
6292 for ( lCount = 0; lCount < AFS_OBJECT_REFERENCE_MAX; lCount++)
6295 ASSERT( (*ppObjectInfo)->ObjectReferences[ lCount] >= 0);
6298 ASSERT( (*ppObjectInfo)->ObjectReferenceCount == 0);
6300 pObjectInfo = (AFSObjectInfoCB *) InterlockedCompareExchangePointer( (PVOID *)ppObjectInfo,
6304 if ( pObjectInfo == NULL)
6307 try_return( NOTHING);
6310 ASSERT( *ppObjectInfo == NULL);
6312 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
6315 pParentObjectInfo = AFSFindObjectInfo( pVolume,
6316 &pObjectInfo->ParentFileId,
6319 if( pParentObjectInfo != NULL)
6322 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID);
6324 AFSAcquireShared( pParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
6327 lCount = AFSObjectInfoDecrement( pParentObjectInfo,
6328 AFS_OBJECT_REFERENCE_CHILD);
6330 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
6331 AFS_TRACE_LEVEL_VERBOSE,
6332 "AFSDeleteObjectInfo Decrement count on parent object %p Cnt %d\n",
6336 AFSReleaseResource( pParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
6338 AFSReleaseObjectInfo( &pParentObjectInfo);
6343 // Remove it from the tree and list if it was inserted
6346 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
6349 AFSRemoveHashEntry( &pVolume->ObjectInfoTree.TreeHead,
6350 &pObjectInfo->TreeEntry);
6353 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_VOLUME_LIST))
6356 if( pObjectInfo->ListEntry.fLink == NULL)
6359 pVolume->ObjectInfoListTail = (AFSObjectInfoCB *)pObjectInfo->ListEntry.bLink;
6361 if( pVolume->ObjectInfoListTail != NULL)
6364 pVolume->ObjectInfoListTail->ListEntry.fLink = NULL;
6370 ((AFSObjectInfoCB *)(pObjectInfo->ListEntry.fLink))->ListEntry.bLink = pObjectInfo->ListEntry.bLink;
6373 if( pObjectInfo->ListEntry.bLink == NULL)
6376 pVolume->ObjectInfoListHead = (AFSObjectInfoCB *)pObjectInfo->ListEntry.fLink;
6378 if( pVolume->ObjectInfoListHead != NULL)
6381 pVolume->ObjectInfoListHead->ListEntry.bLink = NULL;
6387 ((AFSObjectInfoCB *)(pObjectInfo->ListEntry.bLink))->ListEntry.fLink = pObjectInfo->ListEntry.fLink;
6391 bHeldInService = BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_HELD_IN_SERVICE);
6396 FileId = pObjectInfo->FileId;
6399 ASSERT( pObjectInfo->ObjectReferenceCount == 0);
6401 ExDeleteResourceLite( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
6403 ExDeleteResourceLite( &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6405 AFSExFreePoolWithTag( pObjectInfo->NonPagedInfo, AFS_NP_OBJECT_INFO_TAG);
6407 AFSExFreePoolWithTag( pObjectInfo, AFS_OBJECT_INFO_TAG);
6411 if( bAcquiredTreeLock)
6414 AFSReleaseResource( pVolume->ObjectInfoTree.TreeLock);
6418 // Release the fid in the service
6424 AFSReleaseFid( &FileId);
6432 AFSEvaluateRootEntry( IN AFSDirectoryCB *DirectoryCB,
6433 OUT AFSDirectoryCB **TargetDirEntry)
6436 NTSTATUS ntStatus = STATUS_SUCCESS;
6437 AFSDirEnumEntry *pDirEntry = NULL;
6438 UNICODE_STRING uniFullPathName = {0};
6439 AFSNameArrayHdr *pNameArray = NULL;
6440 AFSVolumeCB *pVolumeCB = NULL;
6441 LONG VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
6442 AFSVolumeCB *pNewVolumeCB = NULL;
6443 LONG NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
6444 AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
6445 AFSDirectoryCB *pNewParentDirEntry = NULL;
6446 WCHAR *pwchBuffer = NULL;
6447 UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
6448 ULONG ulNameDifference = 0;
6455 ntStatus = AFSRetrieveValidAuthGroup( NULL,
6456 DirectoryCB->ObjectInformation,
6460 if( !NT_SUCCESS( ntStatus))
6462 try_return( ntStatus);
6466 // Retrieve a target name for the entry
6469 AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
6472 if( DirectoryCB->NameInformation.TargetName.Length == 0)
6475 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6477 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
6482 if( !NT_SUCCESS( ntStatus) ||
6483 pDirEntry->TargetNameLength == 0)
6486 if( pDirEntry != NULL)
6489 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
6492 try_return( ntStatus);
6495 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
6498 if( DirectoryCB->NameInformation.TargetName.Length == 0)
6502 // Update the target name
6505 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
6506 &DirectoryCB->Flags,
6507 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
6508 (USHORT)pDirEntry->TargetNameLength);
6510 if( !NT_SUCCESS( ntStatus))
6513 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6515 try_return( ntStatus);
6519 AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
6523 // Need to pass the full path in for parsing.
6526 uniFullPathName.Length = 0;
6527 uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
6529 uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6530 uniFullPathName.MaximumLength,
6531 AFS_NAME_BUFFER_EIGHT_TAG);
6533 if( uniFullPathName.Buffer == NULL)
6536 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6538 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6541 pwchBuffer = uniFullPathName.Buffer;
6543 RtlZeroMemory( uniFullPathName.Buffer,
6544 uniFullPathName.MaximumLength);
6546 RtlCopyMemory( uniFullPathName.Buffer,
6547 DirectoryCB->NameInformation.TargetName.Buffer,
6548 DirectoryCB->NameInformation.TargetName.Length);
6550 uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6553 // This name should begin with the \afs server so parse it off and chech it
6556 FsRtlDissectName( uniFullPathName,
6560 if( RtlCompareUnicodeString( &uniComponentName,
6566 // Try evaluating the full path
6569 uniFullPathName.Buffer = pwchBuffer;
6571 uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6573 uniFullPathName.MaximumLength = uniFullPathName.Length;
6578 uniFullPathName = uniRemainingPath;
6581 uniParsedName = uniFullPathName;
6583 ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
6585 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6591 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
6594 if( pNameArray == NULL)
6597 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6600 pVolumeCB = AFSGlobalRoot;
6602 pParentDirEntry = AFSGlobalRoot->DirectoryCB;
6604 VolumeReferenceReason = AFS_VOLUME_REFERENCE_EVAL_ROOT;
6606 lCount = AFSVolumeIncrement( pVolumeCB,
6607 VolumeReferenceReason);
6609 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6610 AFS_TRACE_LEVEL_VERBOSE,
6611 "AFSEvaluateRootEntry Increment count on volume %p Reason %u Cnt %d\n",
6613 VolumeReferenceReason,
6616 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
6618 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6619 AFS_TRACE_LEVEL_VERBOSE,
6620 "AFSEvaluateRootEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
6621 &pParentDirEntry->NameInformation.FileName,
6626 ntStatus = AFSLocateNameEntry( NULL,
6635 &VolumeReferenceReason,
6636 &pNewParentDirEntry,
6640 if ( pNewVolumeCB != NULL)
6643 // AFSLocateNameEntry returns pNewVolumeCB with a reference held
6644 // even if pVolumeCB == pNewVolumeCB. It is always safe to release
6645 // the reference on pVolumeCB that was held prior to the call.
6646 // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
6647 // will be released second.
6650 lCount = AFSVolumeDecrement( pVolumeCB,
6651 VolumeReferenceReason);
6653 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6654 AFS_TRACE_LEVEL_VERBOSE,
6655 "AFSEvaluateRootEntry Decrement count on volume %p Reason %u Cnt %d\n",
6657 VolumeReferenceReason,
6660 pVolumeCB = pNewVolumeCB;
6662 pNewVolumeCB = NULL;
6664 VolumeReferenceReason = NewVolumeReferenceReason;
6666 NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
6670 // AFSLocateNameEntry does not alter the reference count of
6671 // pParentDirectoryCB and it returns pNewParentDirectoryCB with
6672 // a reference held.
6675 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
6677 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6678 AFS_TRACE_LEVEL_VERBOSE,
6679 "AFSEvaluateRootEntry DecrementX count on %wZ DE %p Cnt %d\n",
6680 &pParentDirEntry->NameInformation.FileName,
6684 pParentDirEntry = pNewParentDirEntry;
6686 pNewParentDirEntry = NULL;
6688 if( !NT_SUCCESS( ntStatus) ||
6689 ntStatus == STATUS_REPARSE)
6694 try_return( ntStatus);
6698 // Pass back the target dir entry for this request
6699 // The caller must release the DirOpenReferenceCount
6702 *TargetDirEntry = pDirectoryEntry;
6704 pDirectoryEntry = NULL;
6708 if( pDirectoryEntry != NULL)
6711 lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
6713 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6714 AFS_TRACE_LEVEL_VERBOSE,
6715 "AFSEvaluateRootEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6716 &pDirectoryEntry->NameInformation.FileName,
6721 ASSERT( lCount >= 0);
6724 if ( pParentDirEntry != NULL)
6727 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
6729 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6730 AFS_TRACE_LEVEL_VERBOSE,
6731 "AFSEvaluateRootEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
6732 &pParentDirEntry->NameInformation.FileName,
6737 ASSERT( lCount >= 0);
6740 if( pDirEntry != NULL)
6743 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
6746 if( pVolumeCB != NULL)
6749 lCount = AFSVolumeDecrement( pVolumeCB,
6750 VolumeReferenceReason);
6752 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6753 AFS_TRACE_LEVEL_VERBOSE,
6754 "AFSEvaluateRootEntry Decrement2 count on volume %p Reason %u Cnt %d\n",
6756 VolumeReferenceReason,
6760 if( pNameArray != NULL)
6763 AFSFreeNameArray( pNameArray);
6766 if( pwchBuffer != NULL)
6770 // Always free the buffer that we allocated as AFSLocateNameEntry
6771 // will not free it. If uniFullPathName.Buffer was allocated by
6772 // AFSLocateNameEntry, then we must free that as well.
6773 // Check that the uniFullPathName.Buffer in the string is not the same
6774 // offset by the length of the server name
6777 if( uniFullPathName.Length > 0 &&
6778 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
6781 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
6784 AFSExFreePoolWithTag( pwchBuffer, 0);
6792 AFSCleanupFcb( IN AFSFcb *Fcb,
6793 IN BOOLEAN ForceFlush)
6796 NTSTATUS ntStatus = STATUS_SUCCESS;
6797 AFSDeviceExt *pRDRDeviceExt = NULL, *pControlDeviceExt = NULL;
6798 LARGE_INTEGER liTime;
6799 IO_STATUS_BLOCK stIoStatus;
6804 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
6806 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
6808 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
6811 if( !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) &&
6812 !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
6815 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
6816 AFS_TRACE_LEVEL_VERBOSE,
6817 "AFSCleanupEntry Acquiring Fcb lock %p SHARED %08lX\n",
6818 &Fcb->NPFcb->Resource,
6819 PsGetCurrentThread()));
6821 AFSAcquireShared( &Fcb->NPFcb->Resource,
6824 if( Fcb->OpenReferenceCount > 0)
6827 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
6828 AFS_TRACE_LEVEL_VERBOSE,
6829 "AFSCleanupEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
6830 &Fcb->NPFcb->SectionObjectResource,
6831 PsGetCurrentThread()));
6833 AFSAcquireExcl( &Fcb->NPFcb->SectionObjectResource,
6839 CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
6844 if( !NT_SUCCESS( stIoStatus.Status))
6847 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
6848 AFS_TRACE_LEVEL_ERROR,
6849 "AFSCleanupFcb CcFlushCache [1] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
6850 Fcb->ObjectInformation->FileId.Cell,
6851 Fcb->ObjectInformation->FileId.Volume,
6852 Fcb->ObjectInformation->FileId.Vnode,
6853 Fcb->ObjectInformation->FileId.Unique,
6855 stIoStatus.Information));
6857 ntStatus = stIoStatus.Status;
6860 if ( Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
6863 if ( !CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
6869 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
6870 AFS_TRACE_LEVEL_WARNING,
6871 "AFSCleanupFcb CcPurgeCacheSection [1] failure FID %08lX-%08lX-%08lX-%08lX\n",
6872 Fcb->ObjectInformation->FileId.Cell,
6873 Fcb->ObjectInformation->FileId.Volume,
6874 Fcb->ObjectInformation->FileId.Vnode,
6875 Fcb->ObjectInformation->FileId.Unique));
6877 SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
6881 __except( EXCEPTION_EXECUTE_HANDLER)
6884 ntStatus = GetExceptionCode();
6888 "EXCEPTION - AFSCleanupFcb Cc [1] FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
6889 Fcb->ObjectInformation->FileId.Cell,
6890 Fcb->ObjectInformation->FileId.Volume,
6891 Fcb->ObjectInformation->FileId.Vnode,
6892 Fcb->ObjectInformation->FileId.Unique,
6895 SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
6898 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
6899 AFS_TRACE_LEVEL_VERBOSE,
6900 "AFSCleanupFcb Releasing Fcb SectionObject lock %p EXCL %08lX\n",
6901 &Fcb->NPFcb->SectionObjectResource,
6902 PsGetCurrentThread()));
6904 AFSReleaseResource( &Fcb->NPFcb->SectionObjectResource);
6907 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
6908 AFS_TRACE_LEVEL_VERBOSE,
6909 "AFSCleanupEntry Releasing Fcb lock %p SHARED %08lX\n",
6910 &Fcb->NPFcb->Resource,
6911 PsGetCurrentThread()));
6913 AFSReleaseResource( &Fcb->NPFcb->Resource);
6916 // Wait for any currently running flush or release requests to complete
6919 AFSWaitOnQueuedFlushes( Fcb);
6922 // Now perform another flush on the file
6925 if( !NT_SUCCESS( AFSFlushExtents( Fcb,
6929 AFSReleaseExtentsWithFlush( Fcb,
6935 if( Fcb->OpenReferenceCount == 0 ||
6936 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
6937 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
6940 AFSTearDownFcbExtents( Fcb,
6944 try_return( ntStatus);
6947 KeQueryTickCount( &liTime);
6950 // First up are there dirty extents in the cache to flush?
6953 if( BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
6954 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
6958 // The file has been marked as invalid. Dump it
6961 AFSTearDownFcbExtents( Fcb,
6964 else if( ForceFlush ||
6965 ( ( Fcb->Specific.File.ExtentsDirtyCount ||
6966 Fcb->Specific.File.ExtentCount) &&
6967 (liTime.QuadPart - Fcb->Specific.File.LastServerFlush.QuadPart)
6968 >= pControlDeviceExt->Specific.Control.FcbFlushTimeCount.QuadPart))
6970 if( !NT_SUCCESS( AFSFlushExtents( Fcb,
6972 Fcb->OpenReferenceCount == 0)
6975 AFSReleaseExtentsWithFlush( Fcb,
6982 // If there are extents and they haven't been used recently *and*
6983 // are not being used
6987 ( 0 != Fcb->Specific.File.ExtentCount &&
6988 0 != Fcb->Specific.File.LastExtentAccess.QuadPart &&
6989 (liTime.QuadPart - Fcb->Specific.File.LastExtentAccess.QuadPart) >=
6990 (AFS_SERVER_PURGE_SLEEP * pControlDeviceExt->Specific.Control.FcbPurgeTimeCount.QuadPart))))
6993 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
6994 AFS_TRACE_LEVEL_VERBOSE,
6995 "AFSCleanupFcb Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
6996 &Fcb->NPFcb->SectionObjectResource,
6997 PsGetCurrentThread()));
6999 if ( AFSAcquireExcl( &Fcb->NPFcb->SectionObjectResource, ForceFlush))
7005 CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
7010 if( !NT_SUCCESS( stIoStatus.Status))
7013 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
7014 AFS_TRACE_LEVEL_ERROR,
7015 "AFSCleanupFcb CcFlushCache [2] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
7016 Fcb->ObjectInformation->FileId.Cell,
7017 Fcb->ObjectInformation->FileId.Volume,
7018 Fcb->ObjectInformation->FileId.Vnode,
7019 Fcb->ObjectInformation->FileId.Unique,
7021 stIoStatus.Information));
7023 ntStatus = stIoStatus.Status;
7027 Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
7030 if ( !CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
7036 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
7037 AFS_TRACE_LEVEL_WARNING,
7038 "AFSCleanupFcb CcPurgeCacheSection [2] failure FID %08lX-%08lX-%08lX-%08lX\n",
7039 Fcb->ObjectInformation->FileId.Cell,
7040 Fcb->ObjectInformation->FileId.Volume,
7041 Fcb->ObjectInformation->FileId.Vnode,
7042 Fcb->ObjectInformation->FileId.Unique));
7044 SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
7048 __except( EXCEPTION_EXECUTE_HANDLER)
7051 ntStatus = GetExceptionCode();
7055 "EXCEPTION - AFSCleanupFcb Cc [2] FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
7056 Fcb->ObjectInformation->FileId.Cell,
7057 Fcb->ObjectInformation->FileId.Volume,
7058 Fcb->ObjectInformation->FileId.Vnode,
7059 Fcb->ObjectInformation->FileId.Unique,
7063 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
7064 AFS_TRACE_LEVEL_VERBOSE,
7065 "AFSCleanupFcb Releasing Fcb SectionObject lock %p EXCL %08lX\n",
7066 &Fcb->NPFcb->SectionObjectResource,
7067 PsGetCurrentThread()));
7069 AFSReleaseResource( &Fcb->NPFcb->SectionObjectResource);
7071 if( Fcb->OpenReferenceCount <= 0)
7075 // Tear em down we'll not be needing them again
7078 AFSTearDownFcbExtents( Fcb,
7085 ntStatus = STATUS_RETRY;
7098 AFSUpdateDirEntryName( IN AFSDirectoryCB *DirectoryCB,
7099 IN UNICODE_STRING *NewFileName)
7102 NTSTATUS ntStatus = STATUS_SUCCESS;
7103 WCHAR *pTmpBuffer = NULL;
7108 if( NewFileName->Length > DirectoryCB->NameInformation.FileName.Length)
7111 if( BooleanFlagOn( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
7114 AFSExFreePoolWithTag( DirectoryCB->NameInformation.FileName.Buffer, 0);
7116 ClearFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
7118 DirectoryCB->NameInformation.FileName.Buffer = NULL;
7122 // OK, we need to allocate a new name buffer
7125 pTmpBuffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
7126 NewFileName->Length,
7127 AFS_NAME_BUFFER_NINE_TAG);
7129 if( pTmpBuffer == NULL)
7132 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7135 DirectoryCB->NameInformation.FileName.Buffer = pTmpBuffer;
7137 DirectoryCB->NameInformation.FileName.MaximumLength = NewFileName->Length;
7139 SetFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
7142 DirectoryCB->NameInformation.FileName.Length = NewFileName->Length;
7144 RtlCopyMemory( DirectoryCB->NameInformation.FileName.Buffer,
7145 NewFileName->Buffer,
7146 NewFileName->Length);
7157 AFSReadCacheFile( IN void *ReadBuffer,
7158 IN LARGE_INTEGER *ReadOffset,
7159 IN ULONG RequestedDataLength,
7160 IN OUT PULONG BytesRead)
7163 NTSTATUS ntStatus = STATUS_SUCCESS;
7166 PIO_STACK_LOCATION pIoStackLocation = NULL;
7167 DEVICE_OBJECT *pTargetDeviceObject = NULL;
7168 FILE_OBJECT *pCacheFileObject = NULL;
7173 pCacheFileObject = AFSReferenceCacheFileObject();
7175 if( pCacheFileObject == NULL)
7177 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
7180 pTargetDeviceObject = IoGetRelatedDeviceObject( pCacheFileObject);
7183 // Initialize the event
7186 KeInitializeEvent( &kEvent,
7187 SynchronizationEvent,
7191 // Allocate an irp for this request. This could also come from a
7192 // private pool, for instance.
7195 pIrp = IoAllocateIrp( pTargetDeviceObject->StackSize,
7201 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7205 // Build the IRP's main body
7208 pIrp->UserBuffer = ReadBuffer;
7210 pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
7211 pIrp->RequestorMode = KernelMode;
7212 pIrp->Flags |= IRP_READ_OPERATION;
7215 // Set up the I/O stack location.
7218 pIoStackLocation = IoGetNextIrpStackLocation( pIrp);
7219 pIoStackLocation->MajorFunction = IRP_MJ_READ;
7220 pIoStackLocation->DeviceObject = pTargetDeviceObject;
7221 pIoStackLocation->FileObject = pCacheFileObject;
7222 pIoStackLocation->Parameters.Read.Length = RequestedDataLength;
7224 pIoStackLocation->Parameters.Read.ByteOffset.QuadPart = ReadOffset->QuadPart;
7227 // Set the completion routine.
7230 IoSetCompletionRoutine( pIrp,
7238 // Send it to the FSD
7241 ntStatus = IoCallDriver( pTargetDeviceObject,
7244 if( NT_SUCCESS( ntStatus))
7251 ntStatus = KeWaitForSingleObject( &kEvent,
7257 if( NT_SUCCESS( ntStatus))
7260 ntStatus = pIrp->IoStatus.Status;
7262 *BytesRead = (ULONG)pIrp->IoStatus.Information;
7268 if( pCacheFileObject != NULL)
7270 AFSReleaseCacheFileObject( pCacheFileObject);
7276 if( pIrp->MdlAddress != NULL)
7279 if( FlagOn( pIrp->MdlAddress->MdlFlags, MDL_PAGES_LOCKED))
7282 MmUnlockPages( pIrp->MdlAddress);
7285 IoFreeMdl( pIrp->MdlAddress);
7288 pIrp->MdlAddress = NULL;
7302 AFSIrpComplete( IN PDEVICE_OBJECT DeviceObject,
7307 UNREFERENCED_PARAMETER(Irp);
7308 UNREFERENCED_PARAMETER(DeviceObject);
7309 KEVENT *pEvent = (KEVENT *)Context;
7315 return STATUS_MORE_PROCESSING_REQUIRED;
7319 AFSIsDirectoryEmptyForDelete( IN AFSFcb *Fcb)
7322 BOOLEAN bIsEmpty = FALSE;
7323 AFSDirectoryCB *pDirEntry = NULL;
7328 ASSERT( Fcb->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY);
7330 AFSAcquireShared( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
7335 if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
7338 pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
7340 while( pDirEntry != NULL)
7343 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
7344 !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
7352 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
7357 AFSReleaseResource( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
7364 AFSRemoveNameEntry( IN AFSObjectInfoCB *ParentObjectInfo,
7365 IN AFSDirectoryCB *DirEntry)
7368 NTSTATUS ntStatus = STATUS_SUCCESS;
7373 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7376 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7377 AFS_TRACE_LEVEL_VERBOSE,
7378 "AFSRemoveNameEntry DE %p for %wZ has NOT_IN flag set\n",
7380 &DirEntry->NameInformation.FileName));
7382 try_return( ntStatus);
7385 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
7388 // Remove the entry from the parent tree
7391 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7392 AFS_TRACE_LEVEL_VERBOSE,
7393 "AFSRemoveNameEntry DE %p for %wZ removing from case sensitive tree\n",
7395 &DirEntry->NameInformation.FileName));
7397 AFSRemoveCaseSensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7400 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7401 AFS_TRACE_LEVEL_VERBOSE,
7402 "AFSRemoveNameEntry DE %p for %wZ removing from case insensitive tree\n",
7404 &DirEntry->NameInformation.FileName));
7406 AFSRemoveCaseInsensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
7409 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
7413 // From the short name tree
7416 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7417 AFS_TRACE_LEVEL_VERBOSE,
7418 "AFSRemoveNameEntry DE %p for %wZ removing from shortname tree\n",
7420 &DirEntry->NameInformation.FileName));
7422 AFSRemoveShortNameDirEntry( &ParentObjectInfo->Specific.Directory.ShortNameTree,
7425 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
7428 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7429 AFS_TRACE_LEVEL_VERBOSE,
7430 "AFSRemoveNameEntry DE %p for %wZ setting NOT_IN flag\n",
7432 &DirEntry->NameInformation.FileName));
7434 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
7436 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
7447 AFSGetAuthenticationId()
7450 LARGE_INTEGER liAuthId = {0,0};
7451 NTSTATUS ntStatus = STATUS_SUCCESS;
7452 PACCESS_TOKEN hToken = NULL;
7453 PTOKEN_STATISTICS pTokenInfo = NULL;
7454 BOOLEAN bCopyOnOpen = FALSE;
7455 BOOLEAN bEffectiveOnly = FALSE;
7456 BOOLEAN bPrimaryToken = FALSE;
7457 SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
7462 hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
7465 &stImpersonationLevel);
7470 hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
7475 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7476 AFS_TRACE_LEVEL_ERROR,
7477 "AFSGetAuthenticationId Failed to retrieve impersonation or primary token\n"));
7479 try_return( ntStatus);
7482 bPrimaryToken = TRUE;
7485 ntStatus = SeQueryInformationToken( hToken,
7487 (PVOID *)&pTokenInfo);
7489 if( !NT_SUCCESS( ntStatus))
7492 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7493 AFS_TRACE_LEVEL_ERROR,
7494 "AFSGetAuthenticationId Failed to retrieve information Status %08lX\n",
7497 try_return( ntStatus);
7500 liAuthId.HighPart = pTokenInfo->AuthenticationId.HighPart;
7501 liAuthId.LowPart = pTokenInfo->AuthenticationId.LowPart;
7503 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7504 AFS_TRACE_LEVEL_VERBOSE,
7505 "AFSGetAuthenticationId Successfully retrieved authentication ID %I64X\n",
7506 liAuthId.QuadPart));
7516 PsDereferenceImpersonationToken( hToken);
7521 PsDereferencePrimaryToken( hToken);
7525 if( pTokenInfo != NULL)
7528 ExFreePool( pTokenInfo); // Allocated by SeQueryInformationToken
7536 AFSUnwindFileInfo( IN AFSFcb *Fcb,
7540 UNREFERENCED_PARAMETER(Fcb);
7541 if( Ccb->FileUnwindInfo.FileAttributes != (ULONG)-1)
7543 Fcb->ObjectInformation->FileAttributes = Ccb->FileUnwindInfo.FileAttributes;
7546 if( Ccb->FileUnwindInfo.CreationTime.QuadPart != (ULONGLONG)-1)
7548 Fcb->ObjectInformation->CreationTime.QuadPart = Ccb->FileUnwindInfo.CreationTime.QuadPart;
7551 if( Ccb->FileUnwindInfo.LastAccessTime.QuadPart != (ULONGLONG)-1)
7553 Fcb->ObjectInformation->LastAccessTime.QuadPart = Ccb->FileUnwindInfo.LastAccessTime.QuadPart;
7556 if( Ccb->FileUnwindInfo.LastWriteTime.QuadPart != (ULONGLONG)-1)
7558 Fcb->ObjectInformation->LastWriteTime.QuadPart = Ccb->FileUnwindInfo.LastWriteTime.QuadPart;
7561 if( Ccb->FileUnwindInfo.ChangeTime.QuadPart != (ULONGLONG)-1)
7563 Fcb->ObjectInformation->ChangeTime.QuadPart = Ccb->FileUnwindInfo.ChangeTime.QuadPart;
7570 AFSValidateDirList( IN AFSObjectInfoCB *ObjectInfo)
7573 BOOLEAN bIsValid = TRUE;
7575 AFSDirectoryCB *pCurrentDirEntry = NULL, *pDirEntry = NULL;
7577 pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
7579 while( pCurrentDirEntry != NULL)
7582 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
7586 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7591 AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7592 (ULONG)pCurrentDirEntry->CaseSensitiveTreeEntry.HashIndex,
7595 if( pDirEntry == NULL)
7602 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
7605 if( ulCount != (ULONG) ObjectInfo->Specific.Directory.DirectoryNodeCount)
7608 AFSPrint("AFSValidateDirList Count off Calc: %d Stored: %d\n",
7610 ObjectInfo->Specific.Directory.DirectoryNodeCount);
7612 ObjectInfo->Specific.Directory.DirectoryNodeCount = ulCount;
7621 AFSReferenceCacheFileObject()
7624 AFSDeviceExt *pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
7625 FILE_OBJECT *pCacheFileObject = NULL;
7627 AFSAcquireShared( &pRdrDevExt->Specific.RDR.CacheFileLock,
7630 pCacheFileObject = pRdrDevExt->Specific.RDR.CacheFileObject;
7632 if( pCacheFileObject != NULL)
7634 ObReferenceObject( pCacheFileObject);
7637 AFSReleaseResource( &pRdrDevExt->Specific.RDR.CacheFileLock);
7639 return pCacheFileObject;
7643 AFSReleaseCacheFileObject( IN PFILE_OBJECT CacheFileObject)
7646 ASSERT( CacheFileObject != NULL);
7648 ObDereferenceObject( CacheFileObject);
7654 AFSInitializeLibrary( IN AFSLibraryInitCB *LibraryInit)
7657 NTSTATUS ntStatus = STATUS_SUCCESS;
7658 AFSDeviceExt *pControlDevExt = NULL;
7659 ULONG ulTimeIncrement = 0;
7665 AFSControlDeviceObject = LibraryInit->AFSControlDeviceObject;
7667 AFSRDRDeviceObject = LibraryInit->AFSRDRDeviceObject;
7669 AFSServerName = LibraryInit->AFSServerName;
7671 AFSMountRootName = LibraryInit->AFSMountRootName;
7673 AFSDebugFlags = LibraryInit->AFSDebugFlags;
7676 // Callbacks in the framework
7679 AFSProcessRequest = LibraryInit->AFSProcessRequest;
7681 AFSDbgLogMsg = LibraryInit->AFSDbgLogMsg;
7683 AFSDebugTraceFnc = AFSDbgLogMsg;
7685 AFSAddConnectionEx = LibraryInit->AFSAddConnectionEx;
7687 AFSExAllocatePoolWithTag = LibraryInit->AFSExAllocatePoolWithTag;
7689 AFSExFreePoolWithTag = LibraryInit->AFSExFreePoolWithTag;
7691 AFSDumpTraceFilesFnc = LibraryInit->AFSDumpTraceFiles;
7693 AFSRetrieveAuthGroupFnc = LibraryInit->AFSRetrieveAuthGroup;
7695 AFSLibCacheManagerCallbacks = LibraryInit->AFSCacheManagerCallbacks;
7697 if( LibraryInit->AFSCacheBaseAddress != NULL)
7700 SetFlag( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE);
7702 AFSLibCacheBaseAddress = LibraryInit->AFSCacheBaseAddress;
7704 AFSLibCacheLength = LibraryInit->AFSCacheLength;
7708 // Initialize some flush parameters
7711 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
7713 ulTimeIncrement = KeQueryTimeIncrement();
7715 pControlDevExt->Specific.Control.ObjectLifeTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_OBJECT_LIFETIME / (ULONGLONG)ulTimeIncrement);
7716 pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart = AFS_SERVER_PURGE_DELAY;
7717 pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart /= ulTimeIncrement;
7718 pControlDevExt->Specific.Control.FcbFlushTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_SERVER_FLUSH_DELAY / (ULONGLONG)ulTimeIncrement);
7719 pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_EXTENT_REQUEST_TIME/(ULONGLONG)ulTimeIncrement);
7722 // Initialize the global root entry
7725 ntStatus = AFSInitVolume( NULL,
7726 &LibraryInit->GlobalRootFid,
7727 AFS_VOLUME_REFERENCE_GLOBAL_ROOT,
7730 if( !NT_SUCCESS( ntStatus))
7733 AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
7734 AFS_TRACE_LEVEL_ERROR,
7735 "AFSInitializeLibrary AFSInitVolume failure %08lX\n",
7738 try_return( ntStatus);
7741 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
7744 if( !NT_SUCCESS( ntStatus))
7747 AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
7748 AFS_TRACE_LEVEL_ERROR,
7749 "AFSInitializeLibrary AFSInitRootFcb failure %08lX\n",
7752 lCount = AFSVolumeDecrement( AFSGlobalRoot,
7753 AFS_VOLUME_REFERENCE_GLOBAL_ROOT);
7755 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7756 AFS_TRACE_LEVEL_VERBOSE,
7757 "AFSInitializeLibrary Decrement count on volume %p Cnt %d\n",
7761 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
7763 try_return( ntStatus);
7767 // Update the node type code to AFS_ROOT_ALL
7770 AFSGlobalRoot->ObjectInformation.Fcb->Header.NodeTypeCode = AFS_ROOT_ALL;
7772 SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_ACTIVE_GLOBAL_ROOT);
7775 // Invalidate all known volumes since contact with the service and therefore
7776 // the file server was lost.
7779 AFSInvalidateAllVolumes();
7782 // Drop the locks acquired above
7785 AFSInitVolumeWorker( AFSGlobalRoot);
7787 lCount = AFSVolumeDecrement( AFSGlobalRoot,
7788 AFS_VOLUME_REFERENCE_GLOBAL_ROOT);
7790 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7791 AFS_TRACE_LEVEL_VERBOSE,
7792 "AFSInitializeLibrary Decrement count on volume %p Cnt %d\n",
7796 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
7798 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Fcb->Header.Resource);
7812 NTSTATUS ntStatus = STATUS_SUCCESS;
7813 AFSDirectoryCB *pDirNode = NULL, *pLastDirNode = NULL;
7819 if( AFSGlobalDotDirEntry != NULL)
7822 lCount = AFSObjectInfoDecrement( AFSGlobalDotDirEntry->ObjectInformation,
7823 AFS_OBJECT_REFERENCE_GLOBAL);
7825 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
7826 AFS_TRACE_LEVEL_VERBOSE,
7827 "AFSCloseLibrary Decrement count on parent object %p Cnt %d\n",
7828 AFSGlobalDotDirEntry->ObjectInformation,
7834 AFSDeleteObjectInfo( &AFSGlobalDotDirEntry->ObjectInformation);
7837 ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
7839 ExFreePool( AFSGlobalDotDirEntry->NonPaged);
7841 ExFreePool( AFSGlobalDotDirEntry);
7843 AFSGlobalDotDirEntry = NULL;
7846 if( AFSGlobalDotDotDirEntry != NULL)
7849 lCount = AFSObjectInfoDecrement( AFSGlobalDotDotDirEntry->ObjectInformation,
7850 AFS_OBJECT_REFERENCE_GLOBAL);
7852 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
7853 AFS_TRACE_LEVEL_VERBOSE,
7854 "AFSCloseLibrary Decrement count on parent object %p Cnt %d\n",
7855 AFSGlobalDotDotDirEntry->ObjectInformation,
7861 AFSDeleteObjectInfo( &AFSGlobalDotDotDirEntry->ObjectInformation);
7864 ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
7866 ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
7868 ExFreePool( AFSGlobalDotDotDirEntry);
7870 AFSGlobalDotDotDirEntry = NULL;
7873 if( AFSSpecialShareNames != NULL)
7876 pDirNode = AFSSpecialShareNames;
7878 while( pDirNode != NULL)
7881 pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
7883 lCount = AFSObjectInfoDecrement( pDirNode->ObjectInformation,
7884 AFS_OBJECT_REFERENCE_GLOBAL);
7886 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
7887 AFS_TRACE_LEVEL_VERBOSE,
7888 "AFSCloseLibrary Decrement count on parent object %p Cnt %d\n",
7889 pDirNode->ObjectInformation,
7895 AFSDeleteObjectInfo( &pDirNode->ObjectInformation);
7898 ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
7900 ExFreePool( pDirNode->NonPaged);
7902 ExFreePool( pDirNode);
7904 pDirNode = pLastDirNode;
7907 AFSSpecialShareNames = NULL;
7915 AFSDefaultLogMsg( IN ULONG Subsystem,
7921 UNREFERENCED_PARAMETER(Subsystem);
7922 UNREFERENCED_PARAMETER(Level);
7923 NTSTATUS ntStatus = STATUS_SUCCESS;
7925 char chDebugBuffer[ 256];
7930 va_start( va_args, Format);
7932 ntStatus = RtlStringCbVPrintfA( chDebugBuffer,
7937 if( NT_SUCCESS( ntStatus))
7939 DbgPrint( chDebugBuffer);
7949 AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
7950 IN ULONG InputBufferLength,
7951 IN AFSStatusInfoCB *StatusInfo,
7952 OUT ULONG *ReturnLength)
7955 NTSTATUS ntStatus = STATUS_SUCCESS;
7956 AFSVolumeCB *pVolumeCB = NULL;
7957 LONG VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
7958 AFSVolumeCB *pNewVolumeCB = NULL;
7959 LONG NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
7960 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
7961 AFSObjectInfoCB *pObjectInfo = NULL;
7962 ULONGLONG ullIndex = 0;
7963 UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName, uniParsedName;
7964 AFSNameArrayHdr *pNameArray = NULL;
7965 AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
7966 AFSDirectoryCB *pNewParentDirEntry = NULL;
7973 // If we are given a FID then look up the entry by that, otherwise
7977 if( GetStatusInfo->FileID.Cell != 0 &&
7978 GetStatusInfo->FileID.Volume != 0 &&
7979 GetStatusInfo->FileID.Vnode != 0 &&
7980 GetStatusInfo->FileID.Unique != 0)
7983 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
7986 // Locate the volume node
7989 ullIndex = AFSCreateHighIndex( &GetStatusInfo->FileID);
7991 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
7993 (AFSBTreeEntry **)&pVolumeCB);
7995 if( pVolumeCB != NULL)
7998 VolumeReferenceReason = AFS_VOLUME_REFERENCE_GET_OBJECT;
8000 lCount = AFSVolumeIncrement( pVolumeCB,
8001 VolumeReferenceReason);
8003 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8004 AFS_TRACE_LEVEL_VERBOSE,
8005 "AFSGetObjectStatus Increment count on volume %p Reason %u Cnt %d\n",
8007 VolumeReferenceReason,
8011 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
8013 if( !NT_SUCCESS( ntStatus) ||
8016 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8019 if( AFSIsVolumeFID( &GetStatusInfo->FileID))
8022 pObjectInfo = &pVolumeCB->ObjectInformation;
8024 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
8027 lCount = AFSObjectInfoIncrement( pObjectInfo,
8028 AFS_OBJECT_REFERENCE_STATUS);
8030 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8031 AFS_TRACE_LEVEL_VERBOSE,
8032 "AFSGetObjectStatus Increment1 count on object %p Cnt %d\n",
8036 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
8041 AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
8044 ullIndex = AFSCreateLowIndex( &GetStatusInfo->FileID);
8046 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
8048 (AFSBTreeEntry **)&pObjectInfo);
8050 if( pObjectInfo != NULL)
8054 // Reference the node so it won't be torn down
8057 lCount = AFSObjectInfoIncrement( pObjectInfo,
8058 AFS_OBJECT_REFERENCE_STATUS);
8060 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8061 AFS_TRACE_LEVEL_VERBOSE,
8062 "AFSGetObjectStatus Increment2 count on object %p Cnt %d\n",
8066 KeQueryTickCount( &pObjectInfo->LastAccessCount);
8069 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
8071 if( !NT_SUCCESS( ntStatus) ||
8072 pObjectInfo == NULL)
8074 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8081 if( GetStatusInfo->FileNameLength == 0 ||
8082 InputBufferLength < (ULONG)(FIELD_OFFSET( AFSGetStatusInfoCB, FileName) + GetStatusInfo->FileNameLength))
8084 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8087 uniFullPathName.Length = GetStatusInfo->FileNameLength;
8088 uniFullPathName.MaximumLength = uniFullPathName.Length;
8090 uniFullPathName.Buffer = (WCHAR *)GetStatusInfo->FileName;
8093 // This name should begin with the \afs server so parse it off and check it
8096 FsRtlDissectName( uniFullPathName,
8100 if( RtlCompareUnicodeString( &uniComponentName,
8104 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8105 AFS_TRACE_LEVEL_ERROR,
8106 "AFSGetObjectStatus Name %wZ contains invalid server name\n",
8109 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
8112 uniFullPathName = uniRemainingPath;
8114 uniParsedName = uniFullPathName;
8120 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
8123 if( pNameArray == NULL)
8125 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8128 pVolumeCB = AFSGlobalRoot;
8130 pParentDirEntry = AFSGlobalRoot->DirectoryCB;
8133 // Increment the ref count on the volume and dir entry for correct processing below
8136 VolumeReferenceReason = AFS_VOLUME_REFERENCE_GET_OBJECT;
8138 lCount = AFSVolumeIncrement( pVolumeCB,
8139 VolumeReferenceReason);
8141 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8142 AFS_TRACE_LEVEL_VERBOSE,
8143 "AFSGetObjectStatus Increment2 count on volume %p Reason %u Cnt %d\n",
8145 VolumeReferenceReason,
8148 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
8150 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8151 AFS_TRACE_LEVEL_VERBOSE,
8152 "AFSGetObjectStatus Increment count on %wZ DE %p Ccb %p Cnt %d\n",
8153 &pParentDirEntry->NameInformation.FileName,
8158 ntStatus = AFSLocateNameEntry( NULL,
8163 AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL |
8164 AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL,
8168 &NewVolumeReferenceReason,
8169 &pNewParentDirEntry,
8173 if ( pNewVolumeCB != NULL)
8177 // AFSLocateNameEntry returns pNewVolumeCB with a reference held
8178 // even if pVolumeCB == pNewVolumeCB. It is always safe to release
8179 // the reference on pVolumeCB that was held prior to the call.
8180 // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
8181 // will be released second.
8184 lCount = AFSVolumeDecrement( pVolumeCB,
8185 VolumeReferenceReason);
8187 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8188 AFS_TRACE_LEVEL_VERBOSE,
8189 "AFSGetObjectStatus Decrement count on volume %p Reason %u Cnt %d\n",
8191 VolumeReferenceReason,
8194 pVolumeCB = pNewVolumeCB;
8196 pNewVolumeCB = NULL;
8198 VolumeReferenceReason = NewVolumeReferenceReason;
8200 NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
8204 // AFSLocateNameEntry does not alter the reference count of
8205 // pParentDirectoryCB and it returns pNewParentDirectoryCB with
8206 // a reference held.
8209 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
8211 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8212 AFS_TRACE_LEVEL_VERBOSE,
8213 "AFSGetObjectStatus DecrementX count on %wZ DE %p Cnt %d\n",
8214 &pParentDirEntry->NameInformation.FileName,
8218 pParentDirEntry = pNewParentDirEntry;
8220 pNewParentDirEntry = NULL;
8222 if( !NT_SUCCESS( ntStatus) ||
8223 ntStatus == STATUS_REPARSE)
8228 try_return( ntStatus);
8231 pObjectInfo = pDirectoryEntry->ObjectInformation;
8233 AFSAcquireExcl( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
8236 lCount = AFSObjectInfoIncrement( pObjectInfo,
8237 AFS_OBJECT_REFERENCE_STATUS);
8239 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8240 AFS_TRACE_LEVEL_VERBOSE,
8241 "AFSGetObjectStatus Increment3 count on object %p Cnt %d\n",
8245 AFSReleaseResource( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
8249 // At this point we have an object info block, return the information
8252 StatusInfo->FileId = pObjectInfo->FileId;
8254 StatusInfo->TargetFileId = pObjectInfo->TargetFileId;
8256 StatusInfo->Expiration = pObjectInfo->Expiration;
8258 StatusInfo->DataVersion = pObjectInfo->DataVersion;
8260 StatusInfo->FileType = pObjectInfo->FileType;
8262 StatusInfo->ObjectFlags = pObjectInfo->Flags;
8264 StatusInfo->CreationTime = pObjectInfo->CreationTime;
8266 StatusInfo->LastAccessTime = pObjectInfo->LastAccessTime;
8268 StatusInfo->LastWriteTime = pObjectInfo->LastWriteTime;
8270 StatusInfo->ChangeTime = pObjectInfo->ChangeTime;
8272 StatusInfo->FileAttributes = pObjectInfo->FileAttributes;
8274 StatusInfo->EndOfFile = pObjectInfo->EndOfFile;
8276 StatusInfo->AllocationSize = pObjectInfo->AllocationSize;
8278 StatusInfo->EaSize = pObjectInfo->EaSize;
8280 StatusInfo->Links = pObjectInfo->Links;
8283 // Return the information length
8286 *ReturnLength = sizeof( AFSStatusInfoCB);
8290 if( pDirectoryEntry != NULL)
8293 lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
8295 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8296 AFS_TRACE_LEVEL_VERBOSE,
8297 "AFSGetObjectStatus Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
8298 &pDirectoryEntry->NameInformation.FileName,
8303 ASSERT( lCount >= 0);
8306 if ( pParentDirEntry != NULL)
8309 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
8311 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8312 AFS_TRACE_LEVEL_VERBOSE,
8313 "AFSGetObjectStatus Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
8314 &pParentDirEntry->NameInformation.FileName,
8319 ASSERT( lCount >= 0);
8322 if( pVolumeCB != NULL)
8325 if( pObjectInfo != NULL)
8328 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
8331 lCount = AFSObjectInfoDecrement( pObjectInfo,
8332 AFS_OBJECT_REFERENCE_STATUS);
8334 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8335 AFS_TRACE_LEVEL_VERBOSE,
8336 "AFSGetObjectStatus Decrement count on object %p Cnt %d\n",
8340 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
8343 lCount = AFSVolumeDecrement( pVolumeCB,
8344 VolumeReferenceReason);
8346 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8347 AFS_TRACE_LEVEL_VERBOSE,
8348 "AFSGetObjectStatus Decrement4 count on volume %p Reason %u Cnt %d\n",
8350 VolumeReferenceReason,
8354 if( pNameArray != NULL)
8357 AFSFreeNameArray( pNameArray);
8365 AFSCheckSymlinkAccess( IN AFSDirectoryCB *ParentDirectoryCB,
8366 IN UNICODE_STRING *ComponentName)
8369 NTSTATUS ntStatus = STATUS_SUCCESS;
8370 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
8371 AFSDirectoryCB *pDirEntry = NULL;
8379 // Search for the entry in the parent
8382 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8383 AFS_TRACE_LEVEL_VERBOSE_2,
8384 "AFSCheckSymlinkAccess Searching for entry %wZ case sensitive\n",
8387 ulCRC = AFSGenerateCRC( ComponentName,
8390 AFSAcquireShared( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
8393 AFSLocateCaseSensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
8397 if( pDirEntry == NULL)
8401 // Missed so perform a case insensitive lookup
8404 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8405 AFS_TRACE_LEVEL_VERBOSE_2,
8406 "AFSCheckSymlinkAccess Searching for entry %wZ case insensitive\n",
8409 ulCRC = AFSGenerateCRC( ComponentName,
8412 AFSLocateCaseInsensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
8416 if( pDirEntry == NULL)
8420 // OK, if this component is a valid short name then try
8421 // a lookup in the short name tree
8424 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
8425 RtlIsNameLegalDOS8Dot3( ComponentName,
8430 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8431 AFS_TRACE_LEVEL_VERBOSE_2,
8432 "AFSCheckSymlinkAccess Searching for entry %wZ short name\n",
8435 AFSLocateShortNameDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.ShortNameTree,
8442 if( pDirEntry != NULL)
8444 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
8446 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8447 AFS_TRACE_LEVEL_VERBOSE,
8448 "AFSCheckSymlinkAccess Increment count on %wZ DE %p Ccb %p Cnt %d\n",
8449 &pDirEntry->NameInformation.FileName,
8454 ASSERT( lCount >= 0);
8457 AFSReleaseResource( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
8459 if( pDirEntry == NULL)
8462 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8463 AFS_TRACE_LEVEL_VERBOSE_2,
8464 "AFSCheckSymlinkAccess Failed to locate entry %wZ ntStatus %08X\n",
8466 STATUS_OBJECT_NAME_NOT_FOUND));
8468 try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
8472 // We have the symlink object but previously failed to process it so return access
8476 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8477 AFS_TRACE_LEVEL_VERBOSE_2,
8478 "AFSCheckSymlinkAccess Failing symlink access to entry %wZ REPARSE_POINT_NOT_RESOLVED\n",
8481 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
8483 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
8485 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8486 AFS_TRACE_LEVEL_VERBOSE,
8487 "AFSCheckSymlinkAccess Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
8488 &pDirEntry->NameInformation.FileName,
8493 ASSERT( lCount >= 0);
8504 AFSRetrieveFinalComponent( IN UNICODE_STRING *FullPathName,
8505 OUT UNICODE_STRING *ComponentName)
8508 NTSTATUS ntStatus = STATUS_SUCCESS;
8509 UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName;
8511 uniFullPathName = *FullPathName;
8516 FsRtlDissectName( uniFullPathName,
8520 if( uniRemainingPath.Length == 0)
8525 uniFullPathName = uniRemainingPath;
8528 if( uniComponentName.Length > 0)
8530 *ComponentName = uniComponentName;
8537 AFSDumpTraceFiles_Default()
8543 AFSValidNameFormat( IN UNICODE_STRING *FileName)
8546 BOOLEAN bIsValidName = TRUE;
8552 while( usIndex < FileName->Length/sizeof( WCHAR))
8555 if( FileName->Buffer[ usIndex] == L':' ||
8556 FileName->Buffer[ usIndex] == L'*' ||
8557 FileName->Buffer[ usIndex] == L'?' ||
8558 FileName->Buffer[ usIndex] == L'"' ||
8559 FileName->Buffer[ usIndex] == L'<' ||
8560 FileName->Buffer[ usIndex] == L'>')
8562 bIsValidName = FALSE;
8570 return bIsValidName;
8574 AFSCreateDefaultSecurityDescriptor()
8577 NTSTATUS ntStatus = STATUS_SUCCESS;
8579 ULONG ulSACLSize = 0;
8580 SYSTEM_MANDATORY_LABEL_ACE* pACE = NULL;
8581 ULONG ulACESize = 0;
8582 SECURITY_DESCRIPTOR *pSecurityDescr = NULL;
8583 ULONG ulSDLength = 0;
8584 SECURITY_DESCRIPTOR *pRelativeSecurityDescr = NULL;
8585 PSID pWorldSID = NULL;
8586 ULONG *pulSubAuthority = NULL;
8587 ULONG ulWorldSIDLEngth = 0;
8592 ulWorldSIDLEngth = RtlLengthRequiredSid( 1);
8594 pWorldSID = (PSID)ExAllocatePoolWithTag( PagedPool,
8596 AFS_GENERIC_MEMORY_29_TAG);
8598 if( pWorldSID == NULL)
8600 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate World SID\n");
8602 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8605 RtlZeroMemory( pWorldSID,
8608 RtlInitializeSid( pWorldSID,
8609 &SeWorldSidAuthority,
8612 pulSubAuthority = RtlSubAuthoritySid(pWorldSID, 0);
8613 *pulSubAuthority = SECURITY_WORLD_RID;
8615 if( AFSRtlSetSaclSecurityDescriptor == NULL)
8618 AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor == NULL\n");
8623 ulACESize = sizeof( SYSTEM_MANDATORY_LABEL_ACE) + 128;
8625 pACE = (SYSTEM_MANDATORY_LABEL_ACE *)ExAllocatePoolWithTag( PagedPool,
8627 AFS_GENERIC_MEMORY_29_TAG);
8632 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8634 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8637 RtlZeroMemory( pACE,
8640 pACE->Header.AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
8641 pACE->Header.AceType = SYSTEM_MANDATORY_LABEL_ACE_TYPE;
8642 pACE->Header.AceSize = FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + (USHORT)RtlLengthSid( SeExports->SeLowMandatorySid);
8643 pACE->Mask = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP;
8645 RtlCopySid( RtlLengthSid( SeExports->SeLowMandatorySid),
8647 SeExports->SeLowMandatorySid);
8649 ulSACLSize = sizeof(ACL) + RtlLengthSid( SeExports->SeLowMandatorySid) +
8650 FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + ulACESize;
8652 pSACL = (PACL)ExAllocatePoolWithTag( PagedPool,
8654 AFS_GENERIC_MEMORY_29_TAG);
8659 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8661 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8664 ntStatus = RtlCreateAcl( pSACL,
8668 if( !NT_SUCCESS( ntStatus))
8671 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateAcl ntStatus %08lX\n",
8674 try_return( ntStatus);
8677 ntStatus = RtlAddAce( pSACL,
8681 pACE->Header.AceSize);
8683 if( !NT_SUCCESS( ntStatus))
8686 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAddAce ntStatus %08lX\n",
8689 try_return( ntStatus);
8693 pSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
8694 sizeof( SECURITY_DESCRIPTOR),
8695 AFS_GENERIC_MEMORY_27_TAG);
8697 if( pSecurityDescr == NULL)
8700 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8702 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8705 ntStatus = RtlCreateSecurityDescriptor( pSecurityDescr,
8706 SECURITY_DESCRIPTOR_REVISION);
8708 if( !NT_SUCCESS( ntStatus))
8711 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateSecurityDescriptor ntStatus %08lX\n",
8714 try_return( ntStatus);
8717 if( AFSRtlSetSaclSecurityDescriptor != NULL)
8719 ntStatus = AFSRtlSetSaclSecurityDescriptor( pSecurityDescr,
8724 if( !NT_SUCCESS( ntStatus))
8727 AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor ntStatus %08lX\n",
8730 try_return( ntStatus);
8735 // Add in the group and owner to the SD
8738 if( AFSRtlSetGroupSecurityDescriptor != NULL)
8740 ntStatus = AFSRtlSetGroupSecurityDescriptor( pSecurityDescr,
8744 if( !NT_SUCCESS( ntStatus))
8747 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetGroupSecurityDescriptor failed ntStatus %08lX\n",
8750 try_return( ntStatus);
8754 ntStatus = RtlSetOwnerSecurityDescriptor( pSecurityDescr,
8758 if( !NT_SUCCESS( ntStatus))
8761 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetOwnerSecurityDescriptor failed ntStatus %08lX\n",
8764 try_return( ntStatus);
8767 if( !RtlValidSecurityDescriptor( pSecurityDescr))
8770 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlValidSecurityDescriptor NOT\n");
8772 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8775 pRelativeSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
8777 AFS_GENERIC_MEMORY_27_TAG);
8779 if( pRelativeSecurityDescr == NULL)
8782 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8784 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8787 ulSDLength = PAGE_SIZE;
8789 ntStatus = RtlAbsoluteToSelfRelativeSD( pSecurityDescr,
8790 pRelativeSecurityDescr,
8793 if( !NT_SUCCESS( ntStatus))
8796 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAbsoluteToSelfRelativeSD ntStatus %08lX\n",
8799 try_return( ntStatus);
8802 AFSDefaultSD = pRelativeSecurityDescr;
8806 if( !NT_SUCCESS( ntStatus))
8809 if( pRelativeSecurityDescr != NULL)
8811 ExFreePool( pRelativeSecurityDescr);
8815 if( pSecurityDescr != NULL)
8817 ExFreePool( pSecurityDescr);
8830 if( pWorldSID != NULL)
8832 ExFreePool( pWorldSID);
8840 AFSRetrieveParentPath( IN UNICODE_STRING *FullFileName,
8841 OUT UNICODE_STRING *ParentPath)
8844 *ParentPath = *FullFileName;
8847 // If the final character is a \, jump over it
8850 if( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] == L'\\')
8852 ParentPath->Length -= sizeof( WCHAR);
8855 while( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] != L'\\')
8857 ParentPath->Length -= sizeof( WCHAR);
8861 // And the separator
8864 ParentPath->Length -= sizeof( WCHAR);
8870 AFSRetrieveValidAuthGroup( IN AFSFcb *Fcb,
8871 IN AFSObjectInfoCB *ObjectInfo,
8872 IN BOOLEAN WriteAccess,
8873 OUT GUID *AuthGroup)
8876 NTSTATUS ntStatus = STATUS_SUCCESS;
8877 GUID stAuthGroup, stZeroAuthGroup;
8878 BOOLEAN bFoundAuthGroup = FALSE;
8879 AFSCcb *pCcb = NULL;
8885 RtlZeroMemory( &stAuthGroup,
8888 RtlZeroMemory( &stZeroAuthGroup,
8894 if( ObjectInfo != NULL &&
8895 ObjectInfo->Fcb != NULL)
8897 pFcb = ObjectInfo->Fcb;
8904 AFSAcquireShared( &Fcb->NPFcb->CcbListLock,
8907 pCcb = Fcb->CcbListHead;
8909 while( pCcb != NULL)
8913 pCcb->GrantedAccess & FILE_WRITE_DATA)
8915 RtlCopyMemory( &stAuthGroup,
8919 bFoundAuthGroup = TRUE;
8923 else if( pCcb->GrantedAccess & FILE_READ_DATA)
8926 // At least get the read-only access
8929 RtlCopyMemory( &stAuthGroup,
8933 bFoundAuthGroup = TRUE;
8936 pCcb = (AFSCcb *)pCcb->ListEntry.fLink;
8939 AFSReleaseResource( &Fcb->NPFcb->CcbListLock);
8942 if( !bFoundAuthGroup)
8945 AFSRetrieveAuthGroupFnc( (ULONGLONG)PsGetCurrentProcessId(),
8946 (ULONGLONG)PsGetCurrentThreadId(),
8949 if( RtlCompareMemory( &stZeroAuthGroup,
8951 sizeof( GUID)) == sizeof( GUID))
8954 DbgPrint("AFSRetrieveValidAuthGroup Failed to locate PAG\n");
8956 try_return( ntStatus = STATUS_ACCESS_DENIED);
8960 RtlCopyMemory( AuthGroup,
8973 AFSPerformObjectInvalidate( IN AFSObjectInfoCB *ObjectInfo,
8974 IN ULONG InvalidateReason)
8977 AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
8978 NTSTATUS ntStatus = STATUS_SUCCESS;
8981 ULONG ulProcessCount = 0;
8988 switch( InvalidateReason)
8991 case AFS_INVALIDATE_DELETED:
8994 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
8995 ObjectInfo->Fcb != NULL)
8998 AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9001 ObjectInfo->Links = 0;
9003 ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
9005 KeSetEvent( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
9010 // Clear out the extents
9011 // And get rid of them (note this involves waiting
9012 // for any writes or reads to the cache to complete)
9015 AFSTearDownFcbExtents( ObjectInfo->Fcb,
9018 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
9024 case AFS_INVALIDATE_DATA_VERSION:
9027 LARGE_INTEGER liCurrentOffset = {0,0};
9028 LARGE_INTEGER liFlushLength = {0,0};
9029 ULONG ulFlushLength = 0;
9030 BOOLEAN bLocked = FALSE;
9031 BOOLEAN bExtentsLocked = FALSE;
9032 BOOLEAN bCleanExtents = FALSE;
9034 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
9035 ObjectInfo->Fcb != NULL)
9038 AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Resource,
9043 if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
9046 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9047 AFS_TRACE_LEVEL_VERBOSE,
9048 "AFSPerformObjectInvalidation DirectIO Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
9049 &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9050 PsGetCurrentThread()));
9052 AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9055 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9062 if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
9063 !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9069 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9070 AFS_TRACE_LEVEL_WARNING,
9071 "AFSPerformObjectInvalidation DirectIO CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9072 ObjectInfo->FileId.Cell,
9073 ObjectInfo->FileId.Volume,
9074 ObjectInfo->FileId.Vnode,
9075 ObjectInfo->FileId.Unique));
9077 SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9082 bCleanExtents = TRUE;
9085 __except( EXCEPTION_EXECUTE_HANDLER)
9088 ntStatus = GetExceptionCode();
9092 "EXCEPTION - AFSPerformObjectInvalidation DirectIO FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
9093 ObjectInfo->FileId.Cell,
9094 ObjectInfo->FileId.Volume,
9095 ObjectInfo->FileId.Vnode,
9096 ObjectInfo->FileId.Unique,
9099 SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9102 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9103 AFS_TRACE_LEVEL_VERBOSE,
9104 "AFSPerformObjectInvalidation DirectIO Releasing Fcb SectionObject lock %p EXCL %08lX\n",
9105 &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9106 PsGetCurrentThread()));
9108 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
9113 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9114 AFS_TRACE_LEVEL_VERBOSE,
9115 "AFSPerformObjectInvalidate Acquiring Fcb extents lock %p SHARED %08lX\n",
9116 &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9117 PsGetCurrentThread()));
9119 AFSAcquireShared( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9122 bExtentsLocked = TRUE;
9125 // There are several possibilities here:
9127 // 0. If there are no extents or all of the extents are dirty, do nothing.
9129 // 1. There could be nothing dirty and an open reference count of zero
9130 // in which case we can just tear down all of the extents without
9131 // holding any resources.
9133 // 2. There could be nothing dirty and a non-zero open reference count
9134 // in which case we can issue a CcPurge against the entire file
9135 // while holding just the Fcb Resource.
9137 // 3. There can be dirty extents in which case we need to identify
9138 // the non-dirty ranges and then perform a CcPurge on just the
9139 // non-dirty ranges while holding just the Fcb Resource.
9142 if ( ObjectInfo->Fcb->Specific.File.ExtentCount != ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount)
9145 if ( ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount == 0)
9148 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9150 bExtentsLocked = FALSE;
9152 if ( ObjectInfo->Fcb->OpenReferenceCount == 0)
9155 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9159 AFSTearDownFcbExtents( ObjectInfo->Fcb,
9165 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9166 AFS_TRACE_LEVEL_VERBOSE,
9167 "AFSPerformObjectInvalidation Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
9168 &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9169 PsGetCurrentThread()));
9171 AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9174 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9181 if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
9182 !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9188 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9189 AFS_TRACE_LEVEL_WARNING,
9190 "AFSPerformObjectInvalidation CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9191 ObjectInfo->FileId.Cell,
9192 ObjectInfo->FileId.Volume,
9193 ObjectInfo->FileId.Vnode,
9194 ObjectInfo->FileId.Unique));
9196 SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9201 bCleanExtents = TRUE;
9204 __except( EXCEPTION_EXECUTE_HANDLER)
9207 ntStatus = GetExceptionCode();
9211 "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
9212 ObjectInfo->FileId.Cell,
9213 ObjectInfo->FileId.Volume,
9214 ObjectInfo->FileId.Vnode,
9215 ObjectInfo->FileId.Unique,
9218 SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9221 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9222 AFS_TRACE_LEVEL_VERBOSE,
9223 "AFSPerformObjectInvalidation Releasing Fcb SectionObject lock %p EXCL %08lX\n",
9224 &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9225 PsGetCurrentThread()));
9227 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
9233 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9235 bExtentsLocked = FALSE;
9237 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9238 AFS_TRACE_LEVEL_VERBOSE,
9239 "AFSPerformObjectInvalidation Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
9240 &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9241 PsGetCurrentThread()));
9243 AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9246 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9251 // Must build a list of non-dirty ranges from the beginning of the file
9252 // to the end. There can be at most (Fcb->Specific.File.ExtentsDirtyCount + 1)
9253 // ranges. In all but the most extreme random data write scenario there will
9254 // be significantly fewer.
9256 // For each range we need offset and size.
9259 AFSByteRange * ByteRangeList = NULL;
9260 ULONG ulByteRangeCount = 0;
9262 BOOLEAN bPurgeOnClose = FALSE;
9267 ulByteRangeCount = AFSConstructCleanByteRangeList( ObjectInfo->Fcb,
9270 if ( ByteRangeList != NULL ||
9271 ulByteRangeCount == 0)
9274 for ( ulIndex = 0; ulIndex < ulByteRangeCount; ulIndex++)
9281 ulSize = ByteRangeList[ulIndex].Length.QuadPart > DWORD_MAX ? DWORD_MAX : ByteRangeList[ulIndex].Length.LowPart;
9283 if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
9284 !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9285 &ByteRangeList[ulIndex].FileOffset,
9290 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9291 AFS_TRACE_LEVEL_WARNING,
9292 "AFSPerformObjectInvalidation [1] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9293 ObjectInfo->FileId.Cell,
9294 ObjectInfo->FileId.Volume,
9295 ObjectInfo->FileId.Vnode,
9296 ObjectInfo->FileId.Unique));
9298 bPurgeOnClose = TRUE;
9303 bCleanExtents = TRUE;
9306 ByteRangeList[ulIndex].Length.QuadPart -= ulSize;
9308 ByteRangeList[ulIndex].FileOffset.QuadPart += ulSize;
9310 } while ( ByteRangeList[ulIndex].Length.QuadPart > 0);
9317 // We couldn't allocate the memory to build the purge list
9318 // so just walk the extent list while holding the ExtentsList Resource.
9319 // This could deadlock but we do not have much choice.
9322 AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9324 bExtentsLocked = TRUE;
9326 le = ObjectInfo->Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
9330 ulCount = (ULONG)ObjectInfo->Fcb->Specific.File.ExtentCount;
9334 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
9336 while( ulProcessCount < ulCount)
9338 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
9340 if( !BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
9342 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9343 &pEntry->FileOffset,
9348 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9349 AFS_TRACE_LEVEL_WARNING,
9350 "AFSPerformObjectInvalidation [2] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9351 ObjectInfo->FileId.Cell,
9352 ObjectInfo->FileId.Volume,
9353 ObjectInfo->FileId.Vnode,
9354 ObjectInfo->FileId.Unique));
9356 bPurgeOnClose = TRUE;
9361 bCleanExtents = TRUE;
9365 if( liCurrentOffset.QuadPart < pEntry->FileOffset.QuadPart)
9368 liFlushLength.QuadPart = pEntry->FileOffset.QuadPart - liCurrentOffset.QuadPart;
9370 while( liFlushLength.QuadPart > 0)
9373 if( liFlushLength.QuadPart > 512 * 1024000)
9375 ulFlushLength = 512 * 1024000;
9379 ulFlushLength = liFlushLength.LowPart;
9382 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9388 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9389 AFS_TRACE_LEVEL_WARNING,
9390 "AFSPerformObjectInvalidation [3] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9391 ObjectInfo->FileId.Cell,
9392 ObjectInfo->FileId.Volume,
9393 ObjectInfo->FileId.Vnode,
9394 ObjectInfo->FileId.Unique));
9396 bPurgeOnClose = TRUE;
9401 bCleanExtents = TRUE;
9404 liFlushLength.QuadPart -= ulFlushLength;
9408 liCurrentOffset.QuadPart = pEntry->FileOffset.QuadPart + pEntry->Size;
9416 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9422 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9423 AFS_TRACE_LEVEL_WARNING,
9424 "AFSPerformObjectInvalidation [4] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9425 ObjectInfo->FileId.Cell,
9426 ObjectInfo->FileId.Volume,
9427 ObjectInfo->FileId.Vnode,
9428 ObjectInfo->FileId.Unique));
9430 bPurgeOnClose = TRUE;
9435 bCleanExtents = TRUE;
9442 SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9446 __except( EXCEPTION_EXECUTE_HANDLER)
9449 ntStatus = GetExceptionCode();
9453 "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
9454 ObjectInfo->FileId.Cell,
9455 ObjectInfo->FileId.Volume,
9456 ObjectInfo->FileId.Vnode,
9457 ObjectInfo->FileId.Unique,
9461 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9462 AFS_TRACE_LEVEL_VERBOSE,
9463 "AFSPerformObjectInvalidation Releasing Fcb SectionObject lock %p EXCL %08lX\n",
9464 &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9465 PsGetCurrentThread()));
9467 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
9471 if ( bExtentsLocked)
9474 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9481 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9487 AFSReleaseCleanExtents( ObjectInfo->Fcb,
9497 // Destroy the reference passed in by the caller to AFSInvalidateObject
9498 // or AFSQueueInvalidateObject
9501 AFSAcquireShared( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
9504 lCount = AFSObjectInfoDecrement( ObjectInfo,
9505 AFS_OBJECT_REFERENCE_INVALIDATION);
9507 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
9508 AFS_TRACE_LEVEL_VERBOSE,
9509 "AFSPerformObjectInvalidation Decrement count on object %p Cnt %d\n",
9513 AFSReleaseResource( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);