2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSGeneric.cpp
39 #include "AFSCommon.h"
42 // Function: AFSExceptionFilter
46 // This function is the exception handler
50 // A status is returned for the function
54 AFSExceptionFilter( IN ULONG Code,
55 IN PEXCEPTION_POINTERS ExceptPtrs)
58 PEXCEPTION_RECORD ExceptRec;
64 ExceptRec = ExceptPtrs->ExceptionRecord;
66 Context = ExceptPtrs->ContextRecord;
70 "AFSExceptionFilter (Library) - EXR %p CXR %p Code %08lX Address %p Routine %p\n",
73 ExceptRec->ExceptionCode,
74 ExceptRec->ExceptionAddress,
75 (void *)AFSExceptionFilter);
77 DbgPrint("**** Exception Caught in AFS Redirector Library ****\n");
79 DbgPrint("\n\nPerform the following WnDbg Cmds:\n");
80 DbgPrint("\n\t.exr %p ; .cxr %p\n\n", ExceptRec, Context);
82 DbgPrint("**** Exception Complete from AFS Redirector Library ****\n");
84 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION))
87 KeBugCheck( (ULONG)-2);
95 __except( EXCEPTION_EXECUTE_HANDLER)
101 return EXCEPTION_EXECUTE_HANDLER;
105 // Function: AFSLibExAllocatePoolWithTag()
107 // Purpose: Allocate Pool Memory. If BugCheck Exception flag
108 // is configured on, then bugcheck the system if
109 // a memory allocation fails. The routine should be
110 // used for all memory allocations that are to be freed
111 // when the library is unloaded. Memory allocations that
112 // are to survive library unload and reload should be
113 // performed using AFSExAllocatePoolWithTag() which is
114 // provided by the AFS Framework.
117 // POOL_TYPE PoolType - Paged or NonPaged
118 // SIZE_T NumberOfBytes - requested allocation size
119 // ULONG Tag - Pool Allocation Tag to be applied for tracking
122 // void * - the memory allocation
126 AFSLibExAllocatePoolWithTag( IN POOL_TYPE PoolType,
127 IN SIZE_T NumberOfBytes,
131 void *pBuffer = NULL;
133 pBuffer = ExAllocatePoolWithTag( PoolType,
140 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION))
143 KeBugCheck( (ULONG)-2);
150 "AFSLibExAllocatePoolWithTag failure Type %08lX Size %08lX Tag %08lX %08lX\n",
154 PsGetCurrentThread());
164 // Function: AFSAcquireExcl()
166 // Purpose: Called to acquire a resource exclusive with optional wait
169 // PERESOURCE Resource - Resource to acquire
170 // BOOLEAN Wait - Whether to block
173 // BOOLEAN - Whether the mask was acquired
177 AFSAcquireExcl( IN PERESOURCE Resource,
181 BOOLEAN bStatus = FALSE;
184 // Normal kernel APCs must be disabled before calling
185 // ExAcquireResourceExclusiveLite. Otherwise a bugcheck occurs.
188 KeEnterCriticalRegion();
190 bStatus = ExAcquireResourceExclusiveLite( Resource,
196 KeLeaveCriticalRegion();
203 AFSAcquireSharedStarveExclusive( IN PERESOURCE Resource,
207 BOOLEAN bStatus = FALSE;
209 KeEnterCriticalRegion();
211 bStatus = ExAcquireSharedStarveExclusive( Resource,
217 KeLeaveCriticalRegion();
224 // Function: AFSAcquireShared()
226 // Purpose: Called to acquire a resource shared with optional wait
229 // PERESOURCE Resource - Resource to acquire
230 // BOOLEAN Wait - Whether to block
233 // BOOLEAN - Whether the mask was acquired
237 AFSAcquireShared( IN PERESOURCE Resource,
241 BOOLEAN bStatus = FALSE;
243 KeEnterCriticalRegion();
245 bStatus = ExAcquireResourceSharedLite( Resource,
251 KeLeaveCriticalRegion();
258 // Function: AFSReleaseResource()
260 // Purpose: Called to release a resource
263 // PERESOURCE Resource - Resource to release
270 AFSReleaseResource( IN PERESOURCE Resource)
273 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
274 AFS_TRACE_LEVEL_VERBOSE,
275 "AFSReleaseResource Releasing lock %08lX Thread %08lX\n",
277 PsGetCurrentThread());
279 ExReleaseResourceLite( Resource);
281 KeLeaveCriticalRegion();
287 AFSConvertToShared( IN PERESOURCE Resource)
290 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
291 AFS_TRACE_LEVEL_VERBOSE,
292 "AFSConvertToShared Converting lock %08lX Thread %08lX\n",
294 PsGetCurrentThread());
296 ExConvertExclusiveToSharedLite( Resource);
302 // Function: AFSCompleteRequest
306 // This function completes irps
310 // A status is returned for the function
314 AFSCompleteRequest( IN PIRP Irp,
318 Irp->IoStatus.Status = Status;
320 IoCompleteRequest( Irp,
327 // Function: AFSGenerateCRC
331 // Given a device and filename this function generates a CRC
335 // A status is returned for the function
339 AFSGenerateCRC( IN PUNICODE_STRING FileName,
340 IN BOOLEAN UpperCaseName)
344 NTSTATUS ntStatus = STATUS_SUCCESS;
346 ntStatus = RtlHashUnicodeString( FileName,
348 HASH_STRING_ALGORITHM_DEFAULT,
351 if( !NT_SUCCESS( ntStatus))
360 AFSLockSystemBuffer( IN PIRP Irp,
364 NTSTATUS Status = STATUS_SUCCESS;
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( GetExceptionCode(), GetExceptionInformation()) )
409 IoFreeMdl( Irp->MdlAddress );
410 Irp->MdlAddress = NULL;
420 AFSLockUserBuffer( IN void *UserBuffer,
421 IN ULONG BufferLength,
425 NTSTATUS ntStatus = STATUS_SUCCESS;
426 void *pAddress = NULL;
432 pMdl = IoAllocateMdl( UserBuffer,
441 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
445 // Lock the new Mdl in memory.
451 MmProbeAndLockPages( pMdl,
455 pAddress = MmGetSystemAddressForMdlSafe( pMdl,
458 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
481 AFSMapToService( IN PIRP Irp,
485 NTSTATUS ntStatus = STATUS_SUCCESS;
486 void *pMappedBuffer = NULL;
487 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
493 if( pDevExt->Specific.Control.ServiceProcess == NULL)
496 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
499 if( Irp->MdlAddress == NULL)
502 if( AFSLockSystemBuffer( Irp,
506 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
511 // Attach to the service process for mapping
514 KeStackAttachProcess( pDevExt->Specific.Control.ServiceProcess,
515 (PRKAPC_STATE)&stApcState);
517 pMappedBuffer = MmMapLockedPagesSpecifyCache( Irp->MdlAddress,
524 KeUnstackDetachProcess( (PRKAPC_STATE)&stApcState);
531 return pMappedBuffer;
535 AFSUnmapServiceMappedBuffer( IN void *MappedBuffer,
539 NTSTATUS ntStatus = STATUS_SUCCESS;
540 void *pMappedBuffer = NULL;
541 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
547 if( pDevExt->Specific.Control.ServiceProcess == NULL)
550 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
557 // Attach to the service process for mapping
560 KeStackAttachProcess( pDevExt->Specific.Control.ServiceProcess,
561 (PRKAPC_STATE)&stApcState);
563 MmUnmapLockedPages( MappedBuffer,
566 KeUnstackDetachProcess( (PRKAPC_STATE)&stApcState);
578 AFSInitializeLibraryDevice()
581 NTSTATUS ntStatus = STATUS_SUCCESS;
582 AFSDeviceExt *pDeviceExt = NULL;
587 pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
590 // The PIOCtl file name
593 RtlInitUnicodeString( &AFSPIOCtlName,
594 AFS_PIOCTL_FILE_INTERFACE_NAME);
597 // And the global root share name
600 RtlInitUnicodeString( &AFSGlobalRootName,
601 AFS_GLOBAL_ROOT_SHARE_NAME);
609 AFSRemoveLibraryDevice()
612 NTSTATUS ntStatus = STATUS_SUCCESS;
623 AFSDefaultDispatch( IN PDEVICE_OBJECT DeviceObject,
627 NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
628 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
630 AFSCompleteRequest( Irp,
637 AFSInitializeGlobalDirectoryEntries()
640 NTSTATUS ntStatus = STATUS_SUCCESS;
641 AFSDirectoryCB *pDirNode = NULL;
642 ULONG ulEntryLength = 0;
643 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
644 AFSObjectInfoCB *pObjectInfoCB = NULL;
645 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
652 // Initialize the global . entry
655 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
658 if( pObjectInfoCB == NULL)
661 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
662 AFS_TRACE_LEVEL_ERROR,
663 "AFSInitializeGlobalDirectory AFSAllocateObjectInfo failure %08lX\n",
666 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
669 lCount = InterlockedIncrement( &pObjectInfoCB->ObjectReferenceCount);
671 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
672 AFS_TRACE_LEVEL_VERBOSE,
673 "AFSInitializeGlobalDirectoryEntries Increment count on object %08lX Cnt %d\n",
677 ntStatus = STATUS_SUCCESS;
679 ulEntryLength = sizeof( AFSDirectoryCB) +
682 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
686 if( pDirNode == NULL)
689 AFSDeleteObjectInfo( pObjectInfoCB);
691 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
692 AFS_TRACE_LEVEL_ERROR,
693 "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_TAG allocation failure\n");
695 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
698 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
699 sizeof( AFSNonPagedDirectoryCB),
700 AFS_DIR_ENTRY_NP_TAG);
702 if( pNonPagedDirEntry == NULL)
705 ExFreePool( pDirNode);
707 AFSDeleteObjectInfo( pObjectInfoCB);
709 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
710 AFS_TRACE_LEVEL_ERROR,
711 "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_NP_TAG allocation failure\n");
713 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
716 RtlZeroMemory( pDirNode,
719 RtlZeroMemory( pNonPagedDirEntry,
720 sizeof( AFSNonPagedDirectoryCB));
722 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
724 pDirNode->NonPaged = pNonPagedDirEntry;
726 pDirNode->ObjectInformation = pObjectInfoCB;
732 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE | AFS_DIR_ENTRY_FAKE | AFS_DIR_ENTRY_VALID);
734 pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_DOT_INDEX;
737 // Setup the names in the entry
740 pDirNode->NameInformation.FileName.Length = sizeof( WCHAR);
742 pDirNode->NameInformation.FileName.MaximumLength = sizeof( WCHAR);
744 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
746 pDirNode->NameInformation.FileName.Buffer[ 0] = L'.';
749 // Populate the rest of the data
752 pObjectInfoCB->FileType = AFS_FILE_TYPE_DIRECTORY;
754 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
756 AFSGlobalDotDirEntry = pDirNode;
762 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
765 if( pObjectInfoCB == NULL)
768 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
769 AFS_TRACE_LEVEL_ERROR,
770 "AFSInitializeGlobalDirectory AFSAllocateObjectInfo (2) failure %08lX\n",
773 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
776 lCount = InterlockedIncrement( &pObjectInfoCB->ObjectReferenceCount);
778 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
779 AFS_TRACE_LEVEL_VERBOSE,
780 "AFSInitializeGlobalDirectoryEntries Increment count on object %08lX Cnt %d\n",
784 ntStatus = STATUS_SUCCESS;
786 ulEntryLength = sizeof( AFSDirectoryCB) +
787 ( 2 * sizeof( WCHAR));
789 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
793 if( pDirNode == NULL)
796 AFSDeleteObjectInfo( pObjectInfoCB);
798 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
801 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
802 sizeof( AFSNonPagedDirectoryCB),
803 AFS_DIR_ENTRY_NP_TAG);
805 if( pNonPagedDirEntry == NULL)
808 ExFreePool( pDirNode);
810 AFSDeleteObjectInfo( pObjectInfoCB);
812 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
815 RtlZeroMemory( pDirNode,
818 RtlZeroMemory( pNonPagedDirEntry,
819 sizeof( AFSNonPagedDirectoryCB));
821 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
823 pDirNode->NonPaged = pNonPagedDirEntry;
825 pDirNode->ObjectInformation = pObjectInfoCB;
831 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE | AFS_DIR_ENTRY_FAKE | AFS_DIR_ENTRY_VALID);
833 pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX;
836 // Setup the names in the entry
839 pDirNode->NameInformation.FileName.Length = 2 * sizeof( WCHAR);
841 pDirNode->NameInformation.FileName.MaximumLength = 2 * sizeof( WCHAR);
843 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
845 pDirNode->NameInformation.FileName.Buffer[ 0] = L'.';
847 pDirNode->NameInformation.FileName.Buffer[ 1] = L'.';
850 // Populate the rest of the data
853 pObjectInfoCB->FileType = AFS_FILE_TYPE_DIRECTORY;
855 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
857 AFSGlobalDotDotDirEntry = pDirNode;
861 if( !NT_SUCCESS( ntStatus))
864 if( AFSGlobalDotDirEntry != NULL)
867 AFSDeleteObjectInfo( AFSGlobalDotDirEntry->ObjectInformation);
869 ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
871 ExFreePool( AFSGlobalDotDirEntry->NonPaged);
873 ExFreePool( AFSGlobalDotDirEntry);
875 AFSGlobalDotDirEntry = NULL;
878 if( AFSGlobalDotDotDirEntry != NULL)
881 AFSDeleteObjectInfo( AFSGlobalDotDotDirEntry->ObjectInformation);
883 ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
885 ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
887 ExFreePool( AFSGlobalDotDotDirEntry);
889 AFSGlobalDotDotDirEntry = NULL;
898 AFSInitDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
899 IN PUNICODE_STRING FileName,
900 IN PUNICODE_STRING TargetName,
901 IN AFSDirEnumEntry *DirEnumEntry,
905 AFSDirectoryCB *pDirNode = NULL;
906 NTSTATUS ntStatus = STATUS_SUCCESS;
907 ULONG ulEntryLength = 0;
908 AFSDirEnumEntry *pDirEnumCB = NULL;
909 AFSFileID stTargetFileID;
911 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
912 AFSObjectInfoCB *pObjectInfoCB = NULL;
913 BOOLEAN bAllocatedObjectCB = FALSE;
914 ULONGLONG ullIndex = 0;
915 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
921 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
922 AFS_TRACE_LEVEL_VERBOSE,
923 "AFSInitDirEntry Initializing entry %wZ parent FID %08lX-%08lX-%08lX-%08lX\n",
925 ParentObjectInfo->FileId.Cell,
926 ParentObjectInfo->FileId.Volume,
927 ParentObjectInfo->FileId.Vnode,
928 ParentObjectInfo->FileId.Unique);
931 // First thing is to locate/create our object information block
935 AFSAcquireExcl( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
938 ullIndex = AFSCreateLowIndex( &DirEnumEntry->FileId);
940 ntStatus = AFSLocateHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
942 (AFSBTreeEntry **)&pObjectInfoCB);
944 if( !NT_SUCCESS( ntStatus) ||
945 pObjectInfoCB == NULL)
949 // Allocate our object info cb
952 pObjectInfoCB = AFSAllocateObjectInfo( ParentObjectInfo,
955 if( pObjectInfoCB == NULL)
958 AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
960 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
963 bAllocatedObjectCB = TRUE;
965 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
966 AFS_TRACE_LEVEL_VERBOSE,
967 "AFSInitDirEntry initialized object %08lX Parent Object %08lX for %wZ\n",
973 lCount = InterlockedIncrement( &pObjectInfoCB->ObjectReferenceCount);
975 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
976 AFS_TRACE_LEVEL_VERBOSE,
977 "AFSInitDirEntry Increment count on object %08lX Cnt %d\n",
981 AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
983 ntStatus = STATUS_SUCCESS;
985 ulEntryLength = sizeof( AFSDirectoryCB) +
988 if( TargetName != NULL)
991 ulEntryLength += TargetName->Length;
994 pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
998 if( pDirNode == NULL)
1001 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1004 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
1005 sizeof( AFSNonPagedDirectoryCB),
1006 AFS_DIR_ENTRY_NP_TAG);
1008 if( pNonPagedDirEntry == NULL)
1011 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1014 RtlZeroMemory( pDirNode,
1017 RtlZeroMemory( pNonPagedDirEntry,
1018 sizeof( AFSNonPagedDirectoryCB));
1020 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
1022 pDirNode->NonPaged = pNonPagedDirEntry;
1024 pDirNode->ObjectInformation = pObjectInfoCB;
1027 // Set valid entry and NOT_IN_PARENT flag
1030 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1032 pDirNode->FileIndex = FileIndex;
1035 // Setup the names in the entry
1038 if( FileName->Length > 0)
1041 pDirNode->NameInformation.FileName.Length = FileName->Length;
1043 pDirNode->NameInformation.FileName.MaximumLength = FileName->Length;
1045 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
1047 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
1049 pDirNode->NameInformation.FileName.Length);
1052 // Create a CRC for the file
1055 pDirNode->CaseSensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1058 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1062 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1063 AFS_TRACE_LEVEL_VERBOSE,
1064 "AFSInitDirEntry Initialized DE %p for %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1067 ParentObjectInfo->FileId.Cell,
1068 ParentObjectInfo->FileId.Volume,
1069 ParentObjectInfo->FileId.Vnode,
1070 ParentObjectInfo->FileId.Unique);
1072 if( TargetName != NULL &&
1073 TargetName->Length > 0)
1076 pDirNode->NameInformation.TargetName.Length = TargetName->Length;
1078 pDirNode->NameInformation.TargetName.MaximumLength = pDirNode->NameInformation.TargetName.Length;
1080 pDirNode->NameInformation.TargetName.Buffer = (WCHAR *)((char *)pDirNode +
1081 sizeof( AFSDirectoryCB) +
1082 pDirNode->NameInformation.FileName.Length);
1084 RtlCopyMemory( pDirNode->NameInformation.TargetName.Buffer,
1086 pDirNode->NameInformation.TargetName.Length);
1090 // If we allocated the object information cb then update the information
1093 if( bAllocatedObjectCB)
1097 // Populate the rest of the data
1100 pObjectInfoCB->FileId = DirEnumEntry->FileId;
1102 pObjectInfoCB->TargetFileId = DirEnumEntry->TargetFileId;
1104 pObjectInfoCB->FileType = DirEnumEntry->FileType;
1106 pObjectInfoCB->CreationTime = DirEnumEntry->CreationTime;
1108 pObjectInfoCB->LastAccessTime = DirEnumEntry->LastAccessTime;
1110 pObjectInfoCB->LastWriteTime = DirEnumEntry->LastWriteTime;
1112 pObjectInfoCB->ChangeTime = DirEnumEntry->ChangeTime;
1114 pObjectInfoCB->EndOfFile = DirEnumEntry->EndOfFile;
1116 pObjectInfoCB->AllocationSize = DirEnumEntry->AllocationSize;
1118 pObjectInfoCB->FileAttributes = DirEnumEntry->FileAttributes;
1120 if( pObjectInfoCB->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1123 pObjectInfoCB->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1126 if (pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK ||
1127 pObjectInfoCB->FileType == AFS_FILE_TYPE_DFSLINK)
1130 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1133 pObjectInfoCB->EaSize = DirEnumEntry->EaSize;
1136 // Object specific information
1139 pObjectInfoCB->Links = DirEnumEntry->Links;
1141 pObjectInfoCB->Expiration = DirEnumEntry->Expiration;
1143 pObjectInfoCB->DataVersion = DirEnumEntry->DataVersion;
1146 // Check for the case where we have a filetype of SymLink but both the TargetFid and the
1147 // TargetName are empty. In this case set the filetype to zero so we evaluate it later in
1151 if( pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK &&
1152 pObjectInfoCB->TargetFileId.Vnode == 0 &&
1153 pObjectInfoCB->TargetFileId.Unique == 0 &&
1154 pDirNode->NameInformation.TargetName.Length == 0)
1158 // This will ensure we perform a validation on the node
1161 pObjectInfoCB->FileType = AFS_FILE_TYPE_UNKNOWN;
1164 if( pObjectInfoCB->FileType == AFS_FILE_TYPE_UNKNOWN)
1167 SetFlag( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
1173 if( !NT_SUCCESS( ntStatus))
1176 if( pNonPagedDirEntry != NULL)
1179 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
1181 AFSExFreePool( pNonPagedDirEntry);
1184 if( pDirNode != NULL)
1187 AFSExFreePool( pDirNode);
1193 // Dereference our object info block if we have one
1196 if( pObjectInfoCB != NULL)
1199 lCount = InterlockedDecrement( &pObjectInfoCB->ObjectReferenceCount);
1201 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1202 AFS_TRACE_LEVEL_VERBOSE,
1203 "AFSInitDirEntry Decrement count on object %08lX Cnt %d\n",
1207 if( bAllocatedObjectCB)
1210 ASSERT( pObjectInfoCB->ObjectReferenceCount == 0);
1212 AFSDeleteObjectInfo( pObjectInfoCB);
1222 AFSCheckForReadOnlyAccess( IN ACCESS_MASK DesiredAccess,
1223 IN BOOLEAN DirectoryEntry)
1226 BOOLEAN bReturn = TRUE;
1227 ACCESS_MASK stAccessMask = 0;
1230 // Get rid of anything we don't know about
1233 DesiredAccess = (DesiredAccess &
1239 ACCESS_SYSTEM_SECURITY |
1243 FILE_READ_ATTRIBUTES |
1244 FILE_WRITE_ATTRIBUTES |
1245 FILE_LIST_DIRECTORY |
1251 // Our 'read only' access mask. These are the accesses we will
1252 // allow for a read only file
1255 stAccessMask = DELETE |
1260 ACCESS_SYSTEM_SECURITY |
1264 FILE_READ_ATTRIBUTES |
1265 FILE_WRITE_ATTRIBUTES |
1267 FILE_LIST_DIRECTORY |
1271 // For a directory, add in the directory specific accesses
1277 stAccessMask |= FILE_ADD_SUBDIRECTORY |
1282 if( FlagOn( DesiredAccess, ~stAccessMask))
1286 // A write access is set ...
1296 AFSEvaluateNode( IN GUID *AuthGroup,
1297 IN AFSDirectoryCB *DirEntry)
1300 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1301 NTSTATUS ntStatus = STATUS_SUCCESS;
1302 AFSDirEnumEntry *pDirEntry = NULL;
1303 UNICODE_STRING uniTargetName;
1308 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1313 if( !NT_SUCCESS( ntStatus))
1316 try_return( ntStatus);
1319 DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1321 DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1323 DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1325 DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1327 DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1329 DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1331 DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1333 DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1335 DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1337 DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1339 DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1341 if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1344 DirEntry->ObjectInformation->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1347 if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK ||
1348 pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1351 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1354 DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1356 DirEntry->ObjectInformation->Links = pDirEntry->Links;
1359 // If we have a target name then see if it needs updating ...
1362 if( pDirEntry->TargetNameLength > 0)
1366 // Update the target name information if needed
1369 uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1371 uniTargetName.MaximumLength = uniTargetName.Length;
1373 uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1375 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1378 if( DirEntry->NameInformation.TargetName.Length == 0 ||
1379 RtlCompareUnicodeString( &uniTargetName,
1380 &DirEntry->NameInformation.TargetName,
1385 // Update the target name
1388 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1390 uniTargetName.Buffer,
1391 uniTargetName.Length);
1393 if( !NT_SUCCESS( ntStatus))
1396 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1398 try_return( ntStatus);
1402 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1407 if( pDirEntry != NULL)
1410 AFSExFreePool( pDirEntry);
1418 AFSValidateSymLink( IN GUID *AuthGroup,
1419 IN AFSDirectoryCB *DirEntry)
1422 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1423 NTSTATUS ntStatus = STATUS_SUCCESS;
1424 AFSDirEnumEntry *pDirEntry = NULL;
1425 UNICODE_STRING uniTargetName;
1430 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1435 if( !NT_SUCCESS( ntStatus))
1438 try_return( ntStatus);
1441 if( pDirEntry->FileType == AFS_FILE_TYPE_UNKNOWN ||
1442 pDirEntry->FileType == AFS_FILE_TYPE_INVALID)
1445 try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
1448 DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1450 DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1452 DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1455 // Update the target name information if needed
1458 uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1460 uniTargetName.MaximumLength = uniTargetName.Length;
1462 uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1464 if( uniTargetName.Length > 0)
1467 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1470 if( DirEntry->NameInformation.TargetName.Length == 0 ||
1471 RtlCompareUnicodeString( &uniTargetName,
1472 &DirEntry->NameInformation.TargetName,
1477 // Update the target name
1480 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1482 uniTargetName.Buffer,
1483 uniTargetName.Length);
1485 if( !NT_SUCCESS( ntStatus))
1488 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1490 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1494 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1498 // If the FileType is the same then nothing to do since it IS
1502 if( pDirEntry->FileType == DirEntry->ObjectInformation->FileType)
1505 ASSERT( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK);
1507 try_return( ntStatus = STATUS_SUCCESS);
1510 DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1512 DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1514 DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1516 DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1518 DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1520 DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1522 DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1524 DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1526 if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1529 DirEntry->ObjectInformation->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1532 if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK ||
1533 pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1536 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1539 DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1541 DirEntry->ObjectInformation->Links = pDirEntry->Links;
1545 if( pDirEntry != NULL)
1548 AFSExFreePool( pDirEntry);
1556 AFSInvalidateObject( IN OUT AFSObjectInfoCB **ppObjectInfo,
1560 NTSTATUS ntStatus = STATUS_SUCCESS;
1561 IO_STATUS_BLOCK stIoStatus;
1564 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1565 AFS_TRACE_LEVEL_VERBOSE,
1566 "AFSInvalidateObject Invalidation on node type %d for fid %08lX-%08lX-%08lX-%08lX Reason %d\n",
1567 (*ppObjectInfo)->FileType,
1568 (*ppObjectInfo)->FileId.Cell,
1569 (*ppObjectInfo)->FileId.Volume,
1570 (*ppObjectInfo)->FileId.Vnode,
1571 (*ppObjectInfo)->FileId.Unique,
1574 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_SYMLINK ||
1575 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DFSLINK ||
1576 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1579 // We only act on the mount point itself, not the target. If the
1580 // node has been deleted then mark it as such otherwise indicate
1581 // it requires verification
1584 if( Reason == AFS_INVALIDATE_DELETED)
1586 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
1591 if( Reason == AFS_INVALIDATE_FLUSHED)
1594 (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1596 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1599 (*ppObjectInfo)->Expiration.QuadPart = 0;
1601 (*ppObjectInfo)->TargetFileId.Vnode = 0;
1603 (*ppObjectInfo)->TargetFileId.Unique = 0;
1605 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1606 AFS_TRACE_LEVEL_VERBOSE,
1607 "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1608 (*ppObjectInfo)->FileId.Cell,
1609 (*ppObjectInfo)->FileId.Volume,
1610 (*ppObjectInfo)->FileId.Vnode,
1611 (*ppObjectInfo)->FileId.Unique);
1613 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1616 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1618 if( Reason == AFS_INVALIDATE_CREDS)
1620 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1623 if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1624 Reason == AFS_INVALIDATE_FLUSHED)
1626 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1630 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1633 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
1635 FILE_NOTIFY_CHANGE_FILE_NAME |
1636 FILE_NOTIFY_CHANGE_ATTRIBUTES,
1637 FILE_ACTION_MODIFIED);
1639 try_return( ntStatus);
1643 // Depending on the reason for invalidation then perform work on the node
1649 case AFS_INVALIDATE_DELETED:
1653 // Mark this node as invalid
1656 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_DELETED);
1658 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1659 AFS_TRACE_LEVEL_VERBOSE,
1660 "AFSInvalidateObject Set DELETE flag on fid %08lX-%08lX-%08lX-%08lX\n",
1661 (*ppObjectInfo)->FileId.Cell,
1662 (*ppObjectInfo)->FileId.Volume,
1663 (*ppObjectInfo)->FileId.Vnode,
1664 (*ppObjectInfo)->FileId.Unique);
1666 if( (*ppObjectInfo)->ParentObjectInformation != NULL)
1669 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1670 AFS_TRACE_LEVEL_VERBOSE,
1671 "AFSInvalidateObject Set VERIFY flag on parent fid %08lX-%08lX-%08lX-%08lX\n",
1672 (*ppObjectInfo)->ParentObjectInformation->FileId.Cell,
1673 (*ppObjectInfo)->ParentObjectInformation->FileId.Volume,
1674 (*ppObjectInfo)->ParentObjectInformation->FileId.Vnode,
1675 (*ppObjectInfo)->ParentObjectInformation->FileId.Unique);
1677 SetFlag( (*ppObjectInfo)->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1679 (*ppObjectInfo)->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1681 (*ppObjectInfo)->ParentObjectInformation->Expiration.QuadPart = 0;
1684 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1686 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1690 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1693 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
1696 FILE_ACTION_REMOVED);
1698 if( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1701 (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1707 case AFS_INVALIDATE_FLUSHED:
1710 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1711 (*ppObjectInfo)->Fcb != NULL)
1714 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1715 AFS_TRACE_LEVEL_VERBOSE,
1716 "AFSInvalidateObject Flush/purge file fid %08lX-%08lX-%08lX-%08lX\n",
1717 (*ppObjectInfo)->FileId.Cell,
1718 (*ppObjectInfo)->FileId.Volume,
1719 (*ppObjectInfo)->FileId.Vnode,
1720 (*ppObjectInfo)->FileId.Unique);
1722 AFSAcquireExcl( &(*ppObjectInfo)->Fcb->NPFcb->Resource,
1728 CcFlushCache( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1733 if( !NT_SUCCESS( stIoStatus.Status))
1736 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1737 AFS_TRACE_LEVEL_ERROR,
1738 "AFSInvalidateObject CcFlushCache failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1739 (*ppObjectInfo)->FileId.Cell,
1740 (*ppObjectInfo)->FileId.Volume,
1741 (*ppObjectInfo)->FileId.Vnode,
1742 (*ppObjectInfo)->FileId.Unique,
1744 stIoStatus.Information);
1746 ntStatus = stIoStatus.Status;
1749 CcPurgeCacheSection( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1754 __except( EXCEPTION_EXECUTE_HANDLER)
1757 ntStatus = GetExceptionCode();
1760 AFSReleaseResource( &(*ppObjectInfo)->Fcb->NPFcb->Resource);
1763 // Clear out the extents
1764 // Get rid of them (note this involves waiting
1765 // for any writes or reads to the cache to complete)
1768 (VOID) AFSTearDownFcbExtents( (*ppObjectInfo)->Fcb,
1772 (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1775 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE)
1778 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1779 AFS_TRACE_LEVEL_VERBOSE,
1780 "AFSInvalidateObject Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
1781 (*ppObjectInfo)->FileId.Cell,
1782 (*ppObjectInfo)->FileId.Volume,
1783 (*ppObjectInfo)->FileId.Vnode,
1784 (*ppObjectInfo)->FileId.Unique);
1786 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1789 // Fall through to the default processing
1795 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1797 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1801 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1804 if( Reason == AFS_INVALIDATE_CREDS)
1806 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1809 if( Reason == AFS_INVALIDATE_DATA_VERSION)
1811 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1815 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1818 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
1821 FILE_ACTION_MODIFIED);
1824 // Indicate this node requires re-evaluation for the remaining reasons
1827 (*ppObjectInfo)->Expiration.QuadPart = 0;
1829 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1830 AFS_TRACE_LEVEL_VERBOSE,
1831 "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1832 (*ppObjectInfo)->FileId.Cell,
1833 (*ppObjectInfo)->FileId.Volume,
1834 (*ppObjectInfo)->FileId.Vnode,
1835 (*ppObjectInfo)->FileId.Unique);
1837 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1839 if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1840 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1841 ( Reason == AFS_INVALIDATE_CALLBACK ||
1842 Reason == AFS_INVALIDATE_EXPIRED))
1844 if ( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1845 AFS_INVALIDATE_DATA_VERSION)))
1848 (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1862 AFSInvalidateCache( IN AFSInvalidateCacheCB *InvalidateCB)
1865 NTSTATUS ntStatus = STATUS_SUCCESS;
1866 AFSFcb *pDcb = NULL, *pFcb = NULL, *pNextFcb = NULL;
1867 AFSVolumeCB *pVolumeCB = NULL;
1868 AFSFcb *pTargetDcb = NULL;
1869 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1870 AFSDirectoryCB *pCurrentDirEntry = NULL;
1871 BOOLEAN bIsChild = FALSE;
1872 ULONGLONG ullIndex = 0;
1873 AFSObjectInfoCB *pObjectInfo = NULL;
1879 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1880 AFS_TRACE_LEVEL_VERBOSE,
1881 "AFSInvalidateCache Invalidation FID %08lX-%08lX-%08lX-%08lX Type %d WholeVolume %d Reason %d\n",
1882 InvalidateCB->FileID.Cell,
1883 InvalidateCB->FileID.Volume,
1884 InvalidateCB->FileID.Vnode,
1885 InvalidateCB->FileID.Unique,
1886 InvalidateCB->FileType,
1887 InvalidateCB->WholeVolume,
1888 InvalidateCB->Reason);
1891 // Need to locate the Fcb for the directory to purge
1894 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1895 AFS_TRACE_LEVEL_VERBOSE,
1896 "AFSInvalidateCache Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1897 &pDevExt->Specific.RDR.VolumeTreeLock,
1898 PsGetCurrentThread());
1901 // Starve any exclusive waiters on this paticular call
1904 AFSAcquireSharedStarveExclusive( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1907 // Locate the volume node
1910 ullIndex = AFSCreateHighIndex( &InvalidateCB->FileID);
1912 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1914 (AFSBTreeEntry **)&pVolumeCB);
1916 if( pVolumeCB != NULL)
1919 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1921 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1922 AFS_TRACE_LEVEL_VERBOSE,
1923 "AFSInvalidateCache Increment count on volume %08lX Cnt %d\n",
1928 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1930 if( !NT_SUCCESS( ntStatus) ||
1934 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1935 AFS_TRACE_LEVEL_WARNING,
1936 "AFSInvalidateCache Invalidation FAILURE Unable to locate volume node FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1937 InvalidateCB->FileID.Cell,
1938 InvalidateCB->FileID.Volume,
1939 InvalidateCB->FileID.Vnode,
1940 InvalidateCB->FileID.Unique,
1943 try_return( ntStatus = STATUS_SUCCESS);
1947 // If this is a whole volume invalidation then go do it now
1950 if( InvalidateCB->WholeVolume)
1953 ntStatus = AFSInvalidateVolume( pVolumeCB,
1954 InvalidateCB->Reason);
1956 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1958 try_return( ntStatus);
1961 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1964 if ( AFSIsVolumeFID( &InvalidateCB->FileID))
1967 pObjectInfo = &pVolumeCB->ObjectInformation;
1972 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1974 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1975 AFS_TRACE_LEVEL_VERBOSE,
1976 "AFSInvalidateCache Decrement count on volume %08lX Cnt %d\n",
1978 pVolumeCB->VolumeReferenceCount);
1980 ullIndex = AFSCreateLowIndex( &InvalidateCB->FileID);
1982 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1984 (AFSBTreeEntry **)&pObjectInfo);
1987 if( pObjectInfo != NULL)
1991 // Reference the node so it won't be torn down
1994 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1996 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1997 AFS_TRACE_LEVEL_VERBOSE,
1998 "AFSInvalidateCache Increment count on object %08lX Cnt %d\n",
2003 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2005 if( !NT_SUCCESS( ntStatus) ||
2006 pObjectInfo == NULL)
2009 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2010 AFS_TRACE_LEVEL_WARNING,
2011 "AFSInvalidateCache Invalidation FAILURE Unable to locate object FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2012 InvalidateCB->FileID.Cell,
2013 InvalidateCB->FileID.Volume,
2014 InvalidateCB->FileID.Vnode,
2015 InvalidateCB->FileID.Unique,
2018 try_return( ntStatus = STATUS_SUCCESS);
2021 AFSInvalidateObject( &pObjectInfo,
2022 InvalidateCB->Reason);
2026 if( pObjectInfo != NULL)
2029 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2031 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2032 AFS_TRACE_LEVEL_VERBOSE,
2033 "AFSInvalidateCache Decrement count on object %08lX Cnt %d\n",
2043 AFSIsChildOfParent( IN AFSFcb *Dcb,
2047 BOOLEAN bIsChild = FALSE;
2048 AFSFcb *pCurrentFcb = Fcb;
2050 while( pCurrentFcb != NULL)
2053 if( pCurrentFcb->ObjectInformation->ParentObjectInformation == Dcb->ObjectInformation)
2061 pCurrentFcb = pCurrentFcb->ObjectInformation->ParentObjectInformation->Fcb;
2069 AFSCreateHighIndex( IN AFSFileID *FileID)
2072 ULONGLONG ullIndex = 0;
2074 ullIndex = (((ULONGLONG)FileID->Cell << 32) | FileID->Volume);
2081 AFSCreateLowIndex( IN AFSFileID *FileID)
2084 ULONGLONG ullIndex = 0;
2086 ullIndex = (((ULONGLONG)FileID->Vnode << 32) | FileID->Unique);
2092 AFSCheckAccess( IN ACCESS_MASK DesiredAccess,
2093 IN ACCESS_MASK GrantedAccess,
2094 IN BOOLEAN DirectoryEntry)
2097 BOOLEAN bAccessGranted = TRUE;
2100 // Check if we are asking for read/write and granted only read only
2101 // NOTE: There will be more checks here
2104 if( !AFSCheckForReadOnlyAccess( DesiredAccess,
2106 AFSCheckForReadOnlyAccess( GrantedAccess,
2110 bAccessGranted = FALSE;
2113 return bAccessGranted;
2117 AFSGetDriverStatus( IN AFSDriverStatusRespCB *DriverStatus)
2120 NTSTATUS ntStatus = STATUS_SUCCESS;
2121 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2127 DriverStatus->Status = AFS_DRIVER_STATUS_READY;
2129 if( AFSGlobalRoot == NULL)
2136 DriverStatus->Status = AFS_DRIVER_STATUS_NOT_READY;
2139 if( pControlDevExt->Specific.Control.CommServiceCB.IrpPoolControlFlag != POOL_ACTIVE)
2146 DriverStatus->Status = AFS_DRIVER_STATUS_NO_SERVICE;
2153 AFSSubstituteSysName( IN UNICODE_STRING *ComponentName,
2154 IN UNICODE_STRING *SubstituteName,
2155 IN ULONG StringIndex)
2158 NTSTATUS ntStatus = STATUS_SUCCESS;
2159 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2160 AFSSysNameCB *pSysName = NULL;
2161 ERESOURCE *pSysNameLock = NULL;
2164 UNICODE_STRING uniSysName;
2171 if( IoIs32bitProcess( NULL))
2174 pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2176 pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2181 pSysNameLock = &pControlDevExt->Specific.Control.SysName64ListLock;
2183 pSysName = pControlDevExt->Specific.Control.SysName64ListHead;
2187 pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2189 pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2193 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2194 AFS_TRACE_LEVEL_VERBOSE,
2195 "AFSSubstituteSysName Acquiring SysName lock %08lX SHARED %08lX\n",
2197 PsGetCurrentThread());
2199 AFSAcquireShared( pSysNameLock,
2203 // Find where we are in the list
2206 while( pSysName != NULL &&
2207 ulIndex < StringIndex)
2210 pSysName = pSysName->fLink;
2215 if( pSysName == NULL)
2218 try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
2221 RtlInitUnicodeString( &uniSysName,
2224 // If it is a full component of @SYS then just substitue the
2228 if( RtlCompareUnicodeString( &uniSysName,
2233 SubstituteName->Length = pSysName->SysName.Length;
2234 SubstituteName->MaximumLength = SubstituteName->Length;
2236 SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2237 SubstituteName->Length,
2238 AFS_SUBST_BUFFER_TAG);
2240 if( SubstituteName->Buffer == NULL)
2243 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2246 RtlCopyMemory( SubstituteName->Buffer,
2247 pSysName->SysName.Buffer,
2248 pSysName->SysName.Length);
2255 while( ComponentName->Buffer[ usIndex] != L'@')
2261 SubstituteName->Length = (usIndex * sizeof( WCHAR)) + pSysName->SysName.Length;
2262 SubstituteName->MaximumLength = SubstituteName->Length;
2264 SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2265 SubstituteName->Length,
2266 AFS_SUBST_BUFFER_TAG);
2268 if( SubstituteName->Buffer == NULL)
2271 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2274 RtlCopyMemory( SubstituteName->Buffer,
2275 ComponentName->Buffer,
2276 usIndex * sizeof( WCHAR));
2278 RtlCopyMemory( &SubstituteName->Buffer[ usIndex],
2279 pSysName->SysName.Buffer,
2280 pSysName->SysName.Length);
2285 AFSReleaseResource( pSysNameLock);
2292 AFSSubstituteNameInPath( IN OUT UNICODE_STRING *FullPathName,
2293 IN OUT UNICODE_STRING *ComponentName,
2294 IN UNICODE_STRING *SubstituteName,
2295 IN OUT UNICODE_STRING *RemainingPath,
2296 IN BOOLEAN FreePathName)
2299 NTSTATUS ntStatus = STATUS_SUCCESS;
2300 UNICODE_STRING uniPathName;
2301 USHORT usPrefixNameLen = 0;
2302 SHORT sNameLenDelta = 0;
2308 // If the passed in name can handle the additional length
2309 // then just moves things around
2312 sNameLenDelta = SubstituteName->Length - ComponentName->Length;
2314 usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2316 if( FullPathName->MaximumLength > FullPathName->Length + sNameLenDelta)
2319 if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2322 RtlMoveMemory( &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + SubstituteName->Length)/sizeof( WCHAR))],
2323 &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + ComponentName->Length)/sizeof( WCHAR))],
2324 FullPathName->Length - usPrefixNameLen*sizeof( WCHAR) - ComponentName->Length);
2327 RtlCopyMemory( &FullPathName->Buffer[ usPrefixNameLen],
2328 SubstituteName->Buffer,
2329 SubstituteName->Length);
2331 FullPathName->Length += sNameLenDelta;
2333 ComponentName->Length += sNameLenDelta;
2335 ComponentName->MaximumLength = ComponentName->Length;
2337 if ( RemainingPath->Buffer)
2340 RemainingPath->Buffer += sNameLenDelta/sizeof( WCHAR);
2343 try_return( ntStatus);
2347 // Need to re-allocate the buffer
2350 uniPathName.Length = FullPathName->Length -
2351 ComponentName->Length +
2352 SubstituteName->Length;
2354 uniPathName.MaximumLength = FullPathName->MaximumLength + PAGE_SIZE;
2356 uniPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2357 uniPathName.MaximumLength,
2358 AFS_NAME_BUFFER_FOUR_TAG);
2360 if( uniPathName.Buffer == NULL)
2363 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2366 usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2368 usPrefixNameLen *= sizeof( WCHAR);
2370 RtlZeroMemory( uniPathName.Buffer,
2371 uniPathName.MaximumLength);
2373 RtlCopyMemory( uniPathName.Buffer,
2374 FullPathName->Buffer,
2377 RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen/sizeof( WCHAR))],
2378 SubstituteName->Buffer,
2379 SubstituteName->Length);
2381 if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2384 RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen + SubstituteName->Length)/sizeof( WCHAR)],
2385 &FullPathName->Buffer[ (usPrefixNameLen + ComponentName->Length)/sizeof( WCHAR)],
2386 FullPathName->Length - usPrefixNameLen - ComponentName->Length);
2389 ComponentName->Buffer = uniPathName.Buffer + (ComponentName->Buffer - FullPathName->Buffer);
2391 ComponentName->Length += sNameLenDelta;
2393 ComponentName->MaximumLength = ComponentName->Length;
2395 if ( RemainingPath->Buffer)
2398 RemainingPath->Buffer = uniPathName.Buffer
2399 + (RemainingPath->Buffer - FullPathName->Buffer)
2400 + sNameLenDelta/sizeof( WCHAR);
2405 AFSExFreePool( FullPathName->Buffer);
2408 *FullPathName = uniPathName;
2419 AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
2423 NTSTATUS ntStatus = STATUS_SUCCESS;
2424 AFSObjectInfoCB *pCurrentObject = NULL;
2425 AFSObjectInfoCB *pNextObject = NULL;
2427 AFSFcb *pFcb = NULL;
2433 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2434 AFS_TRACE_LEVEL_VERBOSE,
2435 "AFSInvalidateVolume Invalidate volume fid %08lX-%08lX-%08lX-%08lX Reason %08lX\n",
2436 VolumeCB->ObjectInformation.FileId.Cell,
2437 VolumeCB->ObjectInformation.FileId.Volume,
2438 VolumeCB->ObjectInformation.FileId.Vnode,
2439 VolumeCB->ObjectInformation.FileId.Unique,
2443 // Depending on the reason for invalidation then perform work on the node
2449 case AFS_INVALIDATE_DELETED:
2453 // Mark this volume as invalid
2456 SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
2458 SetFlag( VolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE);
2465 // Invalidate the volume root directory
2468 pCurrentObject = &VolumeCB->ObjectInformation;
2470 if ( pCurrentObject )
2473 lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
2475 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2476 AFS_TRACE_LEVEL_VERBOSE,
2477 "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2481 AFSInvalidateObject( &pCurrentObject,
2484 if ( pCurrentObject)
2487 lCount = InterlockedDecrement( &pCurrentObject->ObjectReferenceCount);
2489 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2490 AFS_TRACE_LEVEL_VERBOSE,
2491 "AFSInvalidateVolumeObjects Decrement count on object %08lX Cnt %d\n",
2498 // Apply invalidation to all other volume objects
2501 AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2504 pCurrentObject = VolumeCB->ObjectInfoListHead;
2506 if ( pCurrentObject)
2510 // Reference the node so it won't be torn down
2513 lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
2515 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2516 AFS_TRACE_LEVEL_VERBOSE,
2517 "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2522 while( pCurrentObject != NULL)
2525 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2531 // Reference the node so it won't be torn down
2534 lCount = InterlockedIncrement( &pNextObject->ObjectReferenceCount);
2536 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2537 AFS_TRACE_LEVEL_VERBOSE,
2538 "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2543 AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2545 AFSInvalidateObject( &pCurrentObject,
2548 if ( pCurrentObject )
2551 lCount = InterlockedDecrement( &pCurrentObject->ObjectReferenceCount);
2553 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2554 AFS_TRACE_LEVEL_VERBOSE,
2555 "AFSInvalidateVolumeObjects Decrement count on object %08lX Cnt %d\n",
2560 AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2563 pCurrentObject = pNextObject;
2566 AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2573 AFSInvalidateAllVolumes( VOID)
2575 AFSVolumeCB *pVolumeCB = NULL;
2576 AFSVolumeCB *pNextVolumeCB = NULL;
2577 AFSDeviceExt *pRDRDeviceExt = NULL;
2580 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2582 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2583 AFS_TRACE_LEVEL_VERBOSE,
2584 "AFSInvalidateAllVolumes Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
2585 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2586 PsGetCurrentThread());
2588 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2591 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
2596 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2597 AFS_TRACE_LEVEL_VERBOSE,
2598 "AFSInvalidateAllVolumes Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
2599 pVolumeCB->ObjectInfoTree.TreeLock,
2600 PsGetCurrentThread());
2602 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2605 while( pVolumeCB != NULL)
2608 pNextVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2613 lCount = InterlockedIncrement( &pNextVolumeCB->VolumeReferenceCount);
2616 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2618 // do I need to hold the volume lock here?
2620 AFSInvalidateVolume( pVolumeCB, AFS_INVALIDATE_EXPIRED);
2622 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2625 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2627 pVolumeCB = pNextVolumeCB;
2630 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2634 AFSVerifyEntry( IN GUID *AuthGroup,
2635 IN AFSDirectoryCB *DirEntry)
2638 NTSTATUS ntStatus = STATUS_SUCCESS;
2639 AFSDirEnumEntry *pDirEnumEntry = NULL;
2640 AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
2641 IO_STATUS_BLOCK stIoStatus;
2646 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2647 AFS_TRACE_LEVEL_VERBOSE_2,
2648 "AFSVerifyEntry Verifying entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2649 &DirEntry->NameInformation.FileName,
2650 pObjectInfo->FileId.Cell,
2651 pObjectInfo->FileId.Volume,
2652 pObjectInfo->FileId.Vnode,
2653 pObjectInfo->FileId.Unique);
2655 ntStatus = AFSEvaluateTargetByID( pObjectInfo,
2660 if( !NT_SUCCESS( ntStatus))
2663 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2664 AFS_TRACE_LEVEL_ERROR,
2665 "AFSValidateEntry Evaluate Target failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2666 &DirEntry->NameInformation.FileName,
2667 pObjectInfo->FileId.Cell,
2668 pObjectInfo->FileId.Volume,
2669 pObjectInfo->FileId.Vnode,
2670 pObjectInfo->FileId.Unique,
2673 try_return( ntStatus);
2677 // Check the data version of the file
2680 if( pObjectInfo->DataVersion.QuadPart == pDirEnumEntry->DataVersion.QuadPart &&
2681 !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2684 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2685 AFS_TRACE_LEVEL_VERBOSE,
2686 "AFSVerifyEntry No DV change %I64X for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2687 pObjectInfo->DataVersion.QuadPart,
2688 &DirEntry->NameInformation.FileName,
2689 pObjectInfo->FileId.Cell,
2690 pObjectInfo->FileId.Volume,
2691 pObjectInfo->FileId.Vnode,
2692 pObjectInfo->FileId.Unique);
2695 // We are ok, just get out
2698 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2700 try_return( ntStatus = STATUS_SUCCESS);
2704 // New data version so we will need to process the node based on the type
2707 switch( pDirEnumEntry->FileType)
2710 case AFS_FILE_TYPE_MOUNTPOINT:
2714 // For a mount point we need to ensure the target is the same
2717 if( !AFSIsEqualFID( &pObjectInfo->TargetFileId,
2718 &pDirEnumEntry->TargetFileId))
2724 // Update the metadata for the entry
2727 ntStatus = AFSUpdateMetaData( DirEntry,
2730 if( NT_SUCCESS( ntStatus))
2733 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2739 case AFS_FILE_TYPE_SYMLINK:
2742 ASSERT( pDirEnumEntry->TargetNameLength > 0);
2745 // Update the metadata for the entry
2748 ntStatus = AFSUpdateMetaData( DirEntry,
2751 if( NT_SUCCESS( ntStatus))
2754 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2760 case AFS_FILE_TYPE_FILE:
2762 FILE_OBJECT * pCCFileObject = NULL;
2763 BOOLEAN bPurgeExtents = FALSE;
2765 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2767 bPurgeExtents = TRUE;
2769 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2770 AFS_TRACE_LEVEL_VERBOSE,
2771 "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2772 &DirEntry->NameInformation.FileName,
2773 pObjectInfo->FileId.Cell,
2774 pObjectInfo->FileId.Volume,
2775 pObjectInfo->FileId.Vnode,
2776 pObjectInfo->FileId.Unique);
2778 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
2782 // Update the metadata for the entry
2785 ntStatus = AFSUpdateMetaData( DirEntry,
2788 if( !NT_SUCCESS( ntStatus))
2791 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2792 AFS_TRACE_LEVEL_ERROR,
2793 "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
2794 &DirEntry->NameInformation.FileName,
2795 pObjectInfo->FileId.Cell,
2796 pObjectInfo->FileId.Volume,
2797 pObjectInfo->FileId.Vnode,
2798 pObjectInfo->FileId.Unique,
2804 if( pObjectInfo->Fcb != NULL)
2807 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2808 AFS_TRACE_LEVEL_VERBOSE,
2809 "AFSVerifyEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2810 &DirEntry->NameInformation.FileName,
2811 pObjectInfo->FileId.Cell,
2812 pObjectInfo->FileId.Volume,
2813 pObjectInfo->FileId.Vnode,
2814 pObjectInfo->FileId.Unique);
2816 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
2822 CcFlushCache( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2827 if( !NT_SUCCESS( stIoStatus.Status))
2830 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2831 AFS_TRACE_LEVEL_ERROR,
2832 "AFSVerifyEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
2833 &DirEntry->NameInformation.FileName,
2834 pObjectInfo->FileId.Cell,
2835 pObjectInfo->FileId.Volume,
2836 pObjectInfo->FileId.Vnode,
2837 pObjectInfo->FileId.Unique,
2839 stIoStatus.Information);
2841 ntStatus = stIoStatus.Status;
2847 CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2853 __except( EXCEPTION_EXECUTE_HANDLER)
2855 ntStatus = GetExceptionCode();
2857 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2858 AFS_TRACE_LEVEL_ERROR,
2859 "AFSVerifyEntry CcFlushCache or CcPurgeCacheSection Exception %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2860 &DirEntry->NameInformation.FileName,
2861 pObjectInfo->FileId.Cell,
2862 pObjectInfo->FileId.Volume,
2863 pObjectInfo->FileId.Vnode,
2864 pObjectInfo->FileId.Unique,
2868 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
2872 AFSFlushExtents( pObjectInfo->Fcb,
2877 // Reacquire the Fcb to purge the cache
2880 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2881 AFS_TRACE_LEVEL_VERBOSE,
2882 "AFSVerifyEntry Acquiring Fcb lock %08lX EXCL %08lX\n",
2883 &pObjectInfo->Fcb->NPFcb->Resource,
2884 PsGetCurrentThread());
2886 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
2890 // Update file sizes
2893 pObjectInfo->Fcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart;
2894 pObjectInfo->Fcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart;
2895 pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
2897 pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
2899 if ( pCCFileObject != NULL)
2901 CcSetFileSizes( pCCFileObject,
2902 (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
2905 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
2909 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2910 AFS_TRACE_LEVEL_WARNING,
2911 "AFSValidateEntry Fcb NULL %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2912 &DirEntry->NameInformation.FileName,
2913 pObjectInfo->FileId.Cell,
2914 pObjectInfo->FileId.Volume,
2915 pObjectInfo->FileId.Vnode,
2916 pObjectInfo->FileId.Unique);
2919 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2924 case AFS_FILE_TYPE_DIRECTORY:
2927 AFSFcb *pCurrentFcb = NULL;
2928 AFSDirectoryCB *pCurrentDirEntry = NULL;
2931 // For a directory or root entry flush the content of
2932 // the directory enumeration.
2935 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
2938 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2939 AFS_TRACE_LEVEL_VERBOSE_2,
2940 "AFSVerifyEntry Validating directory content for entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2941 &DirEntry->NameInformation.FileName,
2942 pObjectInfo->FileId.Cell,
2943 pObjectInfo->FileId.Volume,
2944 pObjectInfo->FileId.Vnode,
2945 pObjectInfo->FileId.Unique);
2947 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2950 ntStatus = AFSValidateDirectoryCache( pObjectInfo,
2953 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2955 if ( !NT_SUCCESS( ntStatus))
2958 try_return( ntStatus);
2963 // Update the metadata for the entry
2966 ntStatus = AFSUpdateMetaData( DirEntry,
2969 if( NT_SUCCESS( ntStatus))
2972 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2978 case AFS_FILE_TYPE_DFSLINK:
2981 UNICODE_STRING uniTargetName;
2984 // For a DFS link need to check the target name has not changed
2987 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
2989 uniTargetName.MaximumLength = uniTargetName.Length;
2991 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
2993 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
2996 if( DirEntry->NameInformation.TargetName.Length == 0 ||
2997 RtlCompareUnicodeString( &uniTargetName,
2998 &DirEntry->NameInformation.TargetName,
3003 // Update the target name
3006 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3008 uniTargetName.Buffer,
3009 uniTargetName.Length);
3011 if( !NT_SUCCESS( ntStatus))
3014 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3020 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3023 // Update the metadata for the entry
3026 ntStatus = AFSUpdateMetaData( DirEntry,
3029 if( NT_SUCCESS( ntStatus))
3032 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3040 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3041 AFS_TRACE_LEVEL_WARNING,
3042 "AFSVerifyEntry Attempt to verify node of type %d %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3043 pObjectInfo->FileType,
3044 &DirEntry->NameInformation.FileName,
3045 pObjectInfo->FileId.Cell,
3046 pObjectInfo->FileId.Volume,
3047 pObjectInfo->FileId.Vnode,
3048 pObjectInfo->FileId.Unique);
3055 if( pDirEnumEntry != NULL)
3058 AFSExFreePool( pDirEnumEntry);
3066 AFSSetVolumeState( IN AFSVolumeStatusCB *VolumeStatus)
3069 NTSTATUS ntStatus = STATUS_SUCCESS;
3070 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
3071 ULONGLONG ullIndex = 0;
3072 AFSVolumeCB *pVolumeCB = NULL;
3073 AFSFcb *pFcb = NULL;
3074 AFSObjectInfoCB *pCurrentObject = NULL;
3080 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3081 AFS_TRACE_LEVEL_VERBOSE,
3082 "AFSSetVolumeState Marking volume state %d Volume Cell %08lX Volume %08lX\n",
3083 VolumeStatus->Online,
3084 VolumeStatus->FileID.Cell,
3085 VolumeStatus->FileID.Volume);
3088 // Need to locate the Fcb for the directory to purge
3091 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3092 AFS_TRACE_LEVEL_VERBOSE,
3093 "AFSSetVolumeState Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
3094 &pDevExt->Specific.RDR.VolumeTreeLock,
3095 PsGetCurrentThread());
3097 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
3100 // Locate the volume node
3103 ullIndex = AFSCreateHighIndex( &VolumeStatus->FileID);
3105 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
3107 (AFSBTreeEntry **)&pVolumeCB);
3109 if( pVolumeCB != NULL)
3112 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
3114 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3117 // Set the volume state accordingly
3120 if( VolumeStatus->Online)
3123 InterlockedAnd( (LONG *)&(pVolumeCB->Flags), ~AFS_VOLUME_FLAGS_OFFLINE);
3128 InterlockedOr( (LONG *)&(pVolumeCB->Flags), AFS_VOLUME_FLAGS_OFFLINE);
3131 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
3134 pCurrentObject = pVolumeCB->ObjectInfoListHead;;
3136 while( pCurrentObject != NULL)
3139 if( VolumeStatus->Online)
3142 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
3144 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
3146 pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
3151 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
3154 pFcb = pCurrentObject->Fcb;
3157 !(VolumeStatus->Online) &&
3158 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
3161 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3162 AFS_TRACE_LEVEL_ERROR,
3163 "AFSSetVolumeState Marking volume offline and canceling extents Volume Cell %08lX Volume %08lX\n",
3164 VolumeStatus->FileID.Cell,
3165 VolumeStatus->FileID.Volume);
3168 // Clear out the extents
3171 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3172 AFS_TRACE_LEVEL_VERBOSE,
3173 "AFSSetVolumeState Acquiring Fcb extents lock %08lX EXCL %08lX\n",
3174 &pFcb->NPFcb->Specific.File.ExtentsResource,
3175 PsGetCurrentThread());
3177 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
3180 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
3182 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
3186 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3187 AFS_TRACE_LEVEL_VERBOSE,
3188 "AFSSetVolumeState Releasing Fcb extents lock %08lX EXCL %08lX\n",
3189 &pFcb->NPFcb->Specific.File.ExtentsResource,
3190 PsGetCurrentThread());
3192 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
3195 // And get rid of them (note this involves waiting
3196 // for any writes or reads to the cache to complete)
3199 (VOID) AFSTearDownFcbExtents( pFcb,
3203 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
3206 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
3208 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
3213 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3221 AFSSetNetworkState( IN AFSNetworkStatusCB *NetworkStatus)
3224 NTSTATUS ntStatus = STATUS_SUCCESS;
3229 if( AFSGlobalRoot == NULL)
3232 try_return( ntStatus);
3235 AFSAcquireExcl( AFSGlobalRoot->VolumeLock,
3239 // Set the network state according to the information
3242 if( NetworkStatus->Online)
3245 ClearFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3250 SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3253 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3264 AFSValidateDirectoryCache( IN AFSObjectInfoCB *ObjectInfo,
3268 NTSTATUS ntStatus = STATUS_SUCCESS;
3269 BOOLEAN bAcquiredLock = FALSE;
3270 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
3271 AFSFcb *pFcb = NULL;
3276 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3277 AFS_TRACE_LEVEL_VERBOSE,
3278 "AFSValidateDirectoryCache Validating content for FID %08lX-%08lX-%08lX-%08lX\n",
3279 ObjectInfo->FileId.Cell,
3280 ObjectInfo->FileId.Volume,
3281 ObjectInfo->FileId.Vnode,
3282 ObjectInfo->FileId.Unique);
3284 if( !ExIsResourceAcquiredLite( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock))
3287 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3288 AFS_TRACE_LEVEL_VERBOSE,
3289 "AFSValidateDirectoryCache Acquiring DirectoryNodeHdr.TreeLock lock %08lX EXCL %08lX\n",
3290 ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3291 PsGetCurrentThread());
3293 AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3296 bAcquiredLock = TRUE;
3300 // Check for inconsistency between DirectoryNodeList and DirectoryNodeCount
3303 if ( ObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL &&
3304 ObjectInfo->Specific.Directory.DirectoryNodeCount > 0)
3307 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3308 AFS_TRACE_LEVEL_ERROR,
3309 "AFSValidateDirectoryCache Empty Node List but Non-Zero Node Count %08lX for dir FID %08lX-%08lX-%08lX-%08lX\n",
3310 ObjectInfo->Specific.Directory.DirectoryNodeCount,
3311 ObjectInfo->FileId.Cell,
3312 ObjectInfo->FileId.Volume,
3313 ObjectInfo->FileId.Vnode,
3314 ObjectInfo->FileId.Unique);
3318 // Reset the directory list information by clearing all valid entries
3321 pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3323 while( pCurrentDirEntry != NULL)
3326 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3328 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
3332 // If this entry has been deleted then process it here
3335 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
3336 pCurrentDirEntry->OpenReferenceCount == 0)
3339 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3340 AFS_TRACE_LEVEL_VERBOSE,
3341 "AFSValidateDirectoryCache Deleting dir entry %p name %wZ\n",
3343 &pCurrentDirEntry->NameInformation.FileName);
3345 AFSDeleteDirEntry( ObjectInfo,
3351 ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID);
3353 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3354 AFS_TRACE_LEVEL_VERBOSE,
3355 "AFSValidateDirectoryCache Clear VALID flag on DE %p Reference count %08lX\n",
3357 pCurrentDirEntry->OpenReferenceCount);
3360 // We pull the short name from the parent tree since it could change below
3363 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
3366 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3367 AFS_TRACE_LEVEL_VERBOSE,
3368 "AFSValidateDirectoryCache Removing DE %p (%08lX) from shortname tree for %wZ\n",
3370 pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3371 &pCurrentDirEntry->NameInformation.FileName);
3373 AFSRemoveShortNameDirEntry( &ObjectInfo->Specific.Directory.ShortNameTree,
3376 ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3381 pCurrentDirEntry = pNextDirEntry;
3385 // Reget the directory contents
3388 ntStatus = AFSVerifyDirectoryContent( ObjectInfo,
3391 if ( !NT_SUCCESS( ntStatus))
3393 try_return( ntStatus);
3397 // Now start again and tear down any entries not valid
3400 pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3402 while( pCurrentDirEntry != NULL)
3405 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3407 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID))
3410 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME) &&
3411 pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex > 0)
3414 if( ObjectInfo->Specific.Directory.ShortNameTree == NULL)
3417 ObjectInfo->Specific.Directory.ShortNameTree = pCurrentDirEntry;
3419 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3420 AFS_TRACE_LEVEL_VERBOSE,
3421 "AFSValidateDirectoryCache Insert DE %p to head of shortname tree for %wZ\n",
3423 &pCurrentDirEntry->NameInformation.FileName);
3425 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3430 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfo->Specific.Directory.ShortNameTree,
3433 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3434 AFS_TRACE_LEVEL_VERBOSE,
3435 "AFSValidateDirectoryCache Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
3437 pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3438 &pCurrentDirEntry->NameInformation.FileName);
3442 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3444 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3445 AFS_TRACE_LEVEL_VERBOSE,
3446 "AFSValidateDirectoryCache Insert DE %p to shortname tree for %wZ\n",
3448 &pCurrentDirEntry->NameInformation.FileName);
3453 pCurrentDirEntry = pNextDirEntry;
3458 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3459 AFS_TRACE_LEVEL_VERBOSE,
3460 "AFSValidateDirectoryCache Processing INVALID DE %p Reference count %08lX\n",
3462 pCurrentDirEntry->OpenReferenceCount);
3464 if( pCurrentDirEntry->OpenReferenceCount == 0)
3467 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3468 AFS_TRACE_LEVEL_VERBOSE,
3469 "AFSValidateDirectoryCache Deleting dir entry %wZ from parent FID %08lX-%08lX-%08lX-%08lX\n",
3470 &pCurrentDirEntry->NameInformation.FileName,
3471 ObjectInfo->FileId.Cell,
3472 ObjectInfo->FileId.Volume,
3473 ObjectInfo->FileId.Vnode,
3474 ObjectInfo->FileId.Unique);
3476 AFSDeleteDirEntry( ObjectInfo,
3482 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3483 AFS_TRACE_LEVEL_VERBOSE,
3484 "AFSValidateDirectoryCache Setting dir entry %p Name %wZ DELETED in parent FID %08lX-%08lX-%08lX-%08lX\n",
3486 &pCurrentDirEntry->NameInformation.FileName,
3487 ObjectInfo->FileId.Cell,
3488 ObjectInfo->FileId.Volume,
3489 ObjectInfo->FileId.Vnode,
3490 ObjectInfo->FileId.Unique);
3492 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
3494 AFSRemoveNameEntry( ObjectInfo,
3498 pCurrentDirEntry = pNextDirEntry;
3502 if( !AFSValidateDirList( ObjectInfo))
3505 AFSPrint("AFSValidateDirectoryCache Invalid count ...\n");
3514 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3522 AFSIsVolumeFID( IN AFSFileID *FileID)
3525 BOOLEAN bIsVolume = FALSE;
3527 if( FileID->Vnode == 1 &&
3528 FileID->Unique == 1)
3538 AFSIsFinalNode( IN AFSFcb *Fcb)
3541 BOOLEAN bIsFinalNode = FALSE;
3543 if( Fcb->Header.NodeTypeCode == AFS_ROOT_FCB ||
3544 Fcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB ||
3545 Fcb->Header.NodeTypeCode == AFS_FILE_FCB ||
3546 Fcb->Header.NodeTypeCode == AFS_DFS_LINK_FCB ||
3547 Fcb->Header.NodeTypeCode == AFS_INVALID_FCB )
3550 bIsFinalNode = TRUE;
3555 ASSERT( Fcb->Header.NodeTypeCode == AFS_MOUNT_POINT_FCB ||
3556 Fcb->Header.NodeTypeCode == AFS_SYMBOLIC_LINK_FCB);
3559 return bIsFinalNode;
3563 AFSUpdateMetaData( IN AFSDirectoryCB *DirEntry,
3564 IN AFSDirEnumEntry *DirEnumEntry)
3567 NTSTATUS ntStatus = STATUS_SUCCESS;
3568 UNICODE_STRING uniTargetName;
3569 AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
3574 pObjectInfo->TargetFileId = DirEnumEntry->TargetFileId;
3576 pObjectInfo->Expiration = DirEnumEntry->Expiration;
3578 pObjectInfo->DataVersion = DirEnumEntry->DataVersion;
3580 pObjectInfo->FileType = DirEnumEntry->FileType;
3582 pObjectInfo->CreationTime = DirEnumEntry->CreationTime;
3584 pObjectInfo->LastAccessTime = DirEnumEntry->LastAccessTime;
3586 pObjectInfo->LastWriteTime = DirEnumEntry->LastWriteTime;
3588 pObjectInfo->ChangeTime = DirEnumEntry->ChangeTime;
3590 pObjectInfo->EndOfFile = DirEnumEntry->EndOfFile;
3592 pObjectInfo->AllocationSize = DirEnumEntry->AllocationSize;
3594 pObjectInfo->FileAttributes = DirEnumEntry->FileAttributes;
3596 if( pObjectInfo->FileType == AFS_FILE_TYPE_MOUNTPOINT)
3599 pObjectInfo->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
3602 if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK ||
3603 pObjectInfo->FileType == AFS_FILE_TYPE_DFSLINK)
3606 pObjectInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
3609 pObjectInfo->EaSize = DirEnumEntry->EaSize;
3611 pObjectInfo->Links = DirEnumEntry->Links;
3613 if( DirEnumEntry->TargetNameLength > 0)
3617 // Update the target name information if needed
3620 uniTargetName.Length = (USHORT)DirEnumEntry->TargetNameLength;
3622 uniTargetName.MaximumLength = uniTargetName.Length;
3624 uniTargetName.Buffer = (WCHAR *)((char *)DirEnumEntry + DirEnumEntry->TargetNameOffset);
3626 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3629 if( DirEntry->NameInformation.TargetName.Length == 0 ||
3630 RtlCompareUnicodeString( &uniTargetName,
3631 &DirEntry->NameInformation.TargetName,
3636 // Update the target name
3639 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3641 uniTargetName.Buffer,
3642 uniTargetName.Length);
3644 if( !NT_SUCCESS( ntStatus))
3647 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3649 try_return( ntStatus);
3653 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3655 else if( DirEntry->NameInformation.TargetName.Length > 0)
3658 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3661 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER) &&
3662 DirEntry->NameInformation.TargetName.Buffer != NULL)
3664 AFSExFreePool( DirEntry->NameInformation.TargetName.Buffer);
3667 ClearFlag( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER);
3669 DirEntry->NameInformation.TargetName.Length = 0;
3670 DirEntry->NameInformation.TargetName.MaximumLength = 0;
3671 DirEntry->NameInformation.TargetName.Buffer = NULL;
3673 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3685 AFSValidateEntry( IN AFSDirectoryCB *DirEntry,
3687 IN BOOLEAN PurgeContent,
3688 IN BOOLEAN FastCall)
3691 NTSTATUS ntStatus = STATUS_SUCCESS;
3692 LARGE_INTEGER liSystemTime;
3693 AFSDirEnumEntry *pDirEnumEntry = NULL;
3694 AFSFcb *pCurrentFcb = NULL;
3695 BOOLEAN bReleaseFcb = FALSE;
3696 AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
3702 // If we have an Fcb hanging off the directory entry then be sure to acquire the locks in the
3706 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3707 AFS_TRACE_LEVEL_VERBOSE_2,
3708 "AFSValidateEntry Validating entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3709 &DirEntry->NameInformation.FileName,
3710 pObjectInfo->FileId.Cell,
3711 pObjectInfo->FileId.Volume,
3712 pObjectInfo->FileId.Vnode,
3713 pObjectInfo->FileId.Unique);
3716 // If this is a fake node then bail since the service knows nothing about it
3719 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_FAKE))
3722 try_return( ntStatus);
3726 pObjectInfo->Fcb != NULL)
3729 pCurrentFcb = pObjectInfo->Fcb;
3731 if( !ExIsResourceAcquiredLite( &pCurrentFcb->NPFcb->Resource))
3734 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3735 AFS_TRACE_LEVEL_VERBOSE,
3736 "AFSValidateEntry Acquiring Fcb lock %08lX EXCL %08lX\n",
3737 &pCurrentFcb->NPFcb->Resource,
3738 PsGetCurrentThread());
3740 AFSAcquireExcl( &pCurrentFcb->NPFcb->Resource,
3748 // This routine ensures that the current entry is valid by:
3750 // 1) Checking that the expiration time is non-zero and after where we
3754 KeQuerySystemTime( &liSystemTime);
3756 if( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) &&
3757 !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
3758 !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA) &&
3759 pObjectInfo->Expiration.QuadPart >= liSystemTime.QuadPart)
3762 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3763 AFS_TRACE_LEVEL_VERBOSE_2,
3764 "AFSValidateEntry Directory entry %wZ FID %08lX-%08lX-%08lX-%08lX VALID\n",
3765 &DirEntry->NameInformation.FileName,
3766 pObjectInfo->FileId.Cell,
3767 pObjectInfo->FileId.Volume,
3768 pObjectInfo->FileId.Vnode,
3769 pObjectInfo->FileId.Unique);
3771 try_return( ntStatus);
3775 // This node requires updating
3778 ntStatus = AFSEvaluateTargetByID( pObjectInfo,
3783 if( !NT_SUCCESS( ntStatus))
3786 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3787 AFS_TRACE_LEVEL_ERROR,
3788 "AFSValidateEntry Failed to evaluate entry FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3790 &DirEntry->NameInformation.FileName,
3791 pObjectInfo->FileId.Cell,
3792 pObjectInfo->FileId.Volume,
3793 pObjectInfo->FileId.Vnode,
3794 pObjectInfo->FileId.Unique,
3798 // Failed validation of node so return access-denied
3801 try_return( ntStatus);
3804 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3805 AFS_TRACE_LEVEL_VERBOSE,
3806 "AFSValidateEntry Validating entry FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX DV %I64X returned DV %I64X FT %d\n",
3808 &DirEntry->NameInformation.FileName,
3809 pObjectInfo->FileId.Cell,
3810 pObjectInfo->FileId.Volume,
3811 pObjectInfo->FileId.Vnode,
3812 pObjectInfo->FileId.Unique,
3813 pObjectInfo->DataVersion.QuadPart,
3814 pDirEnumEntry->DataVersion.QuadPart,
3815 pDirEnumEntry->FileType);
3819 // Based on the file type, process the node
3822 switch( pDirEnumEntry->FileType)
3825 case AFS_FILE_TYPE_MOUNTPOINT:
3829 // Update the metadata for the entry
3832 ntStatus = AFSUpdateMetaData( DirEntry,
3835 if( NT_SUCCESS( ntStatus))
3838 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
3844 case AFS_FILE_TYPE_SYMLINK:
3845 case AFS_FILE_TYPE_DFSLINK:
3849 // Update the metadata for the entry
3852 ntStatus = AFSUpdateMetaData( DirEntry,
3855 if( NT_SUCCESS( ntStatus))
3858 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
3864 case AFS_FILE_TYPE_FILE:
3868 // For a file where the data version has become invalid we need to
3869 // fail any current extent requests and purge the cache for the file
3870 // Can't hold the Fcb resource while doing this
3873 if( pCurrentFcb != NULL &&
3874 (pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart ||
3875 BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA)))
3878 IO_STATUS_BLOCK stIoStatus;
3879 BOOLEAN bPurgeExtents = FALSE;
3881 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3882 AFS_TRACE_LEVEL_VERBOSE_2,
3883 "AFSValidateEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3884 &DirEntry->NameInformation.FileName,
3885 pObjectInfo->FileId.Cell,
3886 pObjectInfo->FileId.Volume,
3887 pObjectInfo->FileId.Vnode,
3888 pObjectInfo->FileId.Unique);
3890 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
3892 bPurgeExtents = TRUE;
3894 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3895 AFS_TRACE_LEVEL_VERBOSE,
3896 "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3897 &DirEntry->NameInformation.FileName,
3898 pObjectInfo->FileId.Cell,
3899 pObjectInfo->FileId.Volume,
3900 pObjectInfo->FileId.Vnode,
3901 pObjectInfo->FileId.Unique);
3903 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
3909 CcFlushCache( &pCurrentFcb->NPFcb->SectionObjectPointers,
3914 if( !NT_SUCCESS( stIoStatus.Status))
3917 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
3918 AFS_TRACE_LEVEL_ERROR,
3919 "AFSValidateEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
3920 &DirEntry->NameInformation.FileName,
3921 pObjectInfo->FileId.Cell,
3922 pObjectInfo->FileId.Volume,
3923 pObjectInfo->FileId.Vnode,
3924 pObjectInfo->FileId.Unique,
3926 stIoStatus.Information);
3928 ntStatus = stIoStatus.Status;
3934 CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
3940 __except( EXCEPTION_EXECUTE_HANDLER)
3942 ntStatus = GetExceptionCode();
3944 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
3945 AFS_TRACE_LEVEL_ERROR,
3946 "AFSValidateEntry CcFlushCache or CcPurgeCacheSection exception %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
3947 &DirEntry->NameInformation.FileName,
3948 pObjectInfo->FileId.Cell,
3949 pObjectInfo->FileId.Volume,
3950 pObjectInfo->FileId.Vnode,
3951 pObjectInfo->FileId.Unique,
3956 AFSReleaseResource( &pCurrentFcb->NPFcb->Resource);
3960 AFSFlushExtents( pCurrentFcb,
3965 // Reacquire the Fcb to purge the cache
3968 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3969 AFS_TRACE_LEVEL_VERBOSE,
3970 "AFSValidateEntry Acquiring Fcb lock %08lX EXCL %08lX\n",
3971 &pCurrentFcb->NPFcb->Resource,
3972 PsGetCurrentThread());
3974 AFSAcquireExcl( &pCurrentFcb->NPFcb->Resource,
3979 // Update the metadata for the entry
3982 ntStatus = AFSUpdateMetaData( DirEntry,
3985 if( !NT_SUCCESS( ntStatus))
3988 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3989 AFS_TRACE_LEVEL_ERROR,
3990 "AFSValidateEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
3991 &DirEntry->NameInformation.FileName,
3992 pObjectInfo->FileId.Cell,
3993 pObjectInfo->FileId.Volume,
3994 pObjectInfo->FileId.Vnode,
3995 pObjectInfo->FileId.Unique,
4001 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
4004 // Update file sizes
4007 if( pObjectInfo->Fcb != NULL)
4009 FILE_OBJECT *pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
4011 pObjectInfo->Fcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart;
4012 pObjectInfo->Fcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart;
4013 pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
4015 if ( pCCFileObject != NULL)
4017 CcSetFileSizes( pCCFileObject,
4018 (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
4025 case AFS_FILE_TYPE_DIRECTORY:
4028 AFSDirectoryCB *pCurrentDirEntry = NULL;
4030 if( pCurrentFcb != NULL &&
4031 pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
4035 // For a directory or root entry flush the content of
4036 // the directory enumeration.
4039 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4040 AFS_TRACE_LEVEL_VERBOSE,
4041 "AFSValidateEntry Acquiring DirectoryNodeHdr.TreeLock lock %08lX EXCL %08lX\n",
4042 pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
4043 PsGetCurrentThread());
4045 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
4048 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4049 AFS_TRACE_LEVEL_VERBOSE_2,
4050 "AFSValidateEntry Validating directory content for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4051 &DirEntry->NameInformation.FileName,
4052 pObjectInfo->FileId.Cell,
4053 pObjectInfo->FileId.Volume,
4054 pObjectInfo->FileId.Vnode,
4055 pObjectInfo->FileId.Unique);
4057 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
4060 AFSValidateDirectoryCache( pCurrentFcb->ObjectInformation,
4063 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
4066 if( !NT_SUCCESS( ntStatus))
4069 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4070 AFS_TRACE_LEVEL_ERROR,
4071 "AFSValidateEntry Failed to re-enumerate %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4072 &DirEntry->NameInformation.FileName,
4073 pObjectInfo->FileId.Cell,
4074 pObjectInfo->FileId.Volume,
4075 pObjectInfo->FileId.Vnode,
4076 pObjectInfo->FileId.Unique,
4084 // Update the metadata for the entry
4087 ntStatus = AFSUpdateMetaData( DirEntry,
4090 if( NT_SUCCESS( ntStatus))
4093 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
4101 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4102 AFS_TRACE_LEVEL_WARNING,
4103 "AFSValidateEntry Attempt to verify node of type %d FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4104 pObjectInfo->FileType,
4106 &DirEntry->NameInformation.FileName,
4107 pObjectInfo->FileId.Cell,
4108 pObjectInfo->FileId.Volume,
4109 pObjectInfo->FileId.Vnode,
4110 pObjectInfo->FileId.Unique);
4120 AFSReleaseResource( &pCurrentFcb->NPFcb->Resource);
4123 if( pDirEnumEntry != NULL)
4126 AFSExFreePool( pDirEnumEntry);
4134 AFSInitializeSpecialShareNameList()
4137 NTSTATUS ntStatus = STATUS_SUCCESS;
4138 AFSDirectoryCB *pDirNode = NULL, *pLastDirNode = NULL;
4139 AFSObjectInfoCB *pObjectInfoCB = NULL;
4140 UNICODE_STRING uniShareName;
4141 ULONG ulEntryLength = 0;
4142 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
4147 RtlInitUnicodeString( &uniShareName,
4150 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
4153 if( pObjectInfoCB == NULL)
4156 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4159 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4160 AFS_TRACE_LEVEL_VERBOSE,
4161 "AFSInitializeSpecialShareNameList (srvsvc) Initializing count (1) on object %08lX\n",
4164 pObjectInfoCB->ObjectReferenceCount = 1;
4166 pObjectInfoCB->FileType = AFS_FILE_TYPE_SPECIAL_SHARE_NAME;
4168 ulEntryLength = sizeof( AFSDirectoryCB) +
4169 uniShareName.Length;
4171 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
4175 if( pDirNode == NULL)
4178 AFSDeleteObjectInfo( pObjectInfoCB);
4180 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4183 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
4184 sizeof( AFSNonPagedDirectoryCB),
4185 AFS_DIR_ENTRY_NP_TAG);
4187 if( pNonPagedDirEntry == NULL)
4190 ExFreePool( pDirNode);
4192 AFSDeleteObjectInfo( pObjectInfoCB);
4194 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4197 RtlZeroMemory( pDirNode,
4200 RtlZeroMemory( pNonPagedDirEntry,
4201 sizeof( AFSNonPagedDirectoryCB));
4203 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
4205 pDirNode->NonPaged = pNonPagedDirEntry;
4207 pDirNode->ObjectInformation = pObjectInfoCB;
4213 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_SERVER_SERVICE);
4215 pDirNode->NameInformation.FileName.Length = uniShareName.Length;
4217 pDirNode->NameInformation.FileName.MaximumLength = uniShareName.Length;
4219 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
4221 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
4222 uniShareName.Buffer,
4223 pDirNode->NameInformation.FileName.Length);
4225 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
4228 AFSSpecialShareNames = pDirNode;
4230 pLastDirNode = pDirNode;
4232 RtlInitUnicodeString( &uniShareName,
4235 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
4238 if( pObjectInfoCB == NULL)
4241 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4244 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4245 AFS_TRACE_LEVEL_VERBOSE,
4246 "AFSInitializeSpecialShareNameList (wkssvc) Initializing count (1) on object %08lX\n",
4249 pObjectInfoCB->ObjectReferenceCount = 1;
4251 pObjectInfoCB->FileType = AFS_FILE_TYPE_SPECIAL_SHARE_NAME;
4253 ulEntryLength = sizeof( AFSDirectoryCB) +
4254 uniShareName.Length;
4256 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
4260 if( pDirNode == NULL)
4263 AFSDeleteObjectInfo( pObjectInfoCB);
4265 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4268 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
4269 sizeof( AFSNonPagedDirectoryCB),
4270 AFS_DIR_ENTRY_NP_TAG);
4272 if( pNonPagedDirEntry == NULL)
4275 ExFreePool( pDirNode);
4277 AFSDeleteObjectInfo( pObjectInfoCB);
4279 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4282 RtlZeroMemory( pDirNode,
4285 RtlZeroMemory( pNonPagedDirEntry,
4286 sizeof( AFSNonPagedDirectoryCB));
4288 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
4290 pDirNode->NonPaged = pNonPagedDirEntry;
4292 pDirNode->ObjectInformation = pObjectInfoCB;
4298 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_WORKSTATION_SERVICE);
4300 pDirNode->NameInformation.FileName.Length = uniShareName.Length;
4302 pDirNode->NameInformation.FileName.MaximumLength = uniShareName.Length;
4304 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
4306 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
4307 uniShareName.Buffer,
4308 pDirNode->NameInformation.FileName.Length);
4310 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
4313 pLastDirNode->ListEntry.fLink = pDirNode;
4315 pDirNode->ListEntry.bLink = pLastDirNode;
4317 pLastDirNode = pDirNode;
4319 RtlInitUnicodeString( &uniShareName,
4322 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
4325 if( pObjectInfoCB == NULL)
4328 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4331 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4332 AFS_TRACE_LEVEL_VERBOSE,
4333 "AFSInitializeSpecialShareNameList (ipc$) Initializing count (1) on object %08lX\n",
4336 pObjectInfoCB->ObjectReferenceCount = 1;
4338 pObjectInfoCB->FileType = AFS_FILE_TYPE_SPECIAL_SHARE_NAME;
4340 ulEntryLength = sizeof( AFSDirectoryCB) +
4341 uniShareName.Length;
4343 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
4347 if( pDirNode == NULL)
4350 AFSDeleteObjectInfo( pObjectInfoCB);
4352 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4355 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
4356 sizeof( AFSNonPagedDirectoryCB),
4357 AFS_DIR_ENTRY_NP_TAG);
4359 if( pNonPagedDirEntry == NULL)
4362 ExFreePool( pDirNode);
4364 AFSDeleteObjectInfo( pObjectInfoCB);
4366 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4369 RtlZeroMemory( pDirNode,
4372 RtlZeroMemory( pNonPagedDirEntry,
4373 sizeof( AFSNonPagedDirectoryCB));
4375 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
4377 pDirNode->NonPaged = pNonPagedDirEntry;
4379 pDirNode->ObjectInformation = pObjectInfoCB;
4385 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_IPC);
4387 pDirNode->NameInformation.FileName.Length = uniShareName.Length;
4389 pDirNode->NameInformation.FileName.MaximumLength = uniShareName.Length;
4391 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
4393 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
4394 uniShareName.Buffer,
4395 pDirNode->NameInformation.FileName.Length);
4397 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
4400 pLastDirNode->ListEntry.fLink = pDirNode;
4402 pDirNode->ListEntry.bLink = pLastDirNode;
4406 if( !NT_SUCCESS( ntStatus))
4409 if( AFSSpecialShareNames != NULL)
4412 pDirNode = AFSSpecialShareNames;
4414 while( pDirNode != NULL)
4417 pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
4419 AFSDeleteObjectInfo( pDirNode->ObjectInformation);
4421 ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
4423 ExFreePool( pDirNode->NonPaged);
4425 ExFreePool( pDirNode);
4427 pDirNode = pLastDirNode;
4430 AFSSpecialShareNames = NULL;
4439 AFSGetSpecialShareNameEntry( IN UNICODE_STRING *ShareName,
4440 IN UNICODE_STRING *SecondaryName)
4443 AFSDirectoryCB *pDirectoryCB = NULL;
4444 ULONGLONG ullHash = 0;
4445 UNICODE_STRING uniFullShareName;
4451 // Build up the entire name here. We are guaranteed that if there is a
4452 // secondary name, it is pointing to a portion of the share name buffer
4455 if( SecondaryName->Length > 0 &&
4456 SecondaryName->Buffer != NULL)
4459 uniFullShareName = *SecondaryName;
4462 // The calling routine strips off the leading slash so add it back in
4465 uniFullShareName.Buffer--;
4466 uniFullShareName.Length += sizeof( WCHAR);
4467 uniFullShareName.MaximumLength += sizeof( WCHAR);
4470 // And the share name
4473 uniFullShareName.Buffer -= (ShareName->Length/sizeof( WCHAR));
4474 uniFullShareName.Length += ShareName->Length;
4475 uniFullShareName.MaximumLength += ShareName->Length;
4480 uniFullShareName = *ShareName;
4484 // Generate our hash value
4487 ullHash = AFSGenerateCRC( &uniFullShareName,
4491 // Loop through our special share names to see if this is one of them
4494 pDirectoryCB = AFSSpecialShareNames;
4496 while( pDirectoryCB != NULL)
4499 if( ullHash == pDirectoryCB->CaseInsensitiveTreeEntry.HashIndex)
4505 pDirectoryCB = (AFSDirectoryCB *)pDirectoryCB->ListEntry.fLink;
4509 return pDirectoryCB;
4513 AFSWaitOnQueuedFlushes( IN AFSFcb *Fcb)
4517 // Block on the queue flush event
4520 KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
4530 AFSWaitOnQueuedReleases()
4533 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
4536 // Block on the queue flush event
4539 KeWaitForSingleObject( &pRDRDeviceExt->Specific.RDR.QueuedReleaseExtentEvent,
4549 AFSIsEqualFID( IN AFSFileID *FileId1,
4550 IN AFSFileID *FileId2)
4553 BOOLEAN bIsEqual = FALSE;
4555 if( FileId1->Unique == FileId2->Unique &&
4556 FileId1->Vnode == FileId2->Vnode &&
4557 FileId1->Volume == FileId2->Volume &&
4558 FileId1->Cell == FileId2->Cell)
4568 AFSResetDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB)
4571 NTSTATUS ntStatus = STATUS_SUCCESS;
4572 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
4577 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
4580 // Reset the directory list information
4583 pCurrentDirEntry = ObjectInfoCB->Specific.Directory.DirectoryNodeListHead;
4585 while( pCurrentDirEntry != NULL)
4588 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
4590 if( pCurrentDirEntry->OpenReferenceCount == 0)
4593 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
4594 AFS_TRACE_LEVEL_VERBOSE,
4595 "AFSResetDirectoryContent Deleting dir entry %p for %wZ\n",
4597 &pCurrentDirEntry->NameInformation.FileName);
4599 AFSDeleteDirEntry( ObjectInfoCB,
4605 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
4606 AFS_TRACE_LEVEL_VERBOSE,
4607 "AFSResetDirectoryContent Setting DELETE flag in dir entry %p for %wZ\n",
4609 &pCurrentDirEntry->NameInformation.FileName);
4611 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
4613 AFSRemoveNameEntry( ObjectInfoCB,
4617 pCurrentDirEntry = pNextDirEntry;
4620 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = NULL;
4622 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = NULL;
4624 ObjectInfoCB->Specific.Directory.ShortNameTree = NULL;
4626 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = NULL;
4628 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = NULL;
4630 ObjectInfoCB->Specific.Directory.DirectoryNodeCount = 0;
4632 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
4633 AFS_TRACE_LEVEL_VERBOSE,
4634 "AFSResetDirectoryContent Reset count to 0 on parent FID %08lX-%08lX-%08lX-%08lX\n",
4635 ObjectInfoCB->FileId.Cell,
4636 ObjectInfoCB->FileId.Volume,
4637 ObjectInfoCB->FileId.Vnode,
4638 ObjectInfoCB->FileId.Unique);
4645 AFSEnumerateGlobalRoot( IN GUID *AuthGroup)
4648 NTSTATUS ntStatus = STATUS_SUCCESS;
4649 AFSDirectoryCB *pDirGlobalDirNode = NULL;
4650 UNICODE_STRING uniFullName;
4655 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4656 AFS_TRACE_LEVEL_VERBOSE,
4657 "AFSEnumerateGlobalRoot Acquiring GlobalRoot DirectoryNodeHdr.TreeLock lock %08lX EXCL %08lX\n",
4658 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4659 PsGetCurrentThread());
4661 AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4664 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
4667 try_return( ntStatus);
4671 // Initialize the root information
4674 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.ContentIndex = 1;
4677 // Enumerate the shares in the volume
4680 ntStatus = AFSEnumerateDirectory( AuthGroup,
4681 &AFSGlobalRoot->ObjectInformation,
4684 if( !NT_SUCCESS( ntStatus))
4687 try_return( ntStatus);
4690 pDirGlobalDirNode = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead;
4693 // Indicate the node is initialized
4696 SetFlag( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
4698 uniFullName.MaximumLength = PAGE_SIZE;
4699 uniFullName.Length = 0;
4701 uniFullName.Buffer = (WCHAR *)AFSLibExAllocatePoolWithTag( PagedPool,
4702 uniFullName.MaximumLength,
4703 AFS_GENERIC_MEMORY_12_TAG);
4705 if( uniFullName.Buffer == NULL)
4709 // Reset the directory content
4712 AFSResetDirectoryContent( &AFSGlobalRoot->ObjectInformation);
4714 ClearFlag( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
4716 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4720 // Populate our list of entries in the NP enumeration list
4723 while( pDirGlobalDirNode != NULL)
4726 uniFullName.Buffer[ 0] = L'\\';
4727 uniFullName.Buffer[ 1] = L'\\';
4729 uniFullName.Length = 2 * sizeof( WCHAR);
4731 RtlCopyMemory( &uniFullName.Buffer[ 2],
4732 AFSServerName.Buffer,
4733 AFSServerName.Length);
4735 uniFullName.Length += AFSServerName.Length;
4737 uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)] = L'\\';
4739 uniFullName.Length += sizeof( WCHAR);
4741 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
4742 pDirGlobalDirNode->NameInformation.FileName.Buffer,
4743 pDirGlobalDirNode->NameInformation.FileName.Length);
4745 uniFullName.Length += pDirGlobalDirNode->NameInformation.FileName.Length;
4747 AFSAddConnectionEx( &uniFullName,
4748 RESOURCEDISPLAYTYPE_SHARE,
4751 pDirGlobalDirNode = (AFSDirectoryCB *)pDirGlobalDirNode->ListEntry.fLink;
4754 AFSExFreePool( uniFullName.Buffer);
4758 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4765 AFSIsRelativeName( IN UNICODE_STRING *Name)
4768 BOOLEAN bIsRelative = FALSE;
4770 if( Name->Buffer[ 0] != L'\\')
4780 AFSUpdateName( IN UNICODE_STRING *Name)
4785 while( usIndex < Name->Length/sizeof( WCHAR))
4788 if( Name->Buffer[ usIndex] == L'/')
4791 Name->Buffer[ usIndex] = L'\\';
4801 AFSUpdateTargetName( IN OUT UNICODE_STRING *TargetName,
4802 IN OUT ULONG *Flags,
4803 IN WCHAR *NameBuffer,
4804 IN USHORT NameLength)
4807 NTSTATUS ntStatus = STATUS_SUCCESS;
4808 WCHAR *pTmpBuffer = NULL;
4814 // If we have enough space then just move in the name otherwise
4815 // allocate a new buffer
4818 if( TargetName->Length < NameLength)
4821 pTmpBuffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4823 AFS_NAME_BUFFER_FIVE_TAG);
4825 if( pTmpBuffer == NULL)
4828 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4831 if( BooleanFlagOn( *Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
4834 AFSExFreePool( TargetName->Buffer);
4837 TargetName->MaximumLength = NameLength;
4839 TargetName->Buffer = pTmpBuffer;
4841 SetFlag( *Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER);
4844 TargetName->Length = NameLength;
4846 RtlCopyMemory( TargetName->Buffer,
4848 TargetName->Length);
4851 // Update the name in the buffer
4854 AFSUpdateName( TargetName);
4865 AFSInitNameArray( IN AFSDirectoryCB *DirectoryCB,
4866 IN ULONG InitialElementCount)
4869 AFSNameArrayHdr *pNameArray = NULL;
4870 AFSNameArrayCB *pCurrentElement = NULL;
4871 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4877 if( InitialElementCount == 0)
4880 InitialElementCount = pDevExt->Specific.RDR.NameArrayLength;
4883 pNameArray = (AFSNameArrayHdr *)AFSExAllocatePoolWithTag( PagedPool,
4884 sizeof( AFSNameArrayHdr) +
4885 (InitialElementCount * sizeof( AFSNameArrayCB)),
4886 AFS_NAME_ARRAY_TAG);
4888 if( pNameArray == NULL)
4891 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
4892 AFS_TRACE_LEVEL_ERROR,
4893 "AFSInitNameArray Failed to allocate name array\n");
4895 try_return( pNameArray);
4898 RtlZeroMemory( pNameArray,
4899 sizeof( AFSNameArrayHdr) +
4900 (InitialElementCount * sizeof( AFSNameArrayCB)));
4902 pNameArray->MaxElementCount = InitialElementCount;
4904 if( DirectoryCB != NULL)
4907 pCurrentElement = &pNameArray->ElementArray[ 0];
4909 pNameArray->CurrentEntry = pCurrentElement;
4911 pNameArray->Count = 1;
4913 pNameArray->LinkCount = 0;
4915 lCount = InterlockedIncrement( &DirectoryCB->OpenReferenceCount);
4917 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4918 AFS_TRACE_LEVEL_VERBOSE,
4919 "AFSInitNameArray Increment count on %wZ DE %p Cnt %d\n",
4920 &DirectoryCB->NameInformation.FileName,
4924 pCurrentElement->DirectoryCB = DirectoryCB;
4926 pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
4928 pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
4930 if( pCurrentElement->FileId.Vnode == 1)
4933 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
4936 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
4937 AFS_TRACE_LEVEL_VERBOSE,
4938 "AFSInitNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
4940 pCurrentElement->DirectoryCB,
4941 pCurrentElement->FileId.Cell,
4942 pCurrentElement->FileId.Volume,
4943 pCurrentElement->FileId.Vnode,
4944 pCurrentElement->FileId.Unique,
4945 &pCurrentElement->DirectoryCB->NameInformation.FileName,
4946 pCurrentElement->DirectoryCB->ObjectInformation->FileType);
4958 AFSPopulateNameArray( IN AFSNameArrayHdr *NameArray,
4959 IN UNICODE_STRING *Path,
4960 IN AFSDirectoryCB *DirectoryCB)
4963 NTSTATUS ntStatus = STATUS_SUCCESS;
4964 AFSNameArrayCB *pCurrentElement = NULL;
4965 UNICODE_STRING uniComponentName, uniRemainingPath;
4966 AFSObjectInfoCB *pCurrentObject = NULL;
4967 ULONG ulTotalCount = 0;
4969 USHORT usLength = 0;
4975 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
4976 AFS_TRACE_LEVEL_VERBOSE,
4977 "AFSPopulateNameArray [NA:%p] passed Path %wZ DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
4981 DirectoryCB->ObjectInformation->FileId.Cell,
4982 DirectoryCB->ObjectInformation->FileId.Volume,
4983 DirectoryCB->ObjectInformation->FileId.Vnode,
4984 DirectoryCB->ObjectInformation->FileId.Unique,
4985 &DirectoryCB->NameInformation.FileName,
4986 DirectoryCB->ObjectInformation->FileType);
4989 // Init some info in the header
4992 pCurrentElement = &NameArray->ElementArray[ 0];
4994 NameArray->CurrentEntry = pCurrentElement;
4997 // The first entry points at the root
5000 pCurrentElement->DirectoryCB = DirectoryCB->ObjectInformation->VolumeCB->DirectoryCB;
5002 lCount = InterlockedIncrement( &pCurrentElement->DirectoryCB->OpenReferenceCount);
5004 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5005 AFS_TRACE_LEVEL_VERBOSE,
5006 "AFSPopulateNameArray Increment count on volume %wZ DE %p Cnt %d\n",
5007 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5008 pCurrentElement->DirectoryCB,
5011 pCurrentElement->Component = DirectoryCB->ObjectInformation->VolumeCB->DirectoryCB->NameInformation.FileName;
5013 pCurrentElement->FileId = DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
5015 pCurrentElement->Flags = 0;
5017 if( pCurrentElement->FileId.Vnode == 1)
5020 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5023 NameArray->Count = 1;
5025 NameArray->LinkCount = 0;
5027 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5028 AFS_TRACE_LEVEL_VERBOSE,
5029 "AFSPopulateNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5031 pCurrentElement->DirectoryCB,
5032 pCurrentElement->FileId.Cell,
5033 pCurrentElement->FileId.Volume,
5034 pCurrentElement->FileId.Vnode,
5035 pCurrentElement->FileId.Unique,
5036 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5037 pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5040 // If the root is the parent then we are done ...
5043 if( &DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation == DirectoryCB->ObjectInformation)
5045 try_return( ntStatus);
5057 AFSPopulateNameArrayFromRelatedArray( IN AFSNameArrayHdr *NameArray,
5058 IN AFSNameArrayHdr *RelatedNameArray,
5059 IN AFSDirectoryCB *DirectoryCB)
5062 NTSTATUS ntStatus = STATUS_SUCCESS;
5063 AFSNameArrayCB *pCurrentElement = NULL, *pCurrentRelatedElement = NULL;
5064 UNICODE_STRING uniComponentName, uniRemainingPath;
5065 AFSObjectInfoCB *pObjectInfo = NULL;
5066 ULONG ulTotalCount = 0;
5068 USHORT usLength = 0;
5074 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5075 AFS_TRACE_LEVEL_VERBOSE,
5076 "AFSPopulateNameArray [NA:%p] passed RelatedNameArray %p DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5080 DirectoryCB->ObjectInformation->FileId.Cell,
5081 DirectoryCB->ObjectInformation->FileId.Volume,
5082 DirectoryCB->ObjectInformation->FileId.Vnode,
5083 DirectoryCB->ObjectInformation->FileId.Unique,
5084 &DirectoryCB->NameInformation.FileName,
5085 DirectoryCB->ObjectInformation->FileType);
5088 // Init some info in the header
5091 pCurrentElement = &NameArray->ElementArray[ 0];
5093 pCurrentRelatedElement = &RelatedNameArray->ElementArray[ 0];
5095 NameArray->Count = 0;
5097 NameArray->LinkCount = RelatedNameArray->LinkCount;
5100 // Populate the name array with the data from the related array
5106 pCurrentElement->DirectoryCB = pCurrentRelatedElement->DirectoryCB;
5108 pCurrentElement->Component = pCurrentRelatedElement->DirectoryCB->NameInformation.FileName;
5110 pCurrentElement->FileId = pCurrentElement->DirectoryCB->ObjectInformation->FileId;
5112 pCurrentElement->Flags = 0;
5114 if( pCurrentElement->FileId.Vnode == 1)
5117 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5120 lCount = InterlockedIncrement( &pCurrentElement->DirectoryCB->OpenReferenceCount);
5122 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5123 AFS_TRACE_LEVEL_VERBOSE,
5124 "AFSPopulateNameArrayFromRelatedArray Increment count on %wZ DE %p Cnt %d\n",
5125 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5126 pCurrentElement->DirectoryCB,
5129 lCount = InterlockedIncrement( &NameArray->Count);
5131 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5132 AFS_TRACE_LEVEL_VERBOSE,
5133 "AFSPopulateNameArrayFromRelatedArray [NA:%p] Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5136 pCurrentElement->DirectoryCB,
5137 pCurrentElement->FileId.Cell,
5138 pCurrentElement->FileId.Volume,
5139 pCurrentElement->FileId.Vnode,
5140 pCurrentElement->FileId.Unique,
5141 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5142 pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5144 if( pCurrentElement->DirectoryCB == DirectoryCB ||
5145 NameArray->Count == RelatedNameArray->Count)
5157 pCurrentRelatedElement++;
5160 NameArray->CurrentEntry = NameArray->Count > 0 ? pCurrentElement : NULL;
5167 AFSFreeNameArray( IN AFSNameArrayHdr *NameArray)
5170 NTSTATUS ntStatus = STATUS_SUCCESS;
5171 AFSNameArrayCB *pCurrentElement = NULL;
5172 LONG lCount, lElement;
5177 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5178 AFS_TRACE_LEVEL_VERBOSE,
5179 "AFSFreeNameArray [NA:%p]\n",
5182 for ( lElement = 0; lElement < NameArray->Count; lElement++)
5185 pCurrentElement = &NameArray->ElementArray[ lElement];
5187 lCount = InterlockedDecrement( &pCurrentElement->DirectoryCB->OpenReferenceCount);
5189 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5190 AFS_TRACE_LEVEL_VERBOSE,
5191 "AFSFreeNameArray Decrement count on %wZ DE %p Cnt %d\n",
5192 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5193 pCurrentElement->DirectoryCB,
5197 AFSExFreePool( NameArray);
5204 AFSInsertNextElement( IN AFSNameArrayHdr *NameArray,
5205 IN AFSDirectoryCB *DirectoryCB)
5208 NTSTATUS ntStatus = STATUS_SUCCESS;
5209 AFSNameArrayCB *pCurrentElement = NULL;
5215 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5216 AFS_TRACE_LEVEL_VERBOSE,
5217 "AFSInsertNextElement [NA:%p] passed DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5220 DirectoryCB->ObjectInformation->FileId.Cell,
5221 DirectoryCB->ObjectInformation->FileId.Volume,
5222 DirectoryCB->ObjectInformation->FileId.Vnode,
5223 DirectoryCB->ObjectInformation->FileId.Unique,
5224 &DirectoryCB->NameInformation.FileName,
5225 DirectoryCB->ObjectInformation->FileType);
5227 if( NameArray->Count == NameArray->MaxElementCount)
5230 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5231 AFS_TRACE_LEVEL_ERROR,
5232 "AFSInsertNextElement [NA:%p] Name has reached Maximum Size\n",
5235 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5238 if( NameArray->CurrentEntry != NULL &&
5239 NameArray->CurrentEntry->DirectoryCB == DirectoryCB)
5242 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5243 AFS_TRACE_LEVEL_WARNING,
5244 "AFSInsertNextElement [NA:%p] DE %p already current element\n",
5248 try_return( ntStatus);
5251 if( NameArray->Count > 0)
5254 NameArray->CurrentEntry++;
5258 NameArray->CurrentEntry = &NameArray->ElementArray[ 0];
5261 pCurrentElement = NameArray->CurrentEntry;
5263 lCount = InterlockedIncrement( &NameArray->Count);
5265 lCount = InterlockedIncrement( &DirectoryCB->OpenReferenceCount);
5267 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5268 AFS_TRACE_LEVEL_VERBOSE,
5269 "AFSInsertNextElement Increment count on %wZ DE %p Cnt %d\n",
5270 &DirectoryCB->NameInformation.FileName,
5274 pCurrentElement->DirectoryCB = DirectoryCB;
5276 pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
5278 pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
5280 pCurrentElement->Flags = 0;
5282 if( pCurrentElement->FileId.Vnode == 1)
5285 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5288 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5289 AFS_TRACE_LEVEL_VERBOSE,
5290 "AFSInsertNextElement [NA:%p] Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5292 NameArray->Count - 1,
5293 pCurrentElement->DirectoryCB,
5294 pCurrentElement->FileId.Cell,
5295 pCurrentElement->FileId.Volume,
5296 pCurrentElement->FileId.Vnode,
5297 pCurrentElement->FileId.Unique,
5298 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5299 pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5310 AFSReplaceCurrentElement( IN AFSNameArrayHdr *NameArray,
5311 IN AFSDirectoryCB *DirectoryCB)
5313 AFSNameArrayCB *pCurrentElement = NULL;
5316 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5317 AFS_TRACE_LEVEL_VERBOSE,
5318 "AFSReplaceCurrentElement [NA:%p] passed DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5321 DirectoryCB->ObjectInformation->FileId.Cell,
5322 DirectoryCB->ObjectInformation->FileId.Volume,
5323 DirectoryCB->ObjectInformation->FileId.Vnode,
5324 DirectoryCB->ObjectInformation->FileId.Unique,
5325 &DirectoryCB->NameInformation.FileName,
5326 DirectoryCB->ObjectInformation->FileType);
5328 ASSERT( NameArray->CurrentEntry != NULL);
5330 pCurrentElement = NameArray->CurrentEntry;
5332 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5333 AFS_TRACE_LEVEL_VERBOSE,
5334 "AFSReplaceCurrentElement [NA:%p] Replacing Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5336 NameArray->Count - 1,
5337 pCurrentElement->DirectoryCB,
5338 pCurrentElement->FileId.Cell,
5339 pCurrentElement->FileId.Volume,
5340 pCurrentElement->FileId.Vnode,
5341 pCurrentElement->FileId.Unique,
5342 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5343 pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5345 lCount = InterlockedDecrement( &NameArray->CurrentEntry->DirectoryCB->OpenReferenceCount);
5347 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5348 AFS_TRACE_LEVEL_VERBOSE,
5349 "AFSReplaceCurrentElement Decrement count on %wZ DE %p Cnt %d\n",
5350 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5351 pCurrentElement->DirectoryCB,
5354 lCount = InterlockedIncrement( &DirectoryCB->OpenReferenceCount);
5356 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5357 AFS_TRACE_LEVEL_VERBOSE,
5358 "AFSReplaceCurrentElement Increment count on %wZ DE %p Cnt %d\n",
5359 &DirectoryCB->NameInformation.FileName,
5363 pCurrentElement->DirectoryCB = DirectoryCB;
5365 pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
5367 pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
5369 pCurrentElement->Flags = 0;
5371 if( pCurrentElement->FileId.Vnode == 1)
5374 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5381 AFSBackupEntry( IN AFSNameArrayHdr *NameArray)
5384 AFSDirectoryCB *pDirectoryCB = NULL;
5385 AFSNameArrayCB *pCurrentElement = NULL;
5391 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5392 AFS_TRACE_LEVEL_VERBOSE,
5393 "AFSBackupEntry [NA:%p]\n",
5396 if( NameArray->Count == 0)
5399 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5400 AFS_TRACE_LEVEL_ERROR,
5401 "AFSBackupEntry [NA:%p] No more entries\n",
5404 try_return( pCurrentElement);
5407 lCount = InterlockedDecrement( &NameArray->CurrentEntry->DirectoryCB->OpenReferenceCount);
5409 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5410 AFS_TRACE_LEVEL_VERBOSE,
5411 "AFSBackupEntry Decrement count on %wZ DE %p Cnt %d\n",
5412 &NameArray->CurrentEntry->DirectoryCB->NameInformation.FileName,
5413 NameArray->CurrentEntry->DirectoryCB,
5416 NameArray->CurrentEntry->DirectoryCB = NULL;
5418 lCount = InterlockedDecrement( &NameArray->Count);
5422 NameArray->CurrentEntry = NULL;
5424 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5425 AFS_TRACE_LEVEL_ERROR,
5426 "AFSBackupEntry [NA:%p] No more entries\n",
5431 NameArray->CurrentEntry--;
5433 pCurrentElement = NameArray->CurrentEntry;
5435 pDirectoryCB = pCurrentElement->DirectoryCB;
5437 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5438 AFS_TRACE_LEVEL_VERBOSE,
5439 "AFSBackupEntry [NA:%p] Returning Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5441 NameArray->Count - 1,
5442 pCurrentElement->DirectoryCB,
5443 pCurrentElement->FileId.Cell,
5444 pCurrentElement->FileId.Volume,
5445 pCurrentElement->FileId.Vnode,
5446 pCurrentElement->FileId.Unique,
5447 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5448 pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5456 return pDirectoryCB;
5460 AFSGetParentEntry( IN AFSNameArrayHdr *NameArray)
5463 AFSDirectoryCB *pDirEntry = NULL;
5464 AFSNameArrayCB *pElement = NULL;
5469 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5470 AFS_TRACE_LEVEL_VERBOSE,
5471 "AFSGetParentEntry [NA:%p]\n",
5474 if( NameArray->Count == 0 ||
5475 NameArray->Count == 1)
5478 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5479 AFS_TRACE_LEVEL_ERROR,
5480 "AFSGetParentEntry [NA:%p] No more entries\n",
5483 try_return( pDirEntry = NULL);
5486 pElement = &NameArray->ElementArray[ NameArray->Count - 2];
5488 pDirEntry = pElement->DirectoryCB;
5490 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5491 AFS_TRACE_LEVEL_VERBOSE,
5492 "AFSGetParentEntry [NA:%p] Returning Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5494 NameArray->Count - 2,
5495 pElement->DirectoryCB,
5496 pElement->FileId.Cell,
5497 pElement->FileId.Volume,
5498 pElement->FileId.Vnode,
5499 pElement->FileId.Unique,
5500 &pElement->DirectoryCB->NameInformation.FileName,
5501 pElement->DirectoryCB->ObjectInformation->FileType);
5512 AFSResetNameArray( IN AFSNameArrayHdr *NameArray,
5513 IN AFSDirectoryCB *DirectoryCB)
5516 AFSNameArrayCB *pCurrentElement = NULL;
5517 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
5518 LONG lCount, lElement;
5523 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5524 AFS_TRACE_LEVEL_VERBOSE,
5525 "AFSResetNameArray [NA:%p] passed DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5528 DirectoryCB->ObjectInformation->FileId.Cell,
5529 DirectoryCB->ObjectInformation->FileId.Volume,
5530 DirectoryCB->ObjectInformation->FileId.Vnode,
5531 DirectoryCB->ObjectInformation->FileId.Unique,
5532 &DirectoryCB->NameInformation.FileName,
5533 DirectoryCB->ObjectInformation->FileType);
5535 // Dereference previous name array contents
5538 for ( lElement = 0; lElement < NameArray->Count; lElement++)
5541 pCurrentElement = &NameArray->ElementArray[ lElement];
5543 lCount = InterlockedDecrement( &pCurrentElement->DirectoryCB->OpenReferenceCount);
5545 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5546 AFS_TRACE_LEVEL_VERBOSE,
5547 "AFSResetNameArray Decrement count on %wZ DE %p Cnt %d\n",
5548 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5549 pCurrentElement->DirectoryCB,
5553 RtlZeroMemory( NameArray,
5554 sizeof( AFSNameArrayHdr) +
5555 ((pDevExt->Specific.RDR.NameArrayLength - 1) * sizeof( AFSNameArrayCB)));
5557 NameArray->MaxElementCount = pDevExt->Specific.RDR.NameArrayLength;
5559 if( DirectoryCB != NULL)
5562 pCurrentElement = &NameArray->ElementArray[ 0];
5564 NameArray->CurrentEntry = pCurrentElement;
5566 NameArray->Count = 1;
5568 NameArray->LinkCount = 0;
5570 lCount = InterlockedIncrement( &DirectoryCB->OpenReferenceCount);
5572 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5573 AFS_TRACE_LEVEL_VERBOSE,
5574 "AFSResetNameArray Increment count on %wZ DE %p Cnt %d\n",
5575 &DirectoryCB->NameInformation.FileName,
5579 pCurrentElement->DirectoryCB = DirectoryCB;
5581 pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
5583 pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
5585 pCurrentElement->Flags = 0;
5587 if( pCurrentElement->FileId.Vnode == 1)
5590 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5593 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5594 AFS_TRACE_LEVEL_VERBOSE,
5595 "AFSResetNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5597 pCurrentElement->DirectoryCB,
5598 pCurrentElement->FileId.Cell,
5599 pCurrentElement->FileId.Volume,
5600 pCurrentElement->FileId.Vnode,
5601 pCurrentElement->FileId.Unique,
5602 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5603 pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5611 AFSDumpNameArray( IN AFSNameArrayHdr *NameArray)
5614 AFSNameArrayCB *pCurrentElement = NULL;
5616 pCurrentElement = &NameArray->ElementArray[ 0];
5618 AFSPrint("AFSDumpNameArray Start (%d)\n", NameArray->Count);
5620 while( pCurrentElement->DirectoryCB != NULL)
5623 AFSPrint("FID %08lX-%08lX-%08lX-%08lX %wZ\n",
5624 pCurrentElement->FileId.Cell,
5625 pCurrentElement->FileId.Volume,
5626 pCurrentElement->FileId.Vnode,
5627 pCurrentElement->FileId.Unique,
5628 &pCurrentElement->DirectoryCB->NameInformation.FileName);
5633 AFSPrint("AFSDumpNameArray End\n\n");
5639 AFSSetEnumerationEvent( IN AFSFcb *Fcb)
5644 // Depending on the type of node, set the event
5647 switch( Fcb->Header.NodeTypeCode)
5650 case AFS_DIRECTORY_FCB:
5655 lCount = InterlockedIncrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
5665 AFSClearEnumerationEvent( IN AFSFcb *Fcb)
5671 // Depending on the type of node, set the event
5674 switch( Fcb->Header.NodeTypeCode)
5677 case AFS_DIRECTORY_FCB:
5682 ASSERT( Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0);
5684 lCount = InterlockedDecrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
5694 AFSIsEnumerationInProcess( IN AFSObjectInfoCB *ObjectInfo)
5697 BOOLEAN bIsInProcess = FALSE;
5702 if( ObjectInfo->Fcb == NULL)
5705 try_return( bIsInProcess);
5708 switch( ObjectInfo->Fcb->Header.NodeTypeCode)
5711 case AFS_DIRECTORY_FCB:
5716 if( ObjectInfo->Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0)
5719 bIsInProcess = TRUE;
5731 return bIsInProcess;
5735 AFSVerifyVolume( IN ULONGLONG ProcessId,
5736 IN AFSVolumeCB *VolumeCB)
5739 NTSTATUS ntStatus = STATUS_SUCCESS;
5746 AFSInitPIOCtlDirectoryCB( IN AFSObjectInfoCB *ObjectInfo)
5749 NTSTATUS ntStatus = STATUS_SUCCESS;
5750 AFSObjectInfoCB *pObjectInfoCB = NULL;
5751 AFSDirectoryCB *pDirNode = NULL;
5752 ULONG ulEntryLength = 0;
5753 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
5759 pObjectInfoCB = AFSAllocateObjectInfo( ObjectInfo,
5762 if( pObjectInfoCB == NULL)
5765 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5768 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
5769 AFS_TRACE_LEVEL_VERBOSE,
5770 "AFSInitPIOCtlDirectoryCB Initializing count (1) on object %08lX\n",
5773 pObjectInfoCB->ObjectReferenceCount = 1;
5775 pObjectInfoCB->FileType = AFS_FILE_TYPE_PIOCTL;
5777 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
5779 ulEntryLength = sizeof( AFSDirectoryCB) + AFSPIOCtlName.Length;
5781 pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
5785 if( pDirNode == NULL)
5788 AFSDeleteObjectInfo( pObjectInfoCB);
5790 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5793 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
5794 sizeof( AFSNonPagedDirectoryCB),
5795 AFS_DIR_ENTRY_NP_TAG);
5797 if( pNonPagedDirEntry == NULL)
5800 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5803 RtlZeroMemory( pDirNode,
5806 RtlZeroMemory( pNonPagedDirEntry,
5807 sizeof( AFSNonPagedDirectoryCB));
5809 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
5811 pDirNode->NonPaged = pNonPagedDirEntry;
5813 pDirNode->ObjectInformation = pObjectInfoCB;
5815 pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_PIOCTL_INDEX;
5821 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_FAKE);
5823 pDirNode->NameInformation.FileName.Length = AFSPIOCtlName.Length;
5825 pDirNode->NameInformation.FileName.MaximumLength = AFSPIOCtlName.Length;
5827 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
5829 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
5830 AFSPIOCtlName.Buffer,
5831 pDirNode->NameInformation.FileName.Length);
5833 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
5836 if ( InterlockedCompareExchangePointer( (PVOID *)&ObjectInfo->Specific.Directory.PIOCtlDirectoryCB, pDirNode, NULL) != NULL)
5839 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
5840 AFS_TRACE_LEVEL_WARNING,
5841 "AFSInitPIOCtlDirectoryCB Raced PIOCtlDirectoryCB %08lX pFcb %08lX\n",
5842 ObjectInfo->Specific.Directory.PIOCtlDirectoryCB,
5846 // Increment the open reference and handle on the node
5849 lCount = InterlockedIncrement( &pDirNode->ObjectInformation->ObjectReferenceCount);
5851 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
5852 AFS_TRACE_LEVEL_VERBOSE,
5853 "AFSInitPIOCtlDirectoryCB Increment count on Object %08lX Cnt %d\n",
5854 pDirNode->ObjectInformation,
5857 try_return( ntStatus = STATUS_REPARSE);
5862 if ( ntStatus != STATUS_SUCCESS)
5865 if ( pDirNode != NULL)
5868 AFSExFreePool( pDirNode);
5871 if ( pObjectInfoCB != NULL)
5874 AFSDeleteObjectInfo( pObjectInfoCB);
5883 AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB,
5884 IN AFSDirectoryCB *DirectoryCB,
5885 IN UNICODE_STRING *ParentPathName,
5886 IN AFSNameArrayHdr *RelatedNameArray,
5888 OUT AFSFileInfoCB *FileInfo)
5891 NTSTATUS ntStatus = STATUS_SUCCESS;
5892 AFSDirEnumEntry *pDirEntry = NULL, *pLastDirEntry = NULL;
5893 UNICODE_STRING uniFullPathName;
5894 AFSNameArrayHdr *pNameArray = NULL;
5895 AFSVolumeCB *pVolumeCB = NULL;
5896 AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
5897 WCHAR *pwchBuffer = NULL;
5898 UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
5899 ULONG ulNameDifference = 0;
5906 // Retrieve a target name for the entry
5909 AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
5912 if( DirectoryCB->NameInformation.TargetName.Length == 0)
5915 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5917 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
5922 if( !NT_SUCCESS( ntStatus) ||
5923 pDirEntry->TargetNameLength == 0)
5926 if( pDirEntry != NULL)
5929 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
5932 try_return( ntStatus);
5935 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
5938 if( DirectoryCB->NameInformation.TargetName.Length == 0)
5942 // Update the target name
5945 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
5946 &DirectoryCB->Flags,
5947 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
5948 (USHORT)pDirEntry->TargetNameLength);
5950 if( !NT_SUCCESS( ntStatus))
5953 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5955 try_return( ntStatus);
5959 AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
5963 // Need to pass the full path in for parsing.
5966 if( AFSIsRelativeName( &DirectoryCB->NameInformation.TargetName))
5969 uniFullPathName.Length = 0;
5970 uniFullPathName.MaximumLength = ParentPathName->Length +
5972 DirectoryCB->NameInformation.TargetName.Length;
5974 uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5975 uniFullPathName.MaximumLength,
5976 AFS_NAME_BUFFER_SIX_TAG);
5978 if( uniFullPathName.Buffer == NULL)
5981 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5983 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5986 pwchBuffer = uniFullPathName.Buffer;
5988 RtlZeroMemory( uniFullPathName.Buffer,
5989 uniFullPathName.MaximumLength);
5991 RtlCopyMemory( uniFullPathName.Buffer,
5992 ParentPathName->Buffer,
5993 ParentPathName->Length);
5995 uniFullPathName.Length = ParentPathName->Length;
5997 if( uniFullPathName.Buffer[ (uniFullPathName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
5998 DirectoryCB->NameInformation.TargetName.Buffer[ 0] != L'\\')
6001 uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)] = L'\\';
6003 uniFullPathName.Length += sizeof( WCHAR);
6006 RtlCopyMemory( &uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)],
6007 DirectoryCB->NameInformation.TargetName.Buffer,
6008 DirectoryCB->NameInformation.TargetName.Length);
6010 uniFullPathName.Length += DirectoryCB->NameInformation.TargetName.Length;
6012 uniParsedName.Length = uniFullPathName.Length - ParentPathName->Length;
6013 uniParsedName.MaximumLength = uniParsedName.Length;
6015 uniParsedName.Buffer = &uniFullPathName.Buffer[ ParentPathName->Length/sizeof( WCHAR)];
6017 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6020 // We populate up to the current parent
6023 if( RelatedNameArray != NULL)
6026 pNameArray = AFSInitNameArray( NULL,
6027 RelatedNameArray->MaxElementCount);
6029 if( pNameArray == NULL)
6032 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6035 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
6042 pNameArray = AFSInitNameArray( NULL,
6045 if( pNameArray == NULL)
6048 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6051 ntStatus = AFSPopulateNameArray( pNameArray,
6056 if( !NT_SUCCESS( ntStatus))
6059 try_return( ntStatus);
6062 pVolumeCB = ParentDirectoryCB->ObjectInformation->VolumeCB;
6064 pParentDirEntry = ParentDirectoryCB;
6069 uniFullPathName.Length = 0;
6070 uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
6072 uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6073 uniFullPathName.MaximumLength,
6074 AFS_NAME_BUFFER_SEVEN_TAG);
6076 if( uniFullPathName.Buffer == NULL)
6079 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6081 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6084 pwchBuffer = uniFullPathName.Buffer;
6086 RtlZeroMemory( uniFullPathName.Buffer,
6087 uniFullPathName.MaximumLength);
6089 RtlCopyMemory( uniFullPathName.Buffer,
6090 DirectoryCB->NameInformation.TargetName.Buffer,
6091 DirectoryCB->NameInformation.TargetName.Length);
6093 uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6096 // This name should begin with the \afs server so parse it off and check it
6099 FsRtlDissectName( uniFullPathName,
6103 if( RtlCompareUnicodeString( &uniComponentName,
6108 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6110 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
6111 AFS_TRACE_LEVEL_ERROR,
6112 "AFSRetrieveFileAttributes Name %wZ contains invalid server name\n",
6115 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
6118 uniFullPathName = uniRemainingPath;
6120 uniParsedName = uniFullPathName;
6122 ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
6124 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6130 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
6133 if( pNameArray == NULL)
6136 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6139 pVolumeCB = AFSGlobalRoot;
6141 pParentDirEntry = AFSGlobalRoot->DirectoryCB;
6145 // Increment the ref count on the volume and dir entry for correct processing below
6148 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
6150 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6151 AFS_TRACE_LEVEL_VERBOSE,
6152 "AFSRetrieveFileAttributes Increment count on volume %08lX Cnt %d\n",
6156 lCount = InterlockedIncrement( &pParentDirEntry->OpenReferenceCount);
6158 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6159 AFS_TRACE_LEVEL_VERBOSE,
6160 "AFSRetrieveFileAttributes Increment count on %wZ DE %p Ccb %p Cnt %d\n",
6161 &pParentDirEntry->NameInformation.FileName,
6166 ntStatus = AFSLocateNameEntry( NULL,
6171 AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL,
6177 if( !NT_SUCCESS( ntStatus))
6181 // The volume lock was released on failure above
6182 // Except for STATUS_OBJECT_NAME_NOT_FOUND
6185 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
6188 if( pVolumeCB != NULL)
6191 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6193 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6194 AFS_TRACE_LEVEL_VERBOSE,
6195 "AFSRetrieveFileAttributes Decrement count on volume %08lX Cnt %d\n",
6200 if( pDirectoryEntry != NULL)
6203 lCount = InterlockedDecrement( &pDirectoryEntry->OpenReferenceCount);
6205 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6206 AFS_TRACE_LEVEL_VERBOSE,
6207 "AFSRetrieveFileAttributes Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6208 &pDirectoryEntry->NameInformation.FileName,
6216 lCount = InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
6218 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6219 AFS_TRACE_LEVEL_VERBOSE,
6220 "AFSRetrieveFileAttributes Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
6221 &pParentDirEntry->NameInformation.FileName,
6230 try_return( ntStatus);
6234 // Store off the information
6237 FileInfo->FileAttributes = pDirectoryEntry->ObjectInformation->FileAttributes;
6240 // Check for the mount point being returned
6243 if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT)
6246 FileInfo->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
6248 else if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK ||
6249 pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DFSLINK)
6252 if ( FileInfo->FileAttributes == FILE_ATTRIBUTE_NORMAL)
6255 FileInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
6260 FileInfo->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
6264 FileInfo->AllocationSize = pDirectoryEntry->ObjectInformation->AllocationSize;
6266 FileInfo->EndOfFile = pDirectoryEntry->ObjectInformation->EndOfFile;
6268 FileInfo->CreationTime = pDirectoryEntry->ObjectInformation->CreationTime;
6270 FileInfo->LastAccessTime = pDirectoryEntry->ObjectInformation->LastAccessTime;
6272 FileInfo->LastWriteTime = pDirectoryEntry->ObjectInformation->LastWriteTime;
6274 FileInfo->ChangeTime = pDirectoryEntry->ObjectInformation->ChangeTime;
6277 // Remove the reference made above
6280 lCount = InterlockedDecrement( &pDirectoryEntry->OpenReferenceCount);
6282 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6283 AFS_TRACE_LEVEL_VERBOSE,
6284 "AFSRetrieveFileAttributes Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
6285 &pDirectoryEntry->NameInformation.FileName,
6292 if( pDirEntry != NULL)
6295 AFSExFreePool( pDirEntry);
6298 if( pVolumeCB != NULL)
6301 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6303 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6304 AFS_TRACE_LEVEL_VERBOSE,
6305 "AFSRetrieveFileAttributes Decrement2 count on volume %08lX Cnt %d\n",
6310 if( pNameArray != NULL)
6313 AFSFreeNameArray( pNameArray);
6316 if( pwchBuffer != NULL)
6320 // Always free the buffer that we allocated as AFSLocateNameEntry
6321 // will not free it. If uniFullPathName.Buffer was allocated by
6322 // AFSLocateNameEntry, then we must free that as well.
6323 // Check that the uniFullPathName.Buffer in the string is not the same
6324 // offset by the length of the server name
6327 if( uniFullPathName.Length > 0 &&
6328 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
6331 AFSExFreePool( uniFullPathName.Buffer);
6334 AFSExFreePool( pwchBuffer);
6342 AFSAllocateObjectInfo( IN AFSObjectInfoCB *ParentObjectInfo,
6343 IN ULONGLONG HashIndex)
6346 NTSTATUS ntStatus = STATUS_SUCCESS;
6347 AFSObjectInfoCB *pObjectInfo = NULL;
6353 pObjectInfo = (AFSObjectInfoCB *)AFSExAllocatePoolWithTag( PagedPool,
6354 sizeof( AFSObjectInfoCB),
6355 AFS_OBJECT_INFO_TAG);
6357 if( pObjectInfo == NULL)
6360 try_return( pObjectInfo);
6363 RtlZeroMemory( pObjectInfo,
6364 sizeof( AFSObjectInfoCB));
6366 pObjectInfo->NonPagedInfo = (AFSNonPagedObjectInfoCB *)AFSExAllocatePoolWithTag( NonPagedPool,
6367 sizeof( AFSNonPagedObjectInfoCB),
6368 AFS_NP_OBJECT_INFO_TAG);
6370 if( pObjectInfo->NonPagedInfo == NULL)
6373 AFSExFreePool( pObjectInfo);
6375 try_return( pObjectInfo = NULL);
6378 ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6380 pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock = &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock;
6382 pObjectInfo->VolumeCB = ParentObjectInfo->VolumeCB;
6384 pObjectInfo->ParentObjectInformation = ParentObjectInfo;
6386 if( ParentObjectInfo != NULL)
6388 lCount = InterlockedIncrement( &ParentObjectInfo->ObjectReferenceCount);
6392 // Initialize the access time
6395 KeQueryTickCount( &pObjectInfo->LastAccessCount);
6401 // Insert the entry into the object tree and list
6404 pObjectInfo->TreeEntry.HashIndex = HashIndex;
6406 if( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead == NULL)
6409 ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead = &pObjectInfo->TreeEntry;
6414 ntStatus = AFSInsertHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
6415 &pObjectInfo->TreeEntry);
6417 ASSERT( NT_SUCCESS( ntStatus));
6421 // And the object list in the volume
6424 if( ParentObjectInfo->VolumeCB->ObjectInfoListHead == NULL)
6427 ParentObjectInfo->VolumeCB->ObjectInfoListHead = pObjectInfo;
6432 ParentObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = (void *)pObjectInfo;
6434 pObjectInfo->ListEntry.bLink = (void *)ParentObjectInfo->VolumeCB->ObjectInfoListTail;
6437 ParentObjectInfo->VolumeCB->ObjectInfoListTail = pObjectInfo;
6440 // Indicate the object is in the hash tree and linked list in the volume
6443 SetFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE | AFS_OBJECT_INSERTED_VOLUME_LIST);
6455 AFSDeleteObjectInfo( IN AFSObjectInfoCB *ObjectInfo)
6458 BOOLEAN bAcquiredTreeLock = FALSE;
6461 if( !ExIsResourceAcquiredExclusiveLite( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock))
6464 ASSERT( !ExIsResourceAcquiredLite( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock));
6466 AFSAcquireExcl( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
6469 bAcquiredTreeLock = TRUE;
6473 // Remove it from the tree and list if it was inserted
6476 if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
6479 AFSRemoveHashEntry( &ObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
6480 &ObjectInfo->TreeEntry);
6483 if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_INSERTED_VOLUME_LIST))
6486 if( ObjectInfo->ListEntry.fLink == NULL)
6489 ObjectInfo->VolumeCB->ObjectInfoListTail = (AFSObjectInfoCB *)ObjectInfo->ListEntry.bLink;
6491 if( ObjectInfo->VolumeCB->ObjectInfoListTail != NULL)
6494 ObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = NULL;
6500 ((AFSObjectInfoCB *)(ObjectInfo->ListEntry.fLink))->ListEntry.bLink = ObjectInfo->ListEntry.bLink;
6503 if( ObjectInfo->ListEntry.bLink == NULL)
6506 ObjectInfo->VolumeCB->ObjectInfoListHead = (AFSObjectInfoCB *)ObjectInfo->ListEntry.fLink;
6508 if( ObjectInfo->VolumeCB->ObjectInfoListHead != NULL)
6511 ObjectInfo->VolumeCB->ObjectInfoListHead->ListEntry.bLink = NULL;
6517 ((AFSObjectInfoCB *)(ObjectInfo->ListEntry.bLink))->ListEntry.fLink = ObjectInfo->ListEntry.fLink;
6521 if( ObjectInfo->ParentObjectInformation != NULL)
6524 lCount = InterlockedDecrement( &ObjectInfo->ParentObjectInformation->ObjectReferenceCount);
6527 if( bAcquiredTreeLock)
6530 AFSReleaseResource( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
6534 // Release the fid in the service
6537 if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_HELD_IN_SERVICE))
6540 AFSReleaseFid( &ObjectInfo->FileId);
6543 ExDeleteResourceLite( &ObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6545 AFSExFreePool( ObjectInfo->NonPagedInfo);
6547 AFSExFreePool( ObjectInfo);
6553 AFSEvaluateRootEntry( IN AFSDirectoryCB *DirectoryCB,
6554 OUT AFSDirectoryCB **TargetDirEntry)
6557 NTSTATUS ntStatus = STATUS_SUCCESS;
6558 AFSDirEnumEntry *pDirEntry = NULL, *pLastDirEntry = NULL;
6559 UNICODE_STRING uniFullPathName;
6560 AFSNameArrayHdr *pNameArray = NULL;
6561 AFSVolumeCB *pVolumeCB = NULL;
6562 AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
6563 WCHAR *pwchBuffer = NULL;
6564 UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
6565 ULONG ulNameDifference = 0;
6572 ntStatus = AFSRetrieveValidAuthGroup( NULL,
6573 DirectoryCB->ObjectInformation,
6577 if( !NT_SUCCESS( ntStatus))
6579 try_return( ntStatus);
6583 // Retrieve a target name for the entry
6586 AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
6589 if( DirectoryCB->NameInformation.TargetName.Length == 0)
6592 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6594 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
6599 if( !NT_SUCCESS( ntStatus) ||
6600 pDirEntry->TargetNameLength == 0)
6603 if( pDirEntry != NULL)
6606 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
6609 try_return( ntStatus);
6612 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
6615 if( DirectoryCB->NameInformation.TargetName.Length == 0)
6619 // Update the target name
6622 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
6623 &DirectoryCB->Flags,
6624 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
6625 (USHORT)pDirEntry->TargetNameLength);
6627 if( !NT_SUCCESS( ntStatus))
6630 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6632 try_return( ntStatus);
6636 AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
6640 // Need to pass the full path in for parsing.
6643 uniFullPathName.Length = 0;
6644 uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
6646 uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6647 uniFullPathName.MaximumLength,
6648 AFS_NAME_BUFFER_EIGHT_TAG);
6650 if( uniFullPathName.Buffer == NULL)
6653 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6655 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6658 pwchBuffer = uniFullPathName.Buffer;
6660 RtlZeroMemory( uniFullPathName.Buffer,
6661 uniFullPathName.MaximumLength);
6663 RtlCopyMemory( uniFullPathName.Buffer,
6664 DirectoryCB->NameInformation.TargetName.Buffer,
6665 DirectoryCB->NameInformation.TargetName.Length);
6667 uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6670 // This name should begin with the \afs server so parse it off and chech it
6673 FsRtlDissectName( uniFullPathName,
6677 if( RtlCompareUnicodeString( &uniComponentName,
6683 // Try evaluating the full path
6686 uniFullPathName.Buffer = pwchBuffer;
6688 uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6690 uniFullPathName.MaximumLength = uniFullPathName.Length;
6695 uniFullPathName = uniRemainingPath;
6698 uniParsedName = uniFullPathName;
6700 ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
6702 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6708 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
6711 if( pNameArray == NULL)
6714 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6717 pVolumeCB = AFSGlobalRoot;
6719 pParentDirEntry = AFSGlobalRoot->DirectoryCB;
6721 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
6723 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6724 AFS_TRACE_LEVEL_VERBOSE,
6725 "AFSEvaluateRootEntry Increment count on volume %08lX Cnt %d\n",
6729 lCount = InterlockedIncrement( &pParentDirEntry->OpenReferenceCount);
6731 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6732 AFS_TRACE_LEVEL_VERBOSE,
6733 "AFSEvaluateRootEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
6734 &pParentDirEntry->NameInformation.FileName,
6739 ntStatus = AFSLocateNameEntry( NULL,
6750 if( !NT_SUCCESS( ntStatus))
6754 // The volume lock was released on failure above
6755 // Except for STATUS_OBJECT_NAME_NOT_FOUND
6758 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
6761 if( pVolumeCB != NULL)
6764 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6766 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6767 AFS_TRACE_LEVEL_VERBOSE,
6768 "AFSEvaluateRootEntry Decrement count on volume %08lX Cnt %d\n",
6773 if( pDirectoryEntry != NULL)
6776 lCount = InterlockedDecrement( &pDirectoryEntry->OpenReferenceCount);
6778 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6779 AFS_TRACE_LEVEL_VERBOSE,
6780 "AFSEvaluateRootEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6781 &pDirectoryEntry->NameInformation.FileName,
6789 lCount = InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
6791 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6792 AFS_TRACE_LEVEL_VERBOSE,
6793 "AFSEvaluateRootEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6794 &pParentDirEntry->NameInformation.FileName,
6803 try_return( ntStatus);
6807 // Pass back the target dir entry for this request
6810 *TargetDirEntry = pDirectoryEntry;
6814 if( pDirEntry != NULL)
6817 AFSExFreePool( pDirEntry);
6820 if( pVolumeCB != NULL)
6823 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6825 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6826 AFS_TRACE_LEVEL_VERBOSE,
6827 "AFSEvaluateRootEntry2 Decrement count on volume %08lX Cnt %d\n",
6832 if( pNameArray != NULL)
6835 AFSFreeNameArray( pNameArray);
6838 if( pwchBuffer != NULL)
6842 // Always free the buffer that we allocated as AFSLocateNameEntry
6843 // will not free it. If uniFullPathName.Buffer was allocated by
6844 // AFSLocateNameEntry, then we must free that as well.
6845 // Check that the uniFullPathName.Buffer in the string is not the same
6846 // offset by the length of the server name
6849 if( uniFullPathName.Length > 0 &&
6850 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
6853 AFSExFreePool( uniFullPathName.Buffer);
6856 AFSExFreePool( pwchBuffer);
6864 AFSCleanupFcb( IN AFSFcb *Fcb,
6865 IN BOOLEAN ForceFlush)
6868 NTSTATUS ntStatus = STATUS_SUCCESS;
6869 AFSDeviceExt *pRDRDeviceExt = NULL, *pControlDeviceExt = NULL;
6870 LARGE_INTEGER liTime;
6871 IO_STATUS_BLOCK stIoStatus;
6876 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
6878 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
6880 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
6883 if( !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) &&
6884 !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
6887 AFSAcquireExcl( &Fcb->NPFcb->Resource,
6890 if( Fcb->OpenReferenceCount > 0)
6896 CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
6901 if( !NT_SUCCESS( stIoStatus.Status))
6904 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
6905 AFS_TRACE_LEVEL_ERROR,
6906 "AFSCleanupFcb CcFlushCache [1] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
6907 Fcb->ObjectInformation->FileId.Cell,
6908 Fcb->ObjectInformation->FileId.Volume,
6909 Fcb->ObjectInformation->FileId.Vnode,
6910 Fcb->ObjectInformation->FileId.Unique,
6912 stIoStatus.Information);
6914 ntStatus = stIoStatus.Status;
6917 CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
6922 __except( EXCEPTION_EXECUTE_HANDLER)
6924 ntStatus = GetExceptionCode();
6928 AFSReleaseResource( &Fcb->NPFcb->Resource);
6931 // Wait for any currently running flush or release requests to complete
6934 AFSWaitOnQueuedFlushes( Fcb);
6937 // Now perform another flush on the file
6940 if( !NT_SUCCESS( AFSFlushExtents( Fcb,
6944 AFSReleaseExtentsWithFlush( Fcb,
6949 if( Fcb->OpenReferenceCount == 0 ||
6950 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
6951 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
6954 AFSTearDownFcbExtents( Fcb,
6958 try_return( ntStatus);
6961 KeQueryTickCount( &liTime);
6964 // First up are there dirty extents in the cache to flush?
6968 ( !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) &&
6969 !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
6970 ( Fcb->Specific.File.ExtentsDirtyCount ||
6971 Fcb->Specific.File.ExtentCount) &&
6972 (liTime.QuadPart - Fcb->Specific.File.LastServerFlush.QuadPart)
6973 >= pControlDeviceExt->Specific.Control.FcbFlushTimeCount.QuadPart))
6975 if( !NT_SUCCESS( AFSFlushExtents( Fcb,
6977 Fcb->OpenReferenceCount == 0)
6980 AFSReleaseExtentsWithFlush( Fcb,
6984 else if( BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
6985 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
6989 // The file has been marked as invalid. Dump it
6992 AFSTearDownFcbExtents( Fcb,
6997 // If there are extents and they haven't been used recently *and*
6998 // are not being used
7002 ( 0 != Fcb->Specific.File.ExtentCount &&
7003 0 != Fcb->Specific.File.LastExtentAccess.QuadPart &&
7004 (liTime.QuadPart - Fcb->Specific.File.LastExtentAccess.QuadPart) >=
7005 (AFS_SERVER_PURGE_SLEEP * pControlDeviceExt->Specific.Control.FcbPurgeTimeCount.QuadPart))) &&
7006 AFSAcquireExcl( &Fcb->NPFcb->Resource,
7013 CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
7018 if( !NT_SUCCESS( stIoStatus.Status))
7021 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
7022 AFS_TRACE_LEVEL_ERROR,
7023 "AFSCleanupFcb CcFlushCache [2] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
7024 Fcb->ObjectInformation->FileId.Cell,
7025 Fcb->ObjectInformation->FileId.Volume,
7026 Fcb->ObjectInformation->FileId.Vnode,
7027 Fcb->ObjectInformation->FileId.Unique,
7029 stIoStatus.Information);
7031 ntStatus = stIoStatus.Status;
7037 CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
7043 __except( EXCEPTION_EXECUTE_HANDLER)
7045 ntStatus = GetExceptionCode();
7048 AFSReleaseResource( &Fcb->NPFcb->Resource);
7050 if( Fcb->OpenReferenceCount == 0)
7054 // Tear em down we'll not be needing them again
7057 AFSTearDownFcbExtents( Fcb,
7071 AFSUpdateDirEntryName( IN AFSDirectoryCB *DirectoryCB,
7072 IN UNICODE_STRING *NewFileName)
7075 NTSTATUS ntStatus = STATUS_SUCCESS;
7076 WCHAR *pTmpBuffer = NULL;
7081 if( NewFileName->Length > DirectoryCB->NameInformation.FileName.Length)
7084 if( BooleanFlagOn( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
7087 AFSExFreePool( DirectoryCB->NameInformation.FileName.Buffer);
7089 ClearFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
7091 DirectoryCB->NameInformation.FileName.Buffer = NULL;
7095 // OK, we need to allocate a new name buffer
7098 pTmpBuffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
7099 NewFileName->Length,
7100 AFS_NAME_BUFFER_NINE_TAG);
7102 if( pTmpBuffer == NULL)
7105 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7108 DirectoryCB->NameInformation.FileName.Buffer = pTmpBuffer;
7110 DirectoryCB->NameInformation.FileName.MaximumLength = NewFileName->Length;
7112 SetFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
7115 DirectoryCB->NameInformation.FileName.Length = NewFileName->Length;
7117 RtlCopyMemory( DirectoryCB->NameInformation.FileName.Buffer,
7118 NewFileName->Buffer,
7119 NewFileName->Length);
7130 AFSReadCacheFile( IN void *ReadBuffer,
7131 IN LARGE_INTEGER *ReadOffset,
7132 IN ULONG RequestedDataLength,
7133 IN OUT PULONG BytesRead)
7136 NTSTATUS ntStatus = STATUS_SUCCESS;
7139 PIO_STACK_LOCATION pIoStackLocation = NULL;
7140 AFSDeviceExt *pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
7141 DEVICE_OBJECT *pTargetDeviceObject = NULL;
7142 FILE_OBJECT *pCacheFileObject = NULL;
7147 pCacheFileObject = AFSReferenceCacheFileObject();
7149 if( pCacheFileObject == NULL)
7151 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
7154 pTargetDeviceObject = IoGetRelatedDeviceObject( pCacheFileObject);
7157 // Initialize the event
7160 KeInitializeEvent( &kEvent,
7161 SynchronizationEvent,
7165 // Allocate an irp for this request. This could also come from a
7166 // private pool, for instance.
7169 pIrp = IoAllocateIrp( pTargetDeviceObject->StackSize,
7175 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7179 // Build the IRP's main body
7182 pIrp->UserBuffer = ReadBuffer;
7184 pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
7185 pIrp->RequestorMode = KernelMode;
7186 pIrp->Flags |= IRP_READ_OPERATION;
7189 // Set up the I/O stack location.
7192 pIoStackLocation = IoGetNextIrpStackLocation( pIrp);
7193 pIoStackLocation->MajorFunction = IRP_MJ_READ;
7194 pIoStackLocation->DeviceObject = pTargetDeviceObject;
7195 pIoStackLocation->FileObject = pCacheFileObject;
7196 pIoStackLocation->Parameters.Read.Length = RequestedDataLength;
7198 pIoStackLocation->Parameters.Read.ByteOffset.QuadPart = ReadOffset->QuadPart;
7201 // Set the completion routine.
7204 IoSetCompletionRoutine( pIrp,
7212 // Send it to the FSD
7215 ntStatus = IoCallDriver( pTargetDeviceObject,
7218 if( NT_SUCCESS( ntStatus))
7225 ntStatus = KeWaitForSingleObject( &kEvent,
7231 if( NT_SUCCESS( ntStatus))
7234 ntStatus = pIrp->IoStatus.Status;
7236 *BytesRead = (ULONG)pIrp->IoStatus.Information;
7242 if( pCacheFileObject != NULL)
7244 AFSReleaseCacheFileObject( pCacheFileObject);
7250 if( pIrp->MdlAddress != NULL)
7253 if( FlagOn( pIrp->MdlAddress->MdlFlags, MDL_PAGES_LOCKED))
7256 MmUnlockPages( pIrp->MdlAddress);
7259 IoFreeMdl( pIrp->MdlAddress);
7262 pIrp->MdlAddress = NULL;
7276 AFSIrpComplete( IN PDEVICE_OBJECT DeviceObject,
7281 KEVENT *pEvent = (KEVENT *)Context;
7287 return STATUS_MORE_PROCESSING_REQUIRED;
7291 AFSIsDirectoryEmptyForDelete( IN AFSFcb *Fcb)
7294 BOOLEAN bIsEmpty = FALSE;
7295 AFSDirectoryCB *pDirEntry = NULL;
7300 AFSAcquireShared( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
7305 if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
7308 pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
7310 while( pDirEntry != NULL)
7313 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
7314 !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
7322 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
7327 AFSReleaseResource( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
7334 AFSRemoveNameEntry( IN AFSObjectInfoCB *ParentObjectInfo,
7335 IN AFSDirectoryCB *DirEntry)
7338 NTSTATUS ntStatus = STATUS_SUCCESS;
7343 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7346 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7347 AFS_TRACE_LEVEL_VERBOSE,
7348 "AFSRemoveNameEntry DE %p for %wZ has NOT_IN flag set\n",
7350 &DirEntry->NameInformation.FileName);
7352 try_return( ntStatus);
7355 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
7358 // Remove the entry from the parent tree
7361 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7362 AFS_TRACE_LEVEL_VERBOSE,
7363 "AFSRemoveNameEntry DE %p for %wZ removing from case sensitive tree\n",
7365 &DirEntry->NameInformation.FileName);
7367 AFSRemoveCaseSensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7370 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7371 AFS_TRACE_LEVEL_VERBOSE,
7372 "AFSRemoveNameEntry DE %p for %wZ removing from case insensitive tree\n",
7374 &DirEntry->NameInformation.FileName);
7376 AFSRemoveCaseInsensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
7379 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
7383 // From the short name tree
7386 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7387 AFS_TRACE_LEVEL_VERBOSE,
7388 "AFSRemoveNameEntry DE %p for %wZ removing from shortname tree\n",
7390 &DirEntry->NameInformation.FileName);
7392 AFSRemoveShortNameDirEntry( &ParentObjectInfo->Specific.Directory.ShortNameTree,
7395 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
7398 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7399 AFS_TRACE_LEVEL_VERBOSE,
7400 "AFSRemoveNameEntry DE %p for %wZ setting NOT_IN flag\n",
7402 &DirEntry->NameInformation.FileName);
7404 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
7406 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
7417 AFSGetAuthenticationId()
7420 LARGE_INTEGER liAuthId = {0,0};
7421 NTSTATUS ntStatus = STATUS_SUCCESS;
7422 PACCESS_TOKEN hToken = NULL;
7423 PTOKEN_STATISTICS pTokenInfo = NULL;
7424 BOOLEAN bCopyOnOpen = FALSE;
7425 BOOLEAN bEffectiveOnly = FALSE;
7426 BOOLEAN bPrimaryToken = FALSE;
7427 SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
7432 hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
7435 &stImpersonationLevel);
7440 hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
7445 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7446 AFS_TRACE_LEVEL_ERROR,
7447 "AFSGetAuthenticationId Failed to retrieve impersonation or primary token\n");
7449 try_return( ntStatus);
7452 bPrimaryToken = TRUE;
7455 ntStatus = SeQueryInformationToken( hToken,
7457 (PVOID *)&pTokenInfo);
7459 if( !NT_SUCCESS( ntStatus))
7462 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7463 AFS_TRACE_LEVEL_ERROR,
7464 "AFSGetAuthenticationId Failed to retrieve information Status %08lX\n", ntStatus);
7466 try_return( ntStatus);
7469 liAuthId.HighPart = pTokenInfo->AuthenticationId.HighPart;
7470 liAuthId.LowPart = pTokenInfo->AuthenticationId.LowPart;
7472 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7473 AFS_TRACE_LEVEL_VERBOSE,
7474 "AFSGetAuthenticationId Successfully retrieved authentication ID %I64X\n",
7485 PsDereferenceImpersonationToken( hToken);
7490 PsDereferencePrimaryToken( hToken);
7494 if( pTokenInfo != NULL)
7497 AFSExFreePool( pTokenInfo);
7505 AFSUnwindFileInfo( IN AFSFcb *Fcb,
7509 if( Ccb->FileUnwindInfo.FileAttributes != (ULONG)-1)
7511 Ccb->DirectoryCB->ObjectInformation->FileAttributes = Ccb->FileUnwindInfo.FileAttributes;
7514 if( Ccb->FileUnwindInfo.CreationTime.QuadPart != (ULONGLONG)-1)
7516 Ccb->DirectoryCB->ObjectInformation->CreationTime.QuadPart = Ccb->FileUnwindInfo.CreationTime.QuadPart;
7519 if( Ccb->FileUnwindInfo.LastAccessTime.QuadPart != (ULONGLONG)-1)
7521 Ccb->DirectoryCB->ObjectInformation->LastAccessTime.QuadPart = Ccb->FileUnwindInfo.LastAccessTime.QuadPart;
7524 if( Ccb->FileUnwindInfo.LastWriteTime.QuadPart != (ULONGLONG)-1)
7526 Ccb->DirectoryCB->ObjectInformation->LastWriteTime.QuadPart = Ccb->FileUnwindInfo.LastWriteTime.QuadPart;
7529 if( Ccb->FileUnwindInfo.ChangeTime.QuadPart != (ULONGLONG)-1)
7531 Ccb->DirectoryCB->ObjectInformation->ChangeTime.QuadPart = Ccb->FileUnwindInfo.ChangeTime.QuadPart;
7538 AFSValidateDirList( IN AFSObjectInfoCB *ObjectInfo)
7541 BOOLEAN bIsValid = TRUE;
7543 AFSDirectoryCB *pCurrentDirEntry = NULL, *pDirEntry = NULL;
7545 pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
7547 while( pCurrentDirEntry != NULL)
7550 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
7554 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7559 AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7560 (ULONG)pCurrentDirEntry->CaseSensitiveTreeEntry.HashIndex,
7563 if( pDirEntry == NULL)
7570 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
7573 if( ulCount != ObjectInfo->Specific.Directory.DirectoryNodeCount)
7576 AFSPrint("AFSValidateDirList Count off Calc: %d Stored: %d\n",
7578 ObjectInfo->Specific.Directory.DirectoryNodeCount);
7580 ObjectInfo->Specific.Directory.DirectoryNodeCount = ulCount;
7589 AFSReferenceCacheFileObject()
7592 AFSDeviceExt *pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
7593 FILE_OBJECT *pCacheFileObject = NULL;
7595 AFSAcquireShared( &pRdrDevExt->Specific.RDR.CacheFileLock,
7598 pCacheFileObject = pRdrDevExt->Specific.RDR.CacheFileObject;
7600 if( pCacheFileObject != NULL)
7602 ObReferenceObject( pCacheFileObject);
7605 AFSReleaseResource( &pRdrDevExt->Specific.RDR.CacheFileLock);
7607 return pCacheFileObject;
7611 AFSReleaseCacheFileObject( IN PFILE_OBJECT CacheFileObject)
7614 ASSERT( CacheFileObject != NULL);
7616 ObDereferenceObject( CacheFileObject);
7622 AFSInitializeLibrary( IN AFSLibraryInitCB *LibraryInit)
7625 NTSTATUS ntStatus = STATUS_SUCCESS;
7626 AFSDeviceExt *pControlDevExt = NULL;
7627 ULONG ulTimeIncrement = 0;
7632 AFSControlDeviceObject = LibraryInit->AFSControlDeviceObject;
7634 AFSRDRDeviceObject = LibraryInit->AFSRDRDeviceObject;
7636 AFSServerName = LibraryInit->AFSServerName;
7638 AFSDebugFlags = LibraryInit->AFSDebugFlags;
7641 // Callbacks in the framework
7644 AFSProcessRequest = LibraryInit->AFSProcessRequest;
7646 AFSDbgLogMsg = LibraryInit->AFSDbgLogMsg;
7648 AFSAddConnectionEx = LibraryInit->AFSAddConnectionEx;
7650 AFSExAllocatePoolWithTag = LibraryInit->AFSExAllocatePoolWithTag;
7652 AFSExFreePool = LibraryInit->AFSExFreePool;
7654 AFSDumpTraceFilesFnc = LibraryInit->AFSDumpTraceFiles;
7656 AFSRetrieveAuthGroupFnc = LibraryInit->AFSRetrieveAuthGroup;
7658 AFSLibCacheManagerCallbacks = LibraryInit->AFSCacheManagerCallbacks;
7660 if( LibraryInit->AFSCacheBaseAddress != NULL)
7663 SetFlag( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE);
7665 AFSLibCacheBaseAddress = LibraryInit->AFSCacheBaseAddress;
7667 AFSLibCacheLength = LibraryInit->AFSCacheLength;
7671 // Initialize some flush parameters
7674 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
7676 ulTimeIncrement = KeQueryTimeIncrement();
7678 pControlDevExt->Specific.Control.ObjectLifeTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_OBJECT_LIFETIME / (ULONGLONG)ulTimeIncrement);
7679 pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart = AFS_SERVER_PURGE_DELAY;
7680 pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart /= ulTimeIncrement;
7681 pControlDevExt->Specific.Control.FcbFlushTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_SERVER_FLUSH_DELAY / (ULONGLONG)ulTimeIncrement);
7682 pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_EXTENT_REQUEST_TIME/(ULONGLONG)ulTimeIncrement);
7685 // Initialize the global root entry
7688 ntStatus = AFSInitVolume( NULL,
7689 &LibraryInit->GlobalRootFid,
7692 if( !NT_SUCCESS( ntStatus))
7695 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
7696 AFS_TRACE_LEVEL_ERROR,
7697 "AFSInitializeLibrary AFSInitVolume failure %08lX\n",
7700 try_return( ntStatus);
7703 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
7706 if( !NT_SUCCESS( ntStatus))
7709 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
7710 AFS_TRACE_LEVEL_ERROR,
7711 "AFSInitializeLibrary AFSInitRootFcb failure %08lX\n",
7714 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
7716 try_return( ntStatus);
7720 // Update the node type code to AFS_ROOT_ALL
7723 AFSGlobalRoot->ObjectInformation.Fcb->Header.NodeTypeCode = AFS_ROOT_ALL;
7725 SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_ACTIVE_GLOBAL_ROOT);
7728 // Invalidate all known volumes since contact with the service and therefore
7729 // the file server was lost.
7732 AFSInvalidateAllVolumes();
7735 // Drop the locks acquired above
7738 AFSInitVolumeWorker( AFSGlobalRoot);
7740 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
7742 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Fcb->Header.Resource);
7756 NTSTATUS ntStatus = STATUS_SUCCESS;
7757 AFSDirectoryCB *pDirNode = NULL, *pLastDirNode = NULL;
7762 if( AFSGlobalDotDirEntry != NULL)
7765 AFSDeleteObjectInfo( AFSGlobalDotDirEntry->ObjectInformation);
7767 ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
7769 ExFreePool( AFSGlobalDotDirEntry->NonPaged);
7771 ExFreePool( AFSGlobalDotDirEntry);
7773 AFSGlobalDotDirEntry = NULL;
7776 if( AFSGlobalDotDotDirEntry != NULL)
7779 AFSDeleteObjectInfo( AFSGlobalDotDotDirEntry->ObjectInformation);
7781 ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
7783 ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
7785 ExFreePool( AFSGlobalDotDotDirEntry);
7787 AFSGlobalDotDotDirEntry = NULL;
7790 if( AFSSpecialShareNames != NULL)
7793 pDirNode = AFSSpecialShareNames;
7795 while( pDirNode != NULL)
7798 pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
7800 AFSDeleteObjectInfo( pDirNode->ObjectInformation);
7802 ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
7804 ExFreePool( pDirNode->NonPaged);
7806 ExFreePool( pDirNode);
7808 pDirNode = pLastDirNode;
7811 AFSSpecialShareNames = NULL;
7819 AFSDefaultLogMsg( IN ULONG Subsystem,
7825 NTSTATUS ntStatus = STATUS_SUCCESS;
7827 char chDebugBuffer[ 256];
7832 va_start( va_args, Format);
7834 ntStatus = RtlStringCbVPrintfA( chDebugBuffer,
7839 if( NT_SUCCESS( ntStatus))
7841 DbgPrint( chDebugBuffer);
7851 AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
7852 IN ULONG InputBufferLength,
7853 IN AFSStatusInfoCB *StatusInfo,
7854 OUT ULONG *ReturnLength)
7857 NTSTATUS ntStatus = STATUS_SUCCESS;
7858 AFSFcb *pFcb = NULL;
7859 AFSVolumeCB *pVolumeCB = NULL;
7860 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
7861 AFSObjectInfoCB *pObjectInfo = NULL;
7862 ULONGLONG ullIndex = 0;
7863 UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName, uniParsedName;
7864 AFSNameArrayHdr *pNameArray = NULL;
7865 AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
7872 // If we are given a FID then look up the entry by that, otherwise
7876 if( GetStatusInfo->FileID.Cell != 0 &&
7877 GetStatusInfo->FileID.Volume != 0 &&
7878 GetStatusInfo->FileID.Vnode != 0 &&
7879 GetStatusInfo->FileID.Unique != 0)
7882 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
7885 // Locate the volume node
7888 ullIndex = AFSCreateHighIndex( &GetStatusInfo->FileID);
7890 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
7892 (AFSBTreeEntry **)&pVolumeCB);
7894 if( pVolumeCB != NULL)
7897 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
7899 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7900 AFS_TRACE_LEVEL_VERBOSE,
7901 "AFSGetObjectStatus Increment count on volume %08lX Cnt %d\n",
7906 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
7908 if( !NT_SUCCESS( ntStatus) ||
7911 try_return( ntStatus = STATUS_INVALID_PARAMETER);
7914 if( AFSIsVolumeFID( &GetStatusInfo->FileID))
7917 pObjectInfo = &pVolumeCB->ObjectInformation;
7919 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
7921 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
7926 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
7929 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
7931 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7932 AFS_TRACE_LEVEL_VERBOSE,
7933 "AFSGetObjectStatus Decrement count on volume %08lX Cnt %d\n",
7937 ullIndex = AFSCreateLowIndex( &GetStatusInfo->FileID);
7939 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
7941 (AFSBTreeEntry **)&pObjectInfo);
7943 if( pObjectInfo != NULL)
7947 // Reference the node so it won't be torn down
7950 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
7952 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
7953 AFS_TRACE_LEVEL_VERBOSE,
7954 "AFSGetObjectStatus Increment count on object %08lX Cnt %d\n",
7959 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
7961 if( !NT_SUCCESS( ntStatus) ||
7962 pObjectInfo == NULL)
7964 try_return( ntStatus = STATUS_INVALID_PARAMETER);
7971 if( GetStatusInfo->FileNameLength == 0 ||
7972 InputBufferLength < (ULONG)(FIELD_OFFSET( AFSGetStatusInfoCB, FileName) + GetStatusInfo->FileNameLength))
7974 try_return( ntStatus = STATUS_INVALID_PARAMETER);
7977 uniFullPathName.Length = GetStatusInfo->FileNameLength;
7978 uniFullPathName.MaximumLength = uniFullPathName.Length;
7980 uniFullPathName.Buffer = (WCHAR *)GetStatusInfo->FileName;
7983 // This name should begin with the \afs server so parse it off and check it
7986 FsRtlDissectName( uniFullPathName,
7990 if( RtlCompareUnicodeString( &uniComponentName,
7994 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7995 AFS_TRACE_LEVEL_ERROR,
7996 "AFSGetObjectStatus Name %wZ contains invalid server name\n",
7999 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
8002 uniFullPathName = uniRemainingPath;
8004 uniParsedName = uniFullPathName;
8010 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
8013 if( pNameArray == NULL)
8015 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8018 pVolumeCB = AFSGlobalRoot;
8020 pParentDirEntry = AFSGlobalRoot->DirectoryCB;
8023 // Increment the ref count on the volume and dir entry for correct processing below
8026 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
8028 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8029 AFS_TRACE_LEVEL_VERBOSE,
8030 "AFSGetObjectStatus Increment count on volume %08lX Cnt %d\n",
8034 lCount = InterlockedIncrement( &pParentDirEntry->OpenReferenceCount);
8036 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8037 AFS_TRACE_LEVEL_VERBOSE,
8038 "AFSGetObjectStatus Increment count on %wZ DE %p Ccb %p Cnt %d\n",
8039 &pParentDirEntry->NameInformation.FileName,
8044 ntStatus = AFSLocateNameEntry( NULL,
8049 AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL |
8050 AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL,
8056 if( !NT_SUCCESS( ntStatus))
8060 // The volume lock was released on failure above
8061 // Except for STATUS_OBJECT_NAME_NOT_FOUND
8064 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
8067 if( pVolumeCB != NULL)
8070 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
8072 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8073 AFS_TRACE_LEVEL_VERBOSE,
8074 "AFSGetObjectStatus Decrement count on volume %08lX Cnt %d\n",
8079 if( pDirectoryEntry != NULL)
8082 lCount = InterlockedDecrement( &pDirectoryEntry->OpenReferenceCount);
8084 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8085 AFS_TRACE_LEVEL_VERBOSE,
8086 "AFSGetObjectStatus Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
8087 &pDirectoryEntry->NameInformation.FileName,
8095 lCount = InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
8097 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8098 AFS_TRACE_LEVEL_VERBOSE,
8099 "AFSGetObjectStatus Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
8100 &pParentDirEntry->NameInformation.FileName,
8109 try_return( ntStatus);
8113 // Remove the reference made above
8116 lCount = InterlockedDecrement( &pDirectoryEntry->OpenReferenceCount);
8118 pObjectInfo = pDirectoryEntry->ObjectInformation;
8120 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
8122 if( pVolumeCB != NULL)
8125 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
8127 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8128 AFS_TRACE_LEVEL_VERBOSE,
8129 "AFSRetrieveFileAttributes Decrement2 count on volume %08lX Cnt %d\n",
8131 pVolumeCB->VolumeReferenceCount);
8136 // At this point we have an object info block, return the information
8139 StatusInfo->FileId = pObjectInfo->FileId;
8141 StatusInfo->TargetFileId = pObjectInfo->TargetFileId;
8143 StatusInfo->Expiration = pObjectInfo->Expiration;
8145 StatusInfo->DataVersion = pObjectInfo->DataVersion;
8147 StatusInfo->FileType = pObjectInfo->FileType;
8149 StatusInfo->ObjectFlags = pObjectInfo->Flags;
8151 StatusInfo->CreationTime = pObjectInfo->CreationTime;
8153 StatusInfo->LastAccessTime = pObjectInfo->LastAccessTime;
8155 StatusInfo->LastWriteTime = pObjectInfo->LastWriteTime;
8157 StatusInfo->ChangeTime = pObjectInfo->ChangeTime;
8159 StatusInfo->FileAttributes = pObjectInfo->FileAttributes;
8161 StatusInfo->EndOfFile = pObjectInfo->EndOfFile;
8163 StatusInfo->AllocationSize = pObjectInfo->AllocationSize;
8165 StatusInfo->EaSize = pObjectInfo->EaSize;
8167 StatusInfo->Links = pObjectInfo->Links;
8170 // Return the information length
8173 *ReturnLength = sizeof( AFSStatusInfoCB);
8177 if( pObjectInfo != NULL)
8180 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
8183 if( pNameArray != NULL)
8186 AFSFreeNameArray( pNameArray);
8194 AFSCheckSymlinkAccess( IN AFSDirectoryCB *ParentDirectoryCB,
8195 IN UNICODE_STRING *ComponentName)
8198 NTSTATUS ntStatus = STATUS_SUCCESS;
8199 AFSDirectoryCB *pDirEntry = NULL;
8207 // Search for the entry in the parent
8210 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8211 AFS_TRACE_LEVEL_VERBOSE_2,
8212 "AFSCheckSymlinkAccess Searching for entry %wZ case sensitive\n",
8215 ulCRC = AFSGenerateCRC( ComponentName,
8218 AFSAcquireShared( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
8221 AFSLocateCaseSensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
8225 if( pDirEntry == NULL)
8229 // Missed so perform a case insensitive lookup
8232 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8233 AFS_TRACE_LEVEL_VERBOSE_2,
8234 "AFSCheckSymlinkAccess Searching for entry %wZ case insensitive\n",
8237 ulCRC = AFSGenerateCRC( ComponentName,
8240 AFSLocateCaseInsensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
8244 if( pDirEntry == NULL)
8248 // OK, if this component is a valid short name then try
8249 // a lookup in the short name tree
8252 if( RtlIsNameLegalDOS8Dot3( ComponentName,
8257 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8258 AFS_TRACE_LEVEL_VERBOSE_2,
8259 "AFSCheckSymlinkAccess Searching for entry %wZ short name\n",
8262 AFSLocateShortNameDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.ShortNameTree,
8269 if( pDirEntry != NULL)
8271 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
8274 AFSReleaseResource( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
8276 if( pDirEntry == NULL)
8279 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8280 AFS_TRACE_LEVEL_VERBOSE_2,
8281 "AFSCheckSymlinkAccess Failed to locate entry %wZ\n",
8284 try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
8288 // We have the symlink object but previously failed to process it so return access
8292 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8293 AFS_TRACE_LEVEL_VERBOSE_2,
8294 "AFSCheckSymlinkAccess Failing symlink access to entry %wZ REPARSE_POINT_NOT_RESOLVED\n",
8297 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
8299 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
8310 AFSRetrieveFinalComponent( IN UNICODE_STRING *FullPathName,
8311 OUT UNICODE_STRING *ComponentName)
8314 NTSTATUS ntStatus = STATUS_SUCCESS;
8315 UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName;
8317 uniFullPathName = *FullPathName;
8322 FsRtlDissectName( uniFullPathName,
8326 if( uniRemainingPath.Length == 0)
8331 uniFullPathName = uniRemainingPath;
8334 if( uniComponentName.Length > 0)
8336 *ComponentName = uniComponentName;
8343 AFSDumpTraceFiles_Default()
8349 AFSValidNameFormat( IN UNICODE_STRING *FileName)
8352 BOOLEAN bIsValidName = TRUE;
8358 while( usIndex < FileName->Length/sizeof( WCHAR))
8361 if( FileName->Buffer[ usIndex] == L':' ||
8362 FileName->Buffer[ usIndex] == L'*' ||
8363 FileName->Buffer[ usIndex] == L'?' ||
8364 FileName->Buffer[ usIndex] == L'"' ||
8365 FileName->Buffer[ usIndex] == L'<' ||
8366 FileName->Buffer[ usIndex] == L'>')
8368 bIsValidName = FALSE;
8376 return bIsValidName;
8380 AFSCreateDefaultSecurityDescriptor()
8383 NTSTATUS ntStatus = STATUS_SUCCESS;
8385 ULONG ulSACLSize = 0;
8386 SYSTEM_MANDATORY_LABEL_ACE* pACE = NULL;
8387 ULONG ulACESize = 0;
8388 SECURITY_DESCRIPTOR *pSecurityDescr = NULL;
8389 ULONG ulSDLength = 0;
8390 SECURITY_DESCRIPTOR *pRelativeSecurityDescr = NULL;
8391 PSID pWorldSID = NULL;
8392 ULONG *pulSubAuthority = NULL;
8393 ULONG ulWorldSIDLEngth = 0;
8398 ulWorldSIDLEngth = RtlLengthRequiredSid( 1);
8400 pWorldSID = (PSID)ExAllocatePoolWithTag( PagedPool,
8402 AFS_GENERIC_MEMORY_29_TAG);
8404 if( pWorldSID == NULL)
8406 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate World SID\n");
8407 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8410 RtlZeroMemory( pWorldSID,
8413 RtlInitializeSid( pWorldSID,
8414 &SeWorldSidAuthority,
8417 pulSubAuthority = RtlSubAuthoritySid(pWorldSID, 0);
8418 *pulSubAuthority = SECURITY_WORLD_RID;
8420 if( AFSRtlSetSaclSecurityDescriptor == NULL)
8423 AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor == NULL\n");
8428 ulACESize = sizeof( SYSTEM_MANDATORY_LABEL_ACE) + 128;
8430 pACE = (SYSTEM_MANDATORY_LABEL_ACE *)ExAllocatePoolWithTag( PagedPool,
8432 AFS_GENERIC_MEMORY_29_TAG);
8437 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8439 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8442 RtlZeroMemory( pACE,
8445 pACE->Header.AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
8446 pACE->Header.AceType = SYSTEM_MANDATORY_LABEL_ACE_TYPE;
8447 pACE->Header.AceSize = FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + (USHORT)RtlLengthSid( SeExports->SeLowMandatorySid);
8448 pACE->Mask = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP;
8450 RtlCopySid( RtlLengthSid( SeExports->SeLowMandatorySid),
8452 SeExports->SeLowMandatorySid);
8454 ulSACLSize = sizeof(ACL) + RtlLengthSid( SeExports->SeLowMandatorySid) +
8455 FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + ulACESize;
8457 pSACL = (PACL)ExAllocatePoolWithTag( PagedPool,
8459 AFS_GENERIC_MEMORY_29_TAG);
8464 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8466 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8469 ntStatus = RtlCreateAcl( pSACL,
8473 if( !NT_SUCCESS( ntStatus))
8476 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateAcl ntStatus %08lX\n",
8479 try_return( ntStatus);
8482 ntStatus = RtlAddAce( pSACL,
8486 pACE->Header.AceSize);
8488 if( !NT_SUCCESS( ntStatus))
8491 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAddAce ntStatus %08lX\n",
8494 try_return( ntStatus);
8498 pSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
8499 sizeof( SECURITY_DESCRIPTOR),
8500 AFS_GENERIC_MEMORY_27_TAG);
8502 if( pSecurityDescr == NULL)
8505 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8507 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8510 ntStatus = RtlCreateSecurityDescriptor( pSecurityDescr,
8511 SECURITY_DESCRIPTOR_REVISION);
8513 if( !NT_SUCCESS( ntStatus))
8516 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateSecurityDescriptor ntStatus %08lX\n",
8519 try_return( ntStatus);
8522 if( AFSRtlSetSaclSecurityDescriptor != NULL)
8524 ntStatus = AFSRtlSetSaclSecurityDescriptor( pSecurityDescr,
8529 if( !NT_SUCCESS( ntStatus))
8532 AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor ntStatus %08lX\n",
8535 try_return( ntStatus);
8540 // Add in the group and owner to the SD
8543 if( AFSRtlSetGroupSecurityDescriptor != NULL)
8545 ntStatus = AFSRtlSetGroupSecurityDescriptor( pSecurityDescr,
8549 if( !NT_SUCCESS( ntStatus))
8552 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetGroupSecurityDescriptor failed ntStatus %08lX\n",
8555 try_return( ntStatus);
8559 ntStatus = RtlSetOwnerSecurityDescriptor( pSecurityDescr,
8563 if( !NT_SUCCESS( ntStatus))
8566 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetOwnerSecurityDescriptor failed ntStatus %08lX\n",
8569 try_return( ntStatus);
8572 if( !RtlValidSecurityDescriptor( pSecurityDescr))
8575 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlValidSecurityDescriptor NOT\n");
8577 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8580 pRelativeSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
8582 AFS_GENERIC_MEMORY_27_TAG);
8584 if( pRelativeSecurityDescr == NULL)
8587 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8589 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8592 ulSDLength = PAGE_SIZE;
8594 ntStatus = RtlAbsoluteToSelfRelativeSD( pSecurityDescr,
8595 pRelativeSecurityDescr,
8598 if( !NT_SUCCESS( ntStatus))
8601 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAbsoluteToSelfRelativeSD ntStatus %08lX\n",
8604 try_return( ntStatus);
8607 AFSDefaultSD = pRelativeSecurityDescr;
8611 if( !NT_SUCCESS( ntStatus))
8614 if( pRelativeSecurityDescr != NULL)
8616 ExFreePool( pRelativeSecurityDescr);
8620 if( pSecurityDescr != NULL)
8622 ExFreePool( pSecurityDescr);
8635 if( pWorldSID != NULL)
8637 ExFreePool( pWorldSID);
8645 AFSRetrieveParentPath( IN UNICODE_STRING *FullFileName,
8646 OUT UNICODE_STRING *ParentPath)
8651 *ParentPath = *FullFileName;
8654 // If the final character is a \, jump over it
8657 if( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] == L'\\')
8659 ParentPath->Length -= sizeof( WCHAR);
8662 while( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] != L'\\')
8664 ParentPath->Length -= sizeof( WCHAR);
8668 // And the separator
8671 ParentPath->Length -= sizeof( WCHAR);
8677 AFSRetrieveValidAuthGroup( IN AFSFcb *Fcb,
8678 IN AFSObjectInfoCB *ObjectInfo,
8679 IN BOOLEAN WriteAccess,
8680 OUT GUID *AuthGroup)
8683 NTSTATUS ntStatus = STATUS_SUCCESS;
8684 GUID stAuthGroup, stZeroAuthGroup;
8685 BOOLEAN bFoundAuthGroup = FALSE;
8686 AFSCcb *pCcb = NULL;
8692 RtlZeroMemory( &stAuthGroup,
8695 RtlZeroMemory( &stZeroAuthGroup,
8701 if( ObjectInfo != NULL &&
8702 ObjectInfo->Fcb != NULL)
8704 pFcb = ObjectInfo->Fcb;
8711 AFSAcquireShared( &Fcb->NPFcb->CcbListLock,
8714 pCcb = Fcb->CcbListHead;
8716 while( pCcb != NULL)
8720 pCcb->GrantedAccess & FILE_WRITE_DATA)
8722 RtlCopyMemory( &stAuthGroup,
8726 bFoundAuthGroup = TRUE;
8730 else if( pCcb->GrantedAccess & FILE_READ_DATA)
8733 // At least get the read-only access
8736 RtlCopyMemory( &stAuthGroup,
8740 bFoundAuthGroup = TRUE;
8743 pCcb = (AFSCcb *)pCcb->ListEntry.fLink;
8746 AFSReleaseResource( &Fcb->NPFcb->CcbListLock);
8749 if( !bFoundAuthGroup)
8752 AFSRetrieveAuthGroupFnc( (ULONGLONG)PsGetCurrentProcessId(),
8753 (ULONGLONG)PsGetCurrentThreadId(),
8756 if( RtlCompareMemory( &stZeroAuthGroup,
8758 sizeof( GUID)) == sizeof( GUID))
8761 DbgPrint("AFSRetrieveValidAuthGroup Failed to locate PAG\n");
8763 try_return( ntStatus = STATUS_ACCESS_DENIED);
8767 RtlCopyMemory( AuthGroup,
8780 AFSPerformObjectInvalidate( IN AFSObjectInfoCB *ObjectInfo,
8781 IN ULONG InvalidateReason)
8784 NTSTATUS ntStatus = STATUS_SUCCESS;
8785 IO_STATUS_BLOCK stIoStatus;
8788 ULONG ulProcessCount = 0;
8794 switch( InvalidateReason)
8797 case AFS_INVALIDATE_DELETED:
8800 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
8801 ObjectInfo->Fcb != NULL)
8806 // Clear out the extents
8807 // And get rid of them (note this involves waiting
8808 // for any writes or reads to the cache to complete)
8811 (VOID) AFSTearDownFcbExtents( ObjectInfo->Fcb,
8818 case AFS_INVALIDATE_DATA_VERSION:
8821 LARGE_INTEGER liCurrentOffset = {0,0};
8822 LARGE_INTEGER liFlushLength = {0,0};
8823 ULONG ulFlushLength = 0;
8824 BOOLEAN bLocked = FALSE;
8825 BOOLEAN bExtentsLocked = FALSE;
8826 BOOLEAN bCleanExtents = FALSE;
8828 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
8829 ObjectInfo->Fcb != NULL)
8832 AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Resource,
8837 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
8838 AFS_TRACE_LEVEL_VERBOSE,
8839 "AFSPerformObjectInvalidate Acquiring Fcb extents lock %08lX SHARED %08lX\n",
8840 &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
8841 PsGetCurrentThread());
8843 AFSAcquireShared( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
8846 bExtentsLocked = TRUE;
8849 // There are several possibilities here:
8851 // 0. If there are no extents or all of the extents are dirty, do nothing.
8853 // 1. There could be nothing dirty and an open reference count of zero
8854 // in which case we can just tear down all of the extents without
8855 // holding any resources.
8857 // 2. There could be nothing dirty and a non-zero open reference count
8858 // in which case we can issue a CcPurge against the entire file
8859 // while holding just the Fcb Resource.
8861 // 3. There can be dirty extents in which case we need to identify
8862 // the non-dirty ranges and then perform a CcPurge on just the
8863 // non-dirty ranges while holding just the Fcb Resource.
8866 if ( ObjectInfo->Fcb->Specific.File.ExtentCount != ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount)
8869 if ( ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount == 0)
8872 if ( ObjectInfo->Fcb->OpenReferenceCount == 0)
8875 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
8877 bExtentsLocked = FALSE;
8879 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
8883 (VOID) AFSTearDownFcbExtents( ObjectInfo->Fcb,
8892 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
8894 bExtentsLocked = FALSE;
8896 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
8901 SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
8906 bCleanExtents = TRUE;
8909 __except( EXCEPTION_EXECUTE_HANDLER)
8912 ntStatus = GetExceptionCode();
8916 "EXCEPTION - AFSPerformObjectInvalidate Status %08lX\n",
8925 // Must build a list of non-dirty ranges from the beginning of the file
8926 // to the end. There can be at most (Fcb->Specific.File.ExtentsDirtyCount + 1)
8927 // ranges. In all but the most extreme random data write scenario there will
8928 // be significantly fewer.
8930 // For each range we need offset and size.
8933 AFSByteRange * ByteRangeList = NULL;
8934 ULONG ulByteRangeCount = 0;
8936 BOOLEAN bPurgeOnClose = FALSE;
8941 ulByteRangeCount = AFSConstructCleanByteRangeList( ObjectInfo->Fcb,
8944 if ( ByteRangeList != NULL ||
8945 ulByteRangeCount == 0)
8948 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
8950 bExtentsLocked = FALSE;
8952 for ( ulIndex = 0; ulIndex < ulByteRangeCount; ulIndex++)
8959 ulSize = ByteRangeList[ulIndex].Length.QuadPart > DWORD_MAX ? DWORD_MAX : ByteRangeList[ulIndex].Length.LowPart;
8961 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
8962 &ByteRangeList[ulIndex].FileOffset,
8967 bPurgeOnClose = TRUE;
8972 bCleanExtents = TRUE;
8975 ByteRangeList[ulIndex].Length.QuadPart -= ulSize;
8977 ByteRangeList[ulIndex].FileOffset.QuadPart += ulSize;
8979 } while ( ByteRangeList[ulIndex].Length.QuadPart > 0);
8986 // We couldn't allocate the memory to build the purge list
8987 // so just walk the extent list while holding the ExtentsList Resource.
8988 // This could deadlock but we do not have much choice.
8991 le = ObjectInfo->Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
8995 ulCount = (ULONG)ObjectInfo->Fcb->Specific.File.ExtentCount;
8999 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
9001 while( ulProcessCount < ulCount)
9003 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
9005 if( !BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
9007 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9008 &pEntry->FileOffset,
9013 bPurgeOnClose = TRUE;
9018 bCleanExtents = TRUE;
9022 if( liCurrentOffset.QuadPart < pEntry->FileOffset.QuadPart)
9025 liFlushLength.QuadPart = pEntry->FileOffset.QuadPart - liCurrentOffset.QuadPart;
9027 while( liFlushLength.QuadPart > 0)
9030 if( liFlushLength.QuadPart > 512 * 1024000)
9032 ulFlushLength = 512 * 1024000;
9036 ulFlushLength = liFlushLength.LowPart;
9039 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9045 bPurgeOnClose = TRUE;
9050 bCleanExtents = TRUE;
9053 liFlushLength.QuadPart -= ulFlushLength;
9057 liCurrentOffset.QuadPart = pEntry->FileOffset.QuadPart + pEntry->Size;
9065 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9071 bPurgeOnClose = TRUE;
9076 bCleanExtents = TRUE;
9083 SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9087 __except( EXCEPTION_EXECUTE_HANDLER)
9090 ntStatus = GetExceptionCode();
9094 "EXCEPTION - AFSPerformObjectInvalidate Status %08lX\n",
9100 if ( bExtentsLocked)
9103 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9109 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9115 AFSReleaseCleanExtents( ObjectInfo->Fcb,
9124 if( ObjectInfo != NULL)
9126 InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);