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;
651 // Initialize the global . entry
654 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
657 if( pObjectInfoCB == NULL)
660 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
661 AFS_TRACE_LEVEL_ERROR,
662 "AFSInitializeGlobalDirectory AFSAllocateObjectInfo failure %08lX\n",
665 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
668 InterlockedIncrement( &pObjectInfoCB->ObjectReferenceCount);
670 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
671 AFS_TRACE_LEVEL_VERBOSE,
672 "AFSInitializeGlobalDirectoryEntries Increment count on object %08lX Cnt %d\n",
674 pObjectInfoCB->ObjectReferenceCount);
676 ntStatus = STATUS_SUCCESS;
678 ulEntryLength = sizeof( AFSDirectoryCB) +
681 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
685 if( pDirNode == NULL)
688 AFSDeleteObjectInfo( pObjectInfoCB);
690 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
691 AFS_TRACE_LEVEL_ERROR,
692 "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_TAG allocation failure\n");
694 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
697 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
698 sizeof( AFSNonPagedDirectoryCB),
699 AFS_DIR_ENTRY_NP_TAG);
701 if( pNonPagedDirEntry == NULL)
704 ExFreePool( pDirNode);
706 AFSDeleteObjectInfo( pObjectInfoCB);
708 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
709 AFS_TRACE_LEVEL_ERROR,
710 "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_NP_TAG allocation failure\n");
712 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
715 RtlZeroMemory( pDirNode,
718 RtlZeroMemory( pNonPagedDirEntry,
719 sizeof( AFSNonPagedDirectoryCB));
721 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
723 pDirNode->NonPaged = pNonPagedDirEntry;
725 pDirNode->ObjectInformation = pObjectInfoCB;
731 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE | AFS_DIR_ENTRY_FAKE | AFS_DIR_ENTRY_VALID);
733 pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_DOT_INDEX;
736 // Setup the names in the entry
739 pDirNode->NameInformation.FileName.Length = sizeof( WCHAR);
741 pDirNode->NameInformation.FileName.MaximumLength = sizeof( WCHAR);
743 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
745 pDirNode->NameInformation.FileName.Buffer[ 0] = L'.';
748 // Populate the rest of the data
751 pObjectInfoCB->FileType = AFS_FILE_TYPE_DIRECTORY;
753 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
755 AFSGlobalDotDirEntry = pDirNode;
761 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
764 if( pObjectInfoCB == NULL)
767 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
768 AFS_TRACE_LEVEL_ERROR,
769 "AFSInitializeGlobalDirectory AFSAllocateObjectInfo (2) failure %08lX\n",
772 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
775 InterlockedIncrement( &pObjectInfoCB->ObjectReferenceCount);
777 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
778 AFS_TRACE_LEVEL_VERBOSE,
779 "AFSInitializeGlobalDirectoryEntries Increment count on object %08lX Cnt %d\n",
781 pObjectInfoCB->ObjectReferenceCount);
783 ntStatus = STATUS_SUCCESS;
785 ulEntryLength = sizeof( AFSDirectoryCB) +
786 ( 2 * sizeof( WCHAR));
788 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
792 if( pDirNode == NULL)
795 AFSDeleteObjectInfo( pObjectInfoCB);
797 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
800 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
801 sizeof( AFSNonPagedDirectoryCB),
802 AFS_DIR_ENTRY_NP_TAG);
804 if( pNonPagedDirEntry == NULL)
807 ExFreePool( pDirNode);
809 AFSDeleteObjectInfo( pObjectInfoCB);
811 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
814 RtlZeroMemory( pDirNode,
817 RtlZeroMemory( pNonPagedDirEntry,
818 sizeof( AFSNonPagedDirectoryCB));
820 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
822 pDirNode->NonPaged = pNonPagedDirEntry;
824 pDirNode->ObjectInformation = pObjectInfoCB;
830 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE | AFS_DIR_ENTRY_FAKE | AFS_DIR_ENTRY_VALID);
832 pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX;
835 // Setup the names in the entry
838 pDirNode->NameInformation.FileName.Length = 2 * sizeof( WCHAR);
840 pDirNode->NameInformation.FileName.MaximumLength = 2 * sizeof( WCHAR);
842 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
844 pDirNode->NameInformation.FileName.Buffer[ 0] = L'.';
846 pDirNode->NameInformation.FileName.Buffer[ 1] = L'.';
849 // Populate the rest of the data
852 pObjectInfoCB->FileType = AFS_FILE_TYPE_DIRECTORY;
854 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
856 AFSGlobalDotDotDirEntry = pDirNode;
860 if( !NT_SUCCESS( ntStatus))
863 if( AFSGlobalDotDirEntry != NULL)
866 AFSDeleteObjectInfo( AFSGlobalDotDirEntry->ObjectInformation);
868 ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
870 ExFreePool( AFSGlobalDotDirEntry->NonPaged);
872 ExFreePool( AFSGlobalDotDirEntry);
874 AFSGlobalDotDirEntry = NULL;
877 if( AFSGlobalDotDotDirEntry != NULL)
880 AFSDeleteObjectInfo( AFSGlobalDotDotDirEntry->ObjectInformation);
882 ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
884 ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
886 ExFreePool( AFSGlobalDotDotDirEntry);
888 AFSGlobalDotDotDirEntry = NULL;
897 AFSInitDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
898 IN PUNICODE_STRING FileName,
899 IN PUNICODE_STRING TargetName,
900 IN AFSDirEnumEntry *DirEnumEntry,
904 AFSDirectoryCB *pDirNode = NULL;
905 NTSTATUS ntStatus = STATUS_SUCCESS;
906 ULONG ulEntryLength = 0;
907 AFSDirEnumEntry *pDirEnumCB = NULL;
908 AFSFileID stTargetFileID;
910 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
911 AFSObjectInfoCB *pObjectInfoCB = NULL;
912 BOOLEAN bAllocatedObjectCB = FALSE;
913 ULONGLONG ullIndex = 0;
914 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
919 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
920 AFS_TRACE_LEVEL_VERBOSE,
921 "AFSInitDirEntry Initializing entry %wZ parent FID %08lX-%08lX-%08lX-%08lX\n",
923 ParentObjectInfo->FileId.Cell,
924 ParentObjectInfo->FileId.Volume,
925 ParentObjectInfo->FileId.Vnode,
926 ParentObjectInfo->FileId.Unique);
929 // First thing is to locate/create our object information block
933 AFSAcquireExcl( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
936 ullIndex = AFSCreateLowIndex( &DirEnumEntry->FileId);
938 ntStatus = AFSLocateHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
940 (AFSBTreeEntry **)&pObjectInfoCB);
942 if( !NT_SUCCESS( ntStatus) ||
943 pObjectInfoCB == NULL)
947 // Allocate our object info cb
950 pObjectInfoCB = AFSAllocateObjectInfo( ParentObjectInfo,
953 if( pObjectInfoCB == NULL)
956 AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
958 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
961 bAllocatedObjectCB = TRUE;
963 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
964 AFS_TRACE_LEVEL_VERBOSE,
965 "AFSInitDirEntry initialized object %08lX Parent Object %08lX for %wZ\n",
971 InterlockedIncrement( &pObjectInfoCB->ObjectReferenceCount);
973 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
974 AFS_TRACE_LEVEL_VERBOSE,
975 "AFSInitDirEntry Increment count on object %08lX Cnt %d\n",
977 pObjectInfoCB->ObjectReferenceCount);
979 AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
981 ntStatus = STATUS_SUCCESS;
983 ulEntryLength = sizeof( AFSDirectoryCB) +
986 if( TargetName != NULL)
989 ulEntryLength += TargetName->Length;
992 pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
996 if( pDirNode == NULL)
999 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1002 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
1003 sizeof( AFSNonPagedDirectoryCB),
1004 AFS_DIR_ENTRY_NP_TAG);
1006 if( pNonPagedDirEntry == NULL)
1009 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1012 RtlZeroMemory( pDirNode,
1015 RtlZeroMemory( pNonPagedDirEntry,
1016 sizeof( AFSNonPagedDirectoryCB));
1018 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
1020 pDirNode->NonPaged = pNonPagedDirEntry;
1022 pDirNode->ObjectInformation = pObjectInfoCB;
1025 // Set valid entry and NOT_IN_PARENT flag
1028 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1030 pDirNode->FileIndex = FileIndex;
1033 // Setup the names in the entry
1036 if( FileName->Length > 0)
1039 pDirNode->NameInformation.FileName.Length = FileName->Length;
1041 pDirNode->NameInformation.FileName.MaximumLength = FileName->Length;
1043 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
1045 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
1047 pDirNode->NameInformation.FileName.Length);
1050 // Create a CRC for the file
1053 pDirNode->CaseSensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1056 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1060 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1061 AFS_TRACE_LEVEL_VERBOSE,
1062 "AFSInitDirEntry Initialized DE %p for %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1065 ParentObjectInfo->FileId.Cell,
1066 ParentObjectInfo->FileId.Volume,
1067 ParentObjectInfo->FileId.Vnode,
1068 ParentObjectInfo->FileId.Unique);
1070 if( TargetName != NULL &&
1071 TargetName->Length > 0)
1074 pDirNode->NameInformation.TargetName.Length = TargetName->Length;
1076 pDirNode->NameInformation.TargetName.MaximumLength = pDirNode->NameInformation.TargetName.Length;
1078 pDirNode->NameInformation.TargetName.Buffer = (WCHAR *)((char *)pDirNode +
1079 sizeof( AFSDirectoryCB) +
1080 pDirNode->NameInformation.FileName.Length);
1082 RtlCopyMemory( pDirNode->NameInformation.TargetName.Buffer,
1084 pDirNode->NameInformation.TargetName.Length);
1088 // If we allocated the object information cb then update the information
1091 if( bAllocatedObjectCB)
1095 // Populate the rest of the data
1098 pObjectInfoCB->FileId = DirEnumEntry->FileId;
1100 pObjectInfoCB->TargetFileId = DirEnumEntry->TargetFileId;
1102 pObjectInfoCB->FileType = DirEnumEntry->FileType;
1104 pObjectInfoCB->CreationTime = DirEnumEntry->CreationTime;
1106 pObjectInfoCB->LastAccessTime = DirEnumEntry->LastAccessTime;
1108 pObjectInfoCB->LastWriteTime = DirEnumEntry->LastWriteTime;
1110 pObjectInfoCB->ChangeTime = DirEnumEntry->ChangeTime;
1112 pObjectInfoCB->EndOfFile = DirEnumEntry->EndOfFile;
1114 pObjectInfoCB->AllocationSize = DirEnumEntry->AllocationSize;
1116 pObjectInfoCB->FileAttributes = DirEnumEntry->FileAttributes;
1118 if( pObjectInfoCB->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1121 pObjectInfoCB->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1124 if (pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK ||
1125 pObjectInfoCB->FileType == AFS_FILE_TYPE_DFSLINK)
1128 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1131 pObjectInfoCB->EaSize = DirEnumEntry->EaSize;
1134 // Object specific information
1137 pObjectInfoCB->Links = DirEnumEntry->Links;
1139 pObjectInfoCB->Expiration = DirEnumEntry->Expiration;
1141 pObjectInfoCB->DataVersion = DirEnumEntry->DataVersion;
1144 // Check for the case where we have a filetype of SymLink but both the TargetFid and the
1145 // TargetName are empty. In this case set the filetype to zero so we evaluate it later in
1149 if( pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK &&
1150 pObjectInfoCB->TargetFileId.Vnode == 0 &&
1151 pObjectInfoCB->TargetFileId.Unique == 0 &&
1152 pDirNode->NameInformation.TargetName.Length == 0)
1156 // This will ensure we perform a validation on the node
1159 pObjectInfoCB->FileType = AFS_FILE_TYPE_UNKNOWN;
1162 if( pObjectInfoCB->FileType == AFS_FILE_TYPE_UNKNOWN)
1165 SetFlag( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
1171 if( !NT_SUCCESS( ntStatus))
1174 if( pNonPagedDirEntry != NULL)
1177 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
1179 AFSExFreePool( pNonPagedDirEntry);
1182 if( pDirNode != NULL)
1185 AFSExFreePool( pDirNode);
1191 // Dereference our object info block if we have one
1194 if( pObjectInfoCB != NULL)
1197 InterlockedDecrement( &pObjectInfoCB->ObjectReferenceCount);
1199 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1200 AFS_TRACE_LEVEL_VERBOSE,
1201 "AFSInitDirEntry Decrement count on object %08lX Cnt %d\n",
1203 pObjectInfoCB->ObjectReferenceCount);
1205 if( bAllocatedObjectCB)
1208 ASSERT( pObjectInfoCB->ObjectReferenceCount == 0);
1210 AFSDeleteObjectInfo( pObjectInfoCB);
1220 AFSCheckForReadOnlyAccess( IN ACCESS_MASK DesiredAccess,
1221 IN BOOLEAN DirectoryEntry)
1224 BOOLEAN bReturn = TRUE;
1225 ACCESS_MASK stAccessMask = 0;
1228 // Get rid of anything we don't know about
1231 DesiredAccess = (DesiredAccess &
1237 ACCESS_SYSTEM_SECURITY |
1241 FILE_READ_ATTRIBUTES |
1242 FILE_WRITE_ATTRIBUTES |
1243 FILE_LIST_DIRECTORY |
1249 // Our 'read only' access mask. These are the accesses we will
1250 // allow for a read only file
1253 stAccessMask = DELETE |
1258 ACCESS_SYSTEM_SECURITY |
1262 FILE_READ_ATTRIBUTES |
1263 FILE_WRITE_ATTRIBUTES |
1265 FILE_LIST_DIRECTORY |
1269 // For a directory, add in the directory specific accesses
1275 stAccessMask |= FILE_ADD_SUBDIRECTORY |
1280 if( FlagOn( DesiredAccess, ~stAccessMask))
1284 // A write access is set ...
1294 AFSEvaluateNode( IN GUID *AuthGroup,
1295 IN AFSDirectoryCB *DirEntry)
1298 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1299 NTSTATUS ntStatus = STATUS_SUCCESS;
1300 AFSDirEnumEntry *pDirEntry = NULL;
1301 UNICODE_STRING uniTargetName;
1306 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1311 if( !NT_SUCCESS( ntStatus))
1314 try_return( ntStatus);
1317 DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1319 DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1321 DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1323 DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1325 DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1327 DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1329 DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1331 DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1333 DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1335 DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1337 DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1339 if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1342 DirEntry->ObjectInformation->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1345 if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK ||
1346 pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1349 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1352 DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1354 DirEntry->ObjectInformation->Links = pDirEntry->Links;
1357 // If we have a target name then see if it needs updating ...
1360 if( pDirEntry->TargetNameLength > 0)
1364 // Update the target name information if needed
1367 uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1369 uniTargetName.MaximumLength = uniTargetName.Length;
1371 uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1373 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1376 if( DirEntry->NameInformation.TargetName.Length == 0 ||
1377 RtlCompareUnicodeString( &uniTargetName,
1378 &DirEntry->NameInformation.TargetName,
1383 // Update the target name
1386 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1388 uniTargetName.Buffer,
1389 uniTargetName.Length);
1391 if( !NT_SUCCESS( ntStatus))
1394 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1396 try_return( ntStatus);
1400 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1405 if( pDirEntry != NULL)
1408 AFSExFreePool( pDirEntry);
1416 AFSValidateSymLink( IN GUID *AuthGroup,
1417 IN AFSDirectoryCB *DirEntry)
1420 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1421 NTSTATUS ntStatus = STATUS_SUCCESS;
1422 AFSDirEnumEntry *pDirEntry = NULL;
1423 UNICODE_STRING uniTargetName;
1428 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1433 if( !NT_SUCCESS( ntStatus))
1436 try_return( ntStatus);
1439 if( pDirEntry->FileType == AFS_FILE_TYPE_UNKNOWN ||
1440 pDirEntry->FileType == AFS_FILE_TYPE_INVALID)
1443 try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
1446 DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1448 DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1450 DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1453 // Update the target name information if needed
1456 uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1458 uniTargetName.MaximumLength = uniTargetName.Length;
1460 uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1462 if( uniTargetName.Length > 0)
1465 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1468 if( DirEntry->NameInformation.TargetName.Length == 0 ||
1469 RtlCompareUnicodeString( &uniTargetName,
1470 &DirEntry->NameInformation.TargetName,
1475 // Update the target name
1478 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1480 uniTargetName.Buffer,
1481 uniTargetName.Length);
1483 if( !NT_SUCCESS( ntStatus))
1486 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1488 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1492 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1496 // If the FileType is the same then nothing to do since it IS
1500 if( pDirEntry->FileType == DirEntry->ObjectInformation->FileType)
1503 ASSERT( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK);
1505 try_return( ntStatus = STATUS_SUCCESS);
1508 DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1510 DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1512 DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1514 DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1516 DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1518 DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1520 DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1522 DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1524 if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1527 DirEntry->ObjectInformation->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1530 if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK ||
1531 pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1534 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1537 DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1539 DirEntry->ObjectInformation->Links = pDirEntry->Links;
1543 if( pDirEntry != NULL)
1546 AFSExFreePool( pDirEntry);
1554 AFSInvalidateCache( IN AFSInvalidateCacheCB *InvalidateCB)
1557 NTSTATUS ntStatus = STATUS_SUCCESS;
1558 AFSFcb *pDcb = NULL, *pFcb = NULL, *pNextFcb = NULL;
1559 AFSVolumeCB *pVolumeCB = NULL;
1560 AFSFcb *pTargetDcb = NULL;
1561 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1562 AFSDirectoryCB *pCurrentDirEntry = NULL;
1563 BOOLEAN bIsChild = FALSE;
1564 ULONGLONG ullIndex = 0;
1565 AFSObjectInfoCB *pObjectInfo = NULL;
1566 IO_STATUS_BLOCK stIoStatus;
1573 // Need to locate the Fcb for the directory to purge
1576 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1577 AFS_TRACE_LEVEL_VERBOSE,
1578 "AFSInvalidateCache Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1579 &pDevExt->Specific.RDR.VolumeTreeLock,
1580 PsGetCurrentThread());
1583 // Starve any exclusive waiters on this paticular call
1586 AFSAcquireSharedStarveExclusive( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1589 // Locate the volume node
1592 ullIndex = AFSCreateHighIndex( &InvalidateCB->FileID);
1594 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1596 (AFSBTreeEntry **)&pVolumeCB);
1598 if( pVolumeCB != NULL)
1601 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1603 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1604 AFS_TRACE_LEVEL_VERBOSE,
1605 "AFSInvalidateCache Increment count on volume %08lX Cnt %d\n",
1607 pVolumeCB->VolumeReferenceCount);
1610 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1612 if( !NT_SUCCESS( ntStatus) ||
1615 try_return( ntStatus = STATUS_SUCCESS);
1619 // If this is a whole volume invalidation then go do it now
1622 if( InvalidateCB->WholeVolume ||
1623 AFSIsVolumeFID( &InvalidateCB->FileID))
1626 ntStatus = AFSInvalidateVolume( pVolumeCB,
1627 InvalidateCB->Reason);
1629 AFSFsRtlNotifyFullReportChange( &pVolumeCB->ObjectInformation,
1631 FILE_NOTIFY_CHANGE_FILE_NAME |
1632 FILE_NOTIFY_CHANGE_DIR_NAME |
1633 FILE_NOTIFY_CHANGE_NAME |
1634 FILE_NOTIFY_CHANGE_ATTRIBUTES |
1635 FILE_NOTIFY_CHANGE_SIZE,
1636 FILE_ACTION_MODIFIED);
1638 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1640 try_return( ntStatus);
1643 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1646 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1648 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1649 AFS_TRACE_LEVEL_VERBOSE,
1650 "AFSInvalidateCache Decrement count on volume %08lX Cnt %d\n",
1652 pVolumeCB->VolumeReferenceCount);
1654 ullIndex = AFSCreateLowIndex( &InvalidateCB->FileID);
1656 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1658 (AFSBTreeEntry **)&pObjectInfo);
1660 if( pObjectInfo != NULL)
1664 // Reference the node so it won't be torn down
1667 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1669 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1670 AFS_TRACE_LEVEL_VERBOSE,
1671 "AFSInvalidateCache Increment count on object %08lX Cnt %d\n",
1673 pObjectInfo->ObjectReferenceCount);
1676 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1678 if( !NT_SUCCESS( ntStatus) ||
1679 pObjectInfo == NULL)
1681 try_return( ntStatus = STATUS_SUCCESS);
1684 if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK ||
1685 pObjectInfo->FileType == AFS_FILE_TYPE_DFSLINK ||
1686 pObjectInfo->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1689 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1690 AFS_TRACE_LEVEL_VERBOSE,
1691 "AFSInvalidateCache Invalidation on node type %d for fid %08lX-%08lX-%08lX-%08lX Reason %d\n",
1692 pObjectInfo->FileType,
1693 pObjectInfo->FileId.Cell,
1694 pObjectInfo->FileId.Volume,
1695 pObjectInfo->FileId.Vnode,
1696 pObjectInfo->FileId.Unique,
1697 InvalidateCB->Reason);
1700 // We only act on the mount point itself, not the target. If the
1701 // node has been deleted then mark it as such otherwise indicate
1702 // it requires verification
1705 if( InvalidateCB->Reason == AFS_INVALIDATE_DELETED)
1707 SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
1712 if( InvalidateCB->Reason == AFS_INVALIDATE_FLUSHED)
1715 pObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1717 SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1720 pObjectInfo->Expiration.QuadPart = 0;
1722 pObjectInfo->TargetFileId.Vnode = 0;
1724 pObjectInfo->TargetFileId.Unique = 0;
1726 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1727 AFS_TRACE_LEVEL_VERBOSE,
1728 "AFSInvalidateCache Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1729 pObjectInfo->FileId.Cell,
1730 pObjectInfo->FileId.Volume,
1731 pObjectInfo->FileId.Vnode,
1732 pObjectInfo->FileId.Unique);
1734 SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1737 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1739 if( InvalidateCB->Reason == AFS_INVALIDATE_CREDS)
1741 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1744 if( InvalidateCB->Reason == AFS_INVALIDATE_DATA_VERSION ||
1745 InvalidateCB->Reason == AFS_INVALIDATE_FLUSHED)
1747 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1751 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1754 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
1756 FILE_NOTIFY_CHANGE_FILE_NAME |
1757 FILE_NOTIFY_CHANGE_ATTRIBUTES,
1758 FILE_ACTION_MODIFIED);
1760 try_return( ntStatus);
1764 // Depending on the reason for invalidation then perform work on the node
1767 switch( InvalidateCB->Reason)
1770 case AFS_INVALIDATE_DELETED:
1774 // Mark this node as invalid
1777 SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
1779 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1780 AFS_TRACE_LEVEL_VERBOSE,
1781 "AFSInvalidateCache Set DELETE flag on fid %08lX-%08lX-%08lX-%08lX\n",
1782 pObjectInfo->FileId.Cell,
1783 pObjectInfo->FileId.Volume,
1784 pObjectInfo->FileId.Vnode,
1785 pObjectInfo->FileId.Unique);
1787 if( pObjectInfo->ParentObjectInformation != NULL)
1790 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1791 AFS_TRACE_LEVEL_VERBOSE,
1792 "AFSInvalidateCache Set VERIFY flag on parent fid %08lX-%08lX-%08lX-%08lX\n",
1793 pObjectInfo->ParentObjectInformation->FileId.Cell,
1794 pObjectInfo->ParentObjectInformation->FileId.Volume,
1795 pObjectInfo->ParentObjectInformation->FileId.Vnode,
1796 pObjectInfo->ParentObjectInformation->FileId.Unique);
1798 SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1799 pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1800 pObjectInfo->ParentObjectInformation->Expiration.QuadPart = 0;
1803 if( pObjectInfo->FileType == AFS_FILE_TYPE_DIRECTORY)
1805 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1809 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1812 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
1815 FILE_ACTION_REMOVED);
1817 if( pObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
1818 pObjectInfo->Fcb != NULL)
1823 // Clear out the extents
1824 // And get rid of them (note this involves waiting
1825 // for any writes or reads to the cache to complete)
1828 (VOID) AFSTearDownFcbExtents( pObjectInfo->Fcb);
1834 case AFS_INVALIDATE_FLUSHED:
1837 if( pObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
1838 pObjectInfo->Fcb != NULL)
1841 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1842 AFS_TRACE_LEVEL_VERBOSE,
1843 "AFSInvalidateCache Flush/purge file fid %08lX-%08lX-%08lX-%08lX\n",
1844 pObjectInfo->FileId.Cell,
1845 pObjectInfo->FileId.Volume,
1846 pObjectInfo->FileId.Vnode,
1847 pObjectInfo->FileId.Unique);
1849 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
1855 CcFlushCache( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
1860 if( !NT_SUCCESS( stIoStatus.Status))
1863 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1864 AFS_TRACE_LEVEL_ERROR,
1865 "AFSInvalidateCache CcFlushCache failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1866 pObjectInfo->FileId.Cell,
1867 pObjectInfo->FileId.Volume,
1868 pObjectInfo->FileId.Vnode,
1869 pObjectInfo->FileId.Unique,
1871 stIoStatus.Information);
1873 ntStatus = stIoStatus.Status;
1876 CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
1881 __except( EXCEPTION_EXECUTE_HANDLER)
1884 ntStatus = GetExceptionCode();
1887 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
1890 // Clear out the extents
1891 // Get rid of them (note this involves waiting
1892 // for any writes or reads to the cache to complete)
1895 (VOID) AFSTearDownFcbExtents( pObjectInfo->Fcb);
1898 pObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1901 if( pObjectInfo->FileType == AFS_FILE_TYPE_FILE)
1904 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1905 AFS_TRACE_LEVEL_VERBOSE,
1906 "AFSInvalidateCache Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
1907 pObjectInfo->FileId.Cell,
1908 pObjectInfo->FileId.Volume,
1909 pObjectInfo->FileId.Vnode,
1910 pObjectInfo->FileId.Unique);
1912 SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1915 // Fall through to the default processing
1921 if( pObjectInfo->FileType == AFS_FILE_TYPE_DIRECTORY)
1923 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1927 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1930 if( InvalidateCB->Reason == AFS_INVALIDATE_CREDS)
1932 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1935 if( InvalidateCB->Reason == AFS_INVALIDATE_DATA_VERSION)
1937 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1941 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1944 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
1947 FILE_ACTION_MODIFIED);
1950 // Indicate this node requires re-evaluation for the remaining reasons
1953 pObjectInfo->Expiration.QuadPart = 0;
1955 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1956 AFS_TRACE_LEVEL_VERBOSE,
1957 "AFSInvalidateCache Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1958 pObjectInfo->FileId.Cell,
1959 pObjectInfo->FileId.Volume,
1960 pObjectInfo->FileId.Vnode,
1961 pObjectInfo->FileId.Unique);
1963 SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1971 if( pObjectInfo != NULL)
1974 InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
1976 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1977 AFS_TRACE_LEVEL_VERBOSE,
1978 "AFSInvalidateCache Decrement count on object %08lX Cnt %d\n",
1980 pObjectInfo->ObjectReferenceCount);
1988 AFSIsChildOfParent( IN AFSFcb *Dcb,
1992 BOOLEAN bIsChild = FALSE;
1993 AFSFcb *pCurrentFcb = Fcb;
1995 while( pCurrentFcb != NULL)
1998 if( pCurrentFcb->ObjectInformation->ParentObjectInformation == Dcb->ObjectInformation)
2006 pCurrentFcb = pCurrentFcb->ObjectInformation->ParentObjectInformation->Fcb;
2014 AFSCreateHighIndex( IN AFSFileID *FileID)
2017 ULONGLONG ullIndex = 0;
2019 ullIndex = (((ULONGLONG)FileID->Cell << 32) | FileID->Volume);
2026 AFSCreateLowIndex( IN AFSFileID *FileID)
2029 ULONGLONG ullIndex = 0;
2031 ullIndex = (((ULONGLONG)FileID->Vnode << 32) | FileID->Unique);
2037 AFSCheckAccess( IN ACCESS_MASK DesiredAccess,
2038 IN ACCESS_MASK GrantedAccess,
2039 IN BOOLEAN DirectoryEntry)
2042 BOOLEAN bAccessGranted = TRUE;
2045 // Check if we are asking for read/write and granted only read only
2046 // NOTE: There will be more checks here
2049 if( !AFSCheckForReadOnlyAccess( DesiredAccess,
2051 AFSCheckForReadOnlyAccess( GrantedAccess,
2055 bAccessGranted = FALSE;
2058 return bAccessGranted;
2062 AFSGetDriverStatus( IN AFSDriverStatusRespCB *DriverStatus)
2065 NTSTATUS ntStatus = STATUS_SUCCESS;
2066 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2072 DriverStatus->Status = AFS_DRIVER_STATUS_READY;
2074 if( AFSGlobalRoot == NULL)
2081 DriverStatus->Status = AFS_DRIVER_STATUS_NOT_READY;
2084 if( pControlDevExt->Specific.Control.CommServiceCB.IrpPoolControlFlag != POOL_ACTIVE)
2091 DriverStatus->Status = AFS_DRIVER_STATUS_NO_SERVICE;
2098 AFSSubstituteSysName( IN UNICODE_STRING *ComponentName,
2099 IN UNICODE_STRING *SubstituteName,
2100 IN ULONG StringIndex)
2103 NTSTATUS ntStatus = STATUS_SUCCESS;
2104 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2105 AFSSysNameCB *pSysName = NULL;
2106 ERESOURCE *pSysNameLock = NULL;
2109 UNICODE_STRING uniSysName;
2116 if( IoIs32bitProcess( NULL))
2119 pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2121 pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2126 pSysNameLock = &pControlDevExt->Specific.Control.SysName64ListLock;
2128 pSysName = pControlDevExt->Specific.Control.SysName64ListHead;
2132 pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2134 pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2138 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2139 AFS_TRACE_LEVEL_VERBOSE,
2140 "AFSSubstituteSysName Acquiring SysName lock %08lX SHARED %08lX\n",
2142 PsGetCurrentThread());
2144 AFSAcquireShared( pSysNameLock,
2148 // Find where we are in the list
2151 while( pSysName != NULL &&
2152 ulIndex < StringIndex)
2155 pSysName = pSysName->fLink;
2160 if( pSysName == NULL)
2163 try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
2166 RtlInitUnicodeString( &uniSysName,
2169 // If it is a full component of @SYS then just substitue the
2173 if( RtlCompareUnicodeString( &uniSysName,
2178 SubstituteName->Length = pSysName->SysName.Length;
2179 SubstituteName->MaximumLength = SubstituteName->Length;
2181 SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2182 SubstituteName->Length,
2183 AFS_SUBST_BUFFER_TAG);
2185 if( SubstituteName->Buffer == NULL)
2188 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2191 RtlCopyMemory( SubstituteName->Buffer,
2192 pSysName->SysName.Buffer,
2193 pSysName->SysName.Length);
2200 while( ComponentName->Buffer[ usIndex] != L'@')
2206 SubstituteName->Length = (usIndex * sizeof( WCHAR)) + pSysName->SysName.Length;
2207 SubstituteName->MaximumLength = SubstituteName->Length;
2209 SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2210 SubstituteName->Length,
2211 AFS_SUBST_BUFFER_TAG);
2213 if( SubstituteName->Buffer == NULL)
2216 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2219 RtlCopyMemory( SubstituteName->Buffer,
2220 ComponentName->Buffer,
2221 usIndex * sizeof( WCHAR));
2223 RtlCopyMemory( &SubstituteName->Buffer[ usIndex],
2224 pSysName->SysName.Buffer,
2225 pSysName->SysName.Length);
2230 AFSReleaseResource( pSysNameLock);
2237 AFSSubstituteNameInPath( IN OUT UNICODE_STRING *FullPathName,
2238 IN OUT UNICODE_STRING *ComponentName,
2239 IN UNICODE_STRING *SubstituteName,
2240 IN OUT UNICODE_STRING *RemainingPath,
2241 IN BOOLEAN FreePathName)
2244 NTSTATUS ntStatus = STATUS_SUCCESS;
2245 UNICODE_STRING uniPathName;
2246 USHORT usPrefixNameLen = 0;
2247 SHORT sNameLenDelta = 0;
2253 // If the passed in name can handle the additional length
2254 // then just moves things around
2257 sNameLenDelta = SubstituteName->Length - ComponentName->Length;
2259 usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2261 if( FullPathName->MaximumLength > FullPathName->Length + sNameLenDelta)
2264 if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2267 RtlMoveMemory( &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + SubstituteName->Length)/sizeof( WCHAR))],
2268 &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + ComponentName->Length)/sizeof( WCHAR))],
2269 FullPathName->Length - usPrefixNameLen*sizeof( WCHAR) - ComponentName->Length);
2272 RtlCopyMemory( &FullPathName->Buffer[ usPrefixNameLen],
2273 SubstituteName->Buffer,
2274 SubstituteName->Length);
2276 FullPathName->Length += sNameLenDelta;
2278 ComponentName->Length += sNameLenDelta;
2280 ComponentName->MaximumLength = ComponentName->Length;
2282 if ( RemainingPath->Buffer)
2285 RemainingPath->Buffer += sNameLenDelta/sizeof( WCHAR);
2288 try_return( ntStatus);
2292 // Need to re-allocate the buffer
2295 uniPathName.Length = FullPathName->Length -
2296 ComponentName->Length +
2297 SubstituteName->Length;
2299 uniPathName.MaximumLength = FullPathName->MaximumLength + PAGE_SIZE;
2301 uniPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2302 uniPathName.MaximumLength,
2303 AFS_NAME_BUFFER_FOUR_TAG);
2305 if( uniPathName.Buffer == NULL)
2308 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2311 usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2313 usPrefixNameLen *= sizeof( WCHAR);
2315 RtlZeroMemory( uniPathName.Buffer,
2316 uniPathName.MaximumLength);
2318 RtlCopyMemory( uniPathName.Buffer,
2319 FullPathName->Buffer,
2322 RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen/sizeof( WCHAR))],
2323 SubstituteName->Buffer,
2324 SubstituteName->Length);
2326 if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2329 RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen + SubstituteName->Length)/sizeof( WCHAR)],
2330 &FullPathName->Buffer[ (usPrefixNameLen + ComponentName->Length)/sizeof( WCHAR)],
2331 FullPathName->Length - usPrefixNameLen - ComponentName->Length);
2334 ComponentName->Buffer = uniPathName.Buffer + (ComponentName->Buffer - FullPathName->Buffer);
2336 ComponentName->Length += sNameLenDelta;
2338 ComponentName->MaximumLength = ComponentName->Length;
2340 if ( RemainingPath->Buffer)
2343 RemainingPath->Buffer = uniPathName.Buffer
2344 + (RemainingPath->Buffer - FullPathName->Buffer)
2345 + sNameLenDelta/sizeof( WCHAR);
2350 AFSExFreePool( FullPathName->Buffer);
2353 *FullPathName = uniPathName;
2364 AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
2368 NTSTATUS ntStatus = STATUS_SUCCESS;
2369 AFSFcb *pFcb = NULL;
2370 AFSObjectInfoCB *pCurrentObject = NULL;
2376 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2377 AFS_TRACE_LEVEL_VERBOSE,
2378 "AFSInvalidateVolume Invalidate volume fid %08lX-%08lX-%08lX-%08lX Reason %08lX\n",
2379 VolumeCB->ObjectInformation.FileId.Cell,
2380 VolumeCB->ObjectInformation.FileId.Volume,
2381 VolumeCB->ObjectInformation.FileId.Vnode,
2382 VolumeCB->ObjectInformation.FileId.Unique,
2386 // Depending on the reason for invalidation then perform work on the node
2392 case AFS_INVALIDATE_DELETED:
2396 // Mark this volume as invalid
2399 VolumeCB->ObjectInformation.Expiration.QuadPart = 0;
2401 SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
2403 SetFlag( VolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE);
2405 AFSFsRtlNotifyFullReportChange( &VolumeCB->ObjectInformation,
2407 FILE_NOTIFY_CHANGE_DIR_NAME,
2408 FILE_ACTION_REMOVED);
2410 AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2413 pCurrentObject = VolumeCB->ObjectInfoListHead;
2415 while( pCurrentObject != NULL)
2418 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY)
2420 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
2424 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
2427 AFSFsRtlNotifyFullReportChange( pCurrentObject,
2430 FILE_ACTION_REMOVED);
2432 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
2434 pFcb = pCurrentObject->Fcb;
2437 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
2442 // Clear out the extents
2443 // And get rid of them (note this involves waiting
2444 // for any writes or reads to the cache to complete)
2447 (VOID) AFSTearDownFcbExtents( pFcb);
2450 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2453 AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2462 // Indicate this node requires re-evaluation for the remaining reasons
2465 VolumeCB->ObjectInformation.Expiration.QuadPart = 0;
2467 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2468 AFS_TRACE_LEVEL_VERBOSE,
2469 "AFSInvalidateVolume Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
2470 VolumeCB->ObjectInformation.FileId.Cell,
2471 VolumeCB->ObjectInformation.FileId.Volume,
2472 VolumeCB->ObjectInformation.FileId.Vnode,
2473 VolumeCB->ObjectInformation.FileId.Unique);
2475 SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY);
2477 if( Reason == AFS_INVALIDATE_FLUSHED)
2480 VolumeCB->ObjectInformation.DataVersion.QuadPart = (ULONGLONG)-1;
2484 // Notify anyone that cares
2487 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
2489 if( Reason == AFS_INVALIDATE_CREDS)
2491 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
2494 if( Reason == AFS_INVALIDATE_DATA_VERSION ||
2495 Reason == AFS_INVALIDATE_FLUSHED)
2497 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
2501 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
2504 AFSFsRtlNotifyFullReportChange( &VolumeCB->ObjectInformation,
2507 FILE_ACTION_MODIFIED);
2510 // Volume invalidations require all objects in the volume be re-verified
2513 AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2516 pCurrentObject = VolumeCB->ObjectInfoListHead;
2518 while( pCurrentObject != NULL)
2521 pCurrentObject->Expiration.QuadPart = 0;
2523 pCurrentObject->TargetFileId.Vnode = 0;
2525 pCurrentObject->TargetFileId.Unique = 0;
2527 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2528 AFS_TRACE_LEVEL_VERBOSE,
2529 "AFSInvalidateVolume Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
2530 pCurrentObject->FileId.Cell,
2531 pCurrentObject->FileId.Volume,
2532 pCurrentObject->FileId.Vnode,
2533 pCurrentObject->FileId.Unique);
2535 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
2537 if( Reason == AFS_INVALIDATE_FLUSHED)
2540 pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
2543 if( Reason == AFS_INVALIDATE_FLUSHED &&
2544 pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
2547 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2548 AFS_TRACE_LEVEL_VERBOSE,
2549 "AFSInvalidateVolume Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
2550 pCurrentObject->FileId.Cell,
2551 pCurrentObject->FileId.Volume,
2552 pCurrentObject->FileId.Vnode,
2553 pCurrentObject->FileId.Unique);
2555 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
2558 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY)
2560 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
2564 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
2567 if( Reason == AFS_INVALIDATE_CREDS)
2569 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
2572 if( Reason == AFS_INVALIDATE_DATA_VERSION ||
2573 Reason == AFS_INVALIDATE_FLUSHED)
2575 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
2579 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
2582 AFSFsRtlNotifyFullReportChange( pCurrentObject,
2585 FILE_ACTION_MODIFIED);
2587 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2590 AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2601 AFSVerifyEntry( IN GUID *AuthGroup,
2602 IN AFSDirectoryCB *DirEntry)
2605 NTSTATUS ntStatus = STATUS_SUCCESS;
2606 AFSDirEnumEntry *pDirEnumEntry = NULL;
2607 AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
2608 IO_STATUS_BLOCK stIoStatus;
2613 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2614 AFS_TRACE_LEVEL_VERBOSE_2,
2615 "AFSVerifyEntry Verifying entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2616 &DirEntry->NameInformation.FileName,
2617 pObjectInfo->FileId.Cell,
2618 pObjectInfo->FileId.Volume,
2619 pObjectInfo->FileId.Vnode,
2620 pObjectInfo->FileId.Unique);
2622 ntStatus = AFSEvaluateTargetByID( pObjectInfo,
2627 if( !NT_SUCCESS( ntStatus))
2630 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2631 AFS_TRACE_LEVEL_ERROR,
2632 "AFSValidateEntry Evaluate Target failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2633 &DirEntry->NameInformation.FileName,
2634 pObjectInfo->FileId.Cell,
2635 pObjectInfo->FileId.Volume,
2636 pObjectInfo->FileId.Vnode,
2637 pObjectInfo->FileId.Unique,
2640 try_return( ntStatus);
2644 // Check the data version of the file
2647 if( pObjectInfo->DataVersion.QuadPart == pDirEnumEntry->DataVersion.QuadPart &&
2648 !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2651 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2652 AFS_TRACE_LEVEL_VERBOSE,
2653 "AFSVerifyEntry No DV change %I64X for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2654 pObjectInfo->DataVersion.QuadPart,
2655 &DirEntry->NameInformation.FileName,
2656 pObjectInfo->FileId.Cell,
2657 pObjectInfo->FileId.Volume,
2658 pObjectInfo->FileId.Vnode,
2659 pObjectInfo->FileId.Unique);
2662 // We are ok, just get out
2665 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2667 try_return( ntStatus = STATUS_SUCCESS);
2671 // New data version so we will need to process the node based on the type
2674 switch( pDirEnumEntry->FileType)
2677 case AFS_FILE_TYPE_MOUNTPOINT:
2681 // For a mount point we need to ensure the target is the same
2684 if( !AFSIsEqualFID( &pObjectInfo->TargetFileId,
2685 &pDirEnumEntry->TargetFileId))
2691 // Update the metadata for the entry
2694 ntStatus = AFSUpdateMetaData( DirEntry,
2697 if( NT_SUCCESS( ntStatus))
2700 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2706 case AFS_FILE_TYPE_SYMLINK:
2709 ASSERT( pDirEnumEntry->TargetNameLength > 0);
2712 // Update the metadata for the entry
2715 ntStatus = AFSUpdateMetaData( DirEntry,
2718 if( NT_SUCCESS( ntStatus))
2721 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2727 case AFS_FILE_TYPE_FILE:
2729 FILE_OBJECT * pCCFileObject = NULL;
2730 BOOLEAN bPurgeExtents = FALSE;
2732 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2734 bPurgeExtents = TRUE;
2736 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2737 AFS_TRACE_LEVEL_VERBOSE,
2738 "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2739 &DirEntry->NameInformation.FileName,
2740 pObjectInfo->FileId.Cell,
2741 pObjectInfo->FileId.Volume,
2742 pObjectInfo->FileId.Vnode,
2743 pObjectInfo->FileId.Unique);
2745 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
2749 // Update the metadata for the entry
2752 ntStatus = AFSUpdateMetaData( DirEntry,
2755 if( !NT_SUCCESS( ntStatus))
2758 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2759 AFS_TRACE_LEVEL_ERROR,
2760 "AFSInvalidateCache Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
2761 &DirEntry->NameInformation.FileName,
2762 pObjectInfo->FileId.Cell,
2763 pObjectInfo->FileId.Volume,
2764 pObjectInfo->FileId.Vnode,
2765 pObjectInfo->FileId.Unique,
2771 if( pObjectInfo->Fcb != NULL)
2774 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2775 AFS_TRACE_LEVEL_VERBOSE,
2776 "AFSVerifyEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2777 &DirEntry->NameInformation.FileName,
2778 pObjectInfo->FileId.Cell,
2779 pObjectInfo->FileId.Volume,
2780 pObjectInfo->FileId.Vnode,
2781 pObjectInfo->FileId.Unique);
2783 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
2789 CcFlushCache( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2794 if( !NT_SUCCESS( stIoStatus.Status))
2797 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2798 AFS_TRACE_LEVEL_ERROR,
2799 "AFSVerifyEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
2800 &DirEntry->NameInformation.FileName,
2801 pObjectInfo->FileId.Cell,
2802 pObjectInfo->FileId.Volume,
2803 pObjectInfo->FileId.Vnode,
2804 pObjectInfo->FileId.Unique,
2806 stIoStatus.Information);
2808 ntStatus = stIoStatus.Status;
2814 CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2820 __except( EXCEPTION_EXECUTE_HANDLER)
2822 ntStatus = GetExceptionCode();
2824 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2825 AFS_TRACE_LEVEL_ERROR,
2826 "AFSVerifyEntry CcFlushCache or CcPurgeCacheSection Exception %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2827 &DirEntry->NameInformation.FileName,
2828 pObjectInfo->FileId.Cell,
2829 pObjectInfo->FileId.Volume,
2830 pObjectInfo->FileId.Vnode,
2831 pObjectInfo->FileId.Unique,
2835 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
2839 AFSFlushExtents( pObjectInfo->Fcb);
2843 // Reacquire the Fcb to purge the cache
2846 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2847 AFS_TRACE_LEVEL_VERBOSE,
2848 "AFSVerifyEntry Acquiring Fcb lock %08lX EXCL %08lX\n",
2849 &pObjectInfo->Fcb->NPFcb->Resource,
2850 PsGetCurrentThread());
2852 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
2856 // Update file sizes
2859 pObjectInfo->Fcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart;
2860 pObjectInfo->Fcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart;
2861 pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
2863 pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
2865 if ( pCCFileObject != NULL)
2867 CcSetFileSizes( pCCFileObject,
2868 (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
2871 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
2875 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2876 AFS_TRACE_LEVEL_WARNING,
2877 "AFSValidateEntry Fcb NULL %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2878 &DirEntry->NameInformation.FileName,
2879 pObjectInfo->FileId.Cell,
2880 pObjectInfo->FileId.Volume,
2881 pObjectInfo->FileId.Vnode,
2882 pObjectInfo->FileId.Unique);
2885 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2890 case AFS_FILE_TYPE_DIRECTORY:
2893 AFSFcb *pCurrentFcb = NULL;
2894 AFSDirectoryCB *pCurrentDirEntry = NULL;
2897 // For a directory or root entry flush the content of
2898 // the directory enumeration.
2901 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
2904 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2905 AFS_TRACE_LEVEL_VERBOSE_2,
2906 "AFSVerifyEntry Validating directory content for entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2907 &DirEntry->NameInformation.FileName,
2908 pObjectInfo->FileId.Cell,
2909 pObjectInfo->FileId.Volume,
2910 pObjectInfo->FileId.Vnode,
2911 pObjectInfo->FileId.Unique);
2913 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2916 ntStatus = AFSValidateDirectoryCache( pObjectInfo,
2919 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2921 if ( !NT_SUCCESS( ntStatus))
2924 try_return( ntStatus);
2929 // Update the metadata for the entry
2932 ntStatus = AFSUpdateMetaData( DirEntry,
2935 if( NT_SUCCESS( ntStatus))
2938 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2944 case AFS_FILE_TYPE_DFSLINK:
2947 UNICODE_STRING uniTargetName;
2950 // For a DFS link need to check the target name has not changed
2953 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
2955 uniTargetName.MaximumLength = uniTargetName.Length;
2957 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
2959 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
2962 if( DirEntry->NameInformation.TargetName.Length == 0 ||
2963 RtlCompareUnicodeString( &uniTargetName,
2964 &DirEntry->NameInformation.TargetName,
2969 // Update the target name
2972 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
2974 uniTargetName.Buffer,
2975 uniTargetName.Length);
2977 if( !NT_SUCCESS( ntStatus))
2980 AFSReleaseResource( &DirEntry->NonPaged->Lock);
2986 AFSReleaseResource( &DirEntry->NonPaged->Lock);
2989 // Update the metadata for the entry
2992 ntStatus = AFSUpdateMetaData( DirEntry,
2995 if( NT_SUCCESS( ntStatus))
2998 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3006 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3007 AFS_TRACE_LEVEL_WARNING,
3008 "AFSVerifyEntry Attempt to verify node of type %d\n",
3009 pObjectInfo->FileType);
3016 if( pDirEnumEntry != NULL)
3019 AFSExFreePool( pDirEnumEntry);
3027 AFSSetVolumeState( IN AFSVolumeStatusCB *VolumeStatus)
3030 NTSTATUS ntStatus = STATUS_SUCCESS;
3031 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
3032 ULONGLONG ullIndex = 0;
3033 AFSVolumeCB *pVolumeCB = NULL;
3034 AFSFcb *pFcb = NULL;
3035 AFSObjectInfoCB *pCurrentObject = NULL;
3040 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3041 AFS_TRACE_LEVEL_VERBOSE,
3042 "AFSSetVolumeState Marking volume state %d Volume Cell %08lX Volume %08lX\n",
3043 VolumeStatus->Online,
3044 VolumeStatus->FileID.Cell,
3045 VolumeStatus->FileID.Volume);
3048 // Need to locate the Fcb for the directory to purge
3051 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3052 AFS_TRACE_LEVEL_VERBOSE,
3053 "AFSSetVolumeState Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
3054 &pDevExt->Specific.RDR.VolumeTreeLock,
3055 PsGetCurrentThread());
3057 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
3060 // Locate the volume node
3063 ullIndex = AFSCreateHighIndex( &VolumeStatus->FileID);
3065 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
3067 (AFSBTreeEntry **)&pVolumeCB);
3069 if( pVolumeCB != NULL)
3072 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
3074 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3077 // Set the volume state accordingly
3080 if( VolumeStatus->Online)
3083 InterlockedAnd( (LONG *)&(pVolumeCB->Flags), ~AFS_VOLUME_FLAGS_OFFLINE);
3088 InterlockedOr( (LONG *)&(pVolumeCB->Flags), AFS_VOLUME_FLAGS_OFFLINE);
3091 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
3094 pCurrentObject = pVolumeCB->ObjectInfoListHead;;
3096 while( pCurrentObject != NULL)
3099 if( VolumeStatus->Online)
3102 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
3104 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
3106 pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
3111 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
3114 pFcb = pCurrentObject->Fcb;
3117 !(VolumeStatus->Online) &&
3118 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
3121 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3122 AFS_TRACE_LEVEL_ERROR,
3123 "AFSSetVolumeState Marking volume offline and canceling extents Volume Cell %08lX Volume %08lX\n",
3124 VolumeStatus->FileID.Cell,
3125 VolumeStatus->FileID.Volume);
3128 // Clear out the extents
3131 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3132 AFS_TRACE_LEVEL_VERBOSE,
3133 "AFSSetVolumeState Acquiring Fcb extents lock %08lX EXCL %08lX\n",
3134 &pFcb->NPFcb->Specific.File.ExtentsResource,
3135 PsGetCurrentThread());
3137 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
3140 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
3142 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
3146 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3147 AFS_TRACE_LEVEL_VERBOSE,
3148 "AFSSetVolumeState Releasing Fcb extents lock %08lX EXCL %08lX\n",
3149 &pFcb->NPFcb->Specific.File.ExtentsResource,
3150 PsGetCurrentThread());
3152 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
3155 // And get rid of them (note this involves waiting
3156 // for any writes or reads to the cache to complete)
3159 (VOID) AFSTearDownFcbExtents( pFcb);
3162 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
3165 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
3167 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
3172 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3180 AFSSetNetworkState( IN AFSNetworkStatusCB *NetworkStatus)
3183 NTSTATUS ntStatus = STATUS_SUCCESS;
3188 if( AFSGlobalRoot == NULL)
3191 try_return( ntStatus);
3194 AFSAcquireExcl( AFSGlobalRoot->VolumeLock,
3198 // Set the network state according to the information
3201 if( NetworkStatus->Online)
3204 ClearFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3209 SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3212 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3223 AFSValidateDirectoryCache( IN AFSObjectInfoCB *ObjectInfo,
3227 NTSTATUS ntStatus = STATUS_SUCCESS;
3228 BOOLEAN bAcquiredLock = FALSE;
3229 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
3230 AFSFcb *pFcb = NULL;
3235 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3236 AFS_TRACE_LEVEL_VERBOSE,
3237 "AFSValidateDirectoryCache Validating content for FID %08lX-%08lX-%08lX-%08lX\n",
3238 ObjectInfo->FileId.Cell,
3239 ObjectInfo->FileId.Volume,
3240 ObjectInfo->FileId.Vnode,
3241 ObjectInfo->FileId.Unique);
3243 if( !ExIsResourceAcquiredLite( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock))
3246 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3247 AFS_TRACE_LEVEL_VERBOSE,
3248 "AFSValidateDirectoryCache Acquiring DirectoryNodeHdr.TreeLock lock %08lX EXCL %08lX\n",
3249 ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3250 PsGetCurrentThread());
3252 AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3255 bAcquiredLock = TRUE;
3259 // Check for inconsistency between DirectoryNodeList and DirectoryNodeCount
3262 if ( ObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL &&
3263 ObjectInfo->Specific.Directory.DirectoryNodeCount > 0)
3266 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3267 AFS_TRACE_LEVEL_ERROR,
3268 "AFSValidateDirectoryCache Empty Node List but Non-Zero Node Count %08lX for dir FID %08lX-%08lX-%08lX-%08lX\n",
3269 ObjectInfo->Specific.Directory.DirectoryNodeCount,
3270 ObjectInfo->FileId.Cell,
3271 ObjectInfo->FileId.Volume,
3272 ObjectInfo->FileId.Vnode,
3273 ObjectInfo->FileId.Unique);
3277 // Reset the directory list information by clearing all valid entries
3280 pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3282 while( pCurrentDirEntry != NULL)
3285 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3287 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
3291 // If this entry has been deleted then process it here
3294 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
3295 pCurrentDirEntry->OpenReferenceCount == 0)
3298 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3299 AFS_TRACE_LEVEL_VERBOSE,
3300 "AFSValidateDirectoryCache Deleting dir entry %p name %wZ\n",
3302 &pCurrentDirEntry->NameInformation.FileName);
3304 AFSDeleteDirEntry( ObjectInfo,
3310 ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID);
3312 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3313 AFS_TRACE_LEVEL_VERBOSE,
3314 "AFSValidateDirectoryCache Clear VALID flag on DE %p Reference count %08lX\n",
3316 pCurrentDirEntry->OpenReferenceCount);
3319 // We pull the short name from the parent tree since it could change below
3322 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
3325 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3326 AFS_TRACE_LEVEL_VERBOSE,
3327 "AFSValidateDirectoryCache Removing DE %p (%08lX) from shortname tree for %wZ\n",
3329 pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3330 &pCurrentDirEntry->NameInformation.FileName);
3332 AFSRemoveShortNameDirEntry( &ObjectInfo->Specific.Directory.ShortNameTree,
3335 ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3340 pCurrentDirEntry = pNextDirEntry;
3344 // Reget the directory contents
3347 ntStatus = AFSVerifyDirectoryContent( ObjectInfo,
3350 if ( !NT_SUCCESS( ntStatus))
3352 try_return( ntStatus);
3356 // Now start again and tear down any entries not valid
3359 pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3361 while( pCurrentDirEntry != NULL)
3364 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3366 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID))
3369 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME) &&
3370 pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex > 0)
3373 if( ObjectInfo->Specific.Directory.ShortNameTree == NULL)
3376 ObjectInfo->Specific.Directory.ShortNameTree = pCurrentDirEntry;
3378 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3379 AFS_TRACE_LEVEL_VERBOSE,
3380 "AFSValidateDirectoryCache Insert DE %p to head of shortname tree for %wZ\n",
3382 &pCurrentDirEntry->NameInformation.FileName);
3384 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3389 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfo->Specific.Directory.ShortNameTree,
3392 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3393 AFS_TRACE_LEVEL_VERBOSE,
3394 "AFSValidateDirectoryCache Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
3396 pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3397 &pCurrentDirEntry->NameInformation.FileName);
3401 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3403 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3404 AFS_TRACE_LEVEL_VERBOSE,
3405 "AFSValidateDirectoryCache Insert DE %p to shortname tree for %wZ\n",
3407 &pCurrentDirEntry->NameInformation.FileName);
3412 pCurrentDirEntry = pNextDirEntry;
3417 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3418 AFS_TRACE_LEVEL_VERBOSE,
3419 "AFSValidateDirectoryCache Processing INVALID DE %p Reference count %08lX\n",
3421 pCurrentDirEntry->OpenReferenceCount);
3423 if( pCurrentDirEntry->OpenReferenceCount == 0)
3426 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3427 AFS_TRACE_LEVEL_VERBOSE,
3428 "AFSValidateDirectoryCache Deleting dir entry %wZ from parent FID %08lX-%08lX-%08lX-%08lX\n",
3429 &pCurrentDirEntry->NameInformation.FileName,
3430 ObjectInfo->FileId.Cell,
3431 ObjectInfo->FileId.Volume,
3432 ObjectInfo->FileId.Vnode,
3433 ObjectInfo->FileId.Unique);
3435 AFSDeleteDirEntry( ObjectInfo,
3441 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3442 AFS_TRACE_LEVEL_VERBOSE,
3443 "AFSValidateDirectoryCache Setting dir entry %p Name %wZ DELETED in parent FID %08lX-%08lX-%08lX-%08lX\n",
3445 &pCurrentDirEntry->NameInformation.FileName,
3446 ObjectInfo->FileId.Cell,
3447 ObjectInfo->FileId.Volume,
3448 ObjectInfo->FileId.Vnode,
3449 ObjectInfo->FileId.Unique);
3451 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
3453 AFSRemoveNameEntry( ObjectInfo,
3457 pCurrentDirEntry = pNextDirEntry;
3461 if( !AFSValidateDirList( ObjectInfo))
3464 AFSPrint("AFSValidateDirectoryCache Invalid count ...\n");
3473 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3481 AFSIsVolumeFID( IN AFSFileID *FileID)
3484 BOOLEAN bIsVolume = FALSE;
3486 if( FileID->Vnode == 1 &&
3487 FileID->Unique == 1)
3497 AFSIsFinalNode( IN AFSFcb *Fcb)
3500 BOOLEAN bIsFinalNode = FALSE;
3502 if( Fcb->Header.NodeTypeCode == AFS_ROOT_FCB ||
3503 Fcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB ||
3504 Fcb->Header.NodeTypeCode == AFS_FILE_FCB ||
3505 Fcb->Header.NodeTypeCode == AFS_DFS_LINK_FCB ||
3506 Fcb->Header.NodeTypeCode == AFS_INVALID_FCB )
3509 bIsFinalNode = TRUE;
3514 ASSERT( Fcb->Header.NodeTypeCode == AFS_MOUNT_POINT_FCB ||
3515 Fcb->Header.NodeTypeCode == AFS_SYMBOLIC_LINK_FCB);
3518 return bIsFinalNode;
3522 AFSUpdateMetaData( IN AFSDirectoryCB *DirEntry,
3523 IN AFSDirEnumEntry *DirEnumEntry)
3526 NTSTATUS ntStatus = STATUS_SUCCESS;
3527 UNICODE_STRING uniTargetName;
3528 AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
3533 pObjectInfo->TargetFileId = DirEnumEntry->TargetFileId;
3535 pObjectInfo->Expiration = DirEnumEntry->Expiration;
3537 pObjectInfo->DataVersion = DirEnumEntry->DataVersion;
3539 pObjectInfo->FileType = DirEnumEntry->FileType;
3541 pObjectInfo->CreationTime = DirEnumEntry->CreationTime;
3543 pObjectInfo->LastAccessTime = DirEnumEntry->LastAccessTime;
3545 pObjectInfo->LastWriteTime = DirEnumEntry->LastWriteTime;
3547 pObjectInfo->ChangeTime = DirEnumEntry->ChangeTime;
3549 pObjectInfo->EndOfFile = DirEnumEntry->EndOfFile;
3551 pObjectInfo->AllocationSize = DirEnumEntry->AllocationSize;
3553 pObjectInfo->FileAttributes = DirEnumEntry->FileAttributes;
3555 if( pObjectInfo->FileType == AFS_FILE_TYPE_MOUNTPOINT)
3558 pObjectInfo->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
3561 if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK ||
3562 pObjectInfo->FileType == AFS_FILE_TYPE_DFSLINK)
3565 pObjectInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
3568 pObjectInfo->EaSize = DirEnumEntry->EaSize;
3570 pObjectInfo->Links = DirEnumEntry->Links;
3572 if( DirEnumEntry->TargetNameLength > 0)
3576 // Update the target name information if needed
3579 uniTargetName.Length = (USHORT)DirEnumEntry->TargetNameLength;
3581 uniTargetName.MaximumLength = uniTargetName.Length;
3583 uniTargetName.Buffer = (WCHAR *)((char *)DirEnumEntry + DirEnumEntry->TargetNameOffset);
3585 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3588 if( DirEntry->NameInformation.TargetName.Length == 0 ||
3589 RtlCompareUnicodeString( &uniTargetName,
3590 &DirEntry->NameInformation.TargetName,
3595 // Update the target name
3598 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3600 uniTargetName.Buffer,
3601 uniTargetName.Length);
3603 if( !NT_SUCCESS( ntStatus))
3606 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3608 try_return( ntStatus);
3612 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3614 else if( DirEntry->NameInformation.TargetName.Length > 0)
3617 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3620 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER) &&
3621 DirEntry->NameInformation.TargetName.Buffer != NULL)
3623 AFSExFreePool( DirEntry->NameInformation.TargetName.Buffer);
3626 ClearFlag( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER);
3628 DirEntry->NameInformation.TargetName.Length = 0;
3629 DirEntry->NameInformation.TargetName.MaximumLength = 0;
3630 DirEntry->NameInformation.TargetName.Buffer = NULL;
3632 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3644 AFSValidateEntry( IN AFSDirectoryCB *DirEntry,
3646 IN BOOLEAN PurgeContent,
3647 IN BOOLEAN FastCall)
3650 NTSTATUS ntStatus = STATUS_SUCCESS;
3651 LARGE_INTEGER liSystemTime;
3652 AFSDirEnumEntry *pDirEnumEntry = NULL;
3653 AFSFcb *pCurrentFcb = NULL;
3654 BOOLEAN bReleaseFcb = FALSE;
3655 AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
3661 // If we have an Fcb hanging off the directory entry then be sure to acquire the locks in the
3665 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3666 AFS_TRACE_LEVEL_VERBOSE_2,
3667 "AFSValidateEntry Validating entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3668 &DirEntry->NameInformation.FileName,
3669 pObjectInfo->FileId.Cell,
3670 pObjectInfo->FileId.Volume,
3671 pObjectInfo->FileId.Vnode,
3672 pObjectInfo->FileId.Unique);
3675 // If this is a fake node then bail since the service knows nothing about it
3678 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_FAKE))
3681 try_return( ntStatus);
3685 pObjectInfo->Fcb != NULL)
3688 pCurrentFcb = pObjectInfo->Fcb;
3690 if( !ExIsResourceAcquiredLite( &pCurrentFcb->NPFcb->Resource))
3693 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3694 AFS_TRACE_LEVEL_VERBOSE,
3695 "AFSValidateEntry Acquiring Fcb lock %08lX EXCL %08lX\n",
3696 &pCurrentFcb->NPFcb->Resource,
3697 PsGetCurrentThread());
3699 AFSAcquireExcl( &pCurrentFcb->NPFcb->Resource,
3707 // This routine ensures that the current entry is valid by:
3709 // 1) Checking that the expiration time is non-zero and after where we
3713 KeQuerySystemTime( &liSystemTime);
3715 if( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) &&
3716 !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
3717 !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA) &&
3718 pObjectInfo->Expiration.QuadPart >= liSystemTime.QuadPart)
3721 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3722 AFS_TRACE_LEVEL_VERBOSE_2,
3723 "AFSValidateEntry Directory entry %wZ FID %08lX-%08lX-%08lX-%08lX VALID\n",
3724 &DirEntry->NameInformation.FileName,
3725 pObjectInfo->FileId.Cell,
3726 pObjectInfo->FileId.Volume,
3727 pObjectInfo->FileId.Vnode,
3728 pObjectInfo->FileId.Unique);
3730 try_return( ntStatus);
3734 // This node requires updating
3737 ntStatus = AFSEvaluateTargetByID( pObjectInfo,
3742 if( !NT_SUCCESS( ntStatus))
3745 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3746 AFS_TRACE_LEVEL_ERROR,
3747 "AFSValidateEntry Failed to evaluate entry %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3748 &DirEntry->NameInformation.FileName,
3749 pObjectInfo->FileId.Cell,
3750 pObjectInfo->FileId.Volume,
3751 pObjectInfo->FileId.Vnode,
3752 pObjectInfo->FileId.Unique,
3756 // Failed validation of node so return access-denied
3759 try_return( ntStatus);
3762 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3763 AFS_TRACE_LEVEL_VERBOSE,
3764 "AFSValidateEntry Validating entry %wZ FID %08lX-%08lX-%08lX-%08lX DV %I64X returned DV %I64X FT %d\n",
3765 &DirEntry->NameInformation.FileName,
3766 pObjectInfo->FileId.Cell,
3767 pObjectInfo->FileId.Volume,
3768 pObjectInfo->FileId.Vnode,
3769 pObjectInfo->FileId.Unique,
3770 pObjectInfo->DataVersion.QuadPart,
3771 pDirEnumEntry->DataVersion.QuadPart,
3772 pDirEnumEntry->FileType);
3776 // Based on the file type, process the node
3779 switch( pDirEnumEntry->FileType)
3782 case AFS_FILE_TYPE_MOUNTPOINT:
3786 // Update the metadata for the entry
3789 ntStatus = AFSUpdateMetaData( DirEntry,
3792 if( NT_SUCCESS( ntStatus))
3795 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
3801 case AFS_FILE_TYPE_SYMLINK:
3802 case AFS_FILE_TYPE_DFSLINK:
3806 // Update the metadata for the entry
3809 ntStatus = AFSUpdateMetaData( DirEntry,
3812 if( NT_SUCCESS( ntStatus))
3815 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
3821 case AFS_FILE_TYPE_FILE:
3825 // For a file where the data version has become invalid we need to
3826 // fail any current extent requests and purge the cache for the file
3827 // Can't hold the Fcb resource while doing this
3830 if( pCurrentFcb != NULL &&
3831 (pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart ||
3832 BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA)))
3835 IO_STATUS_BLOCK stIoStatus;
3836 BOOLEAN bPurgeExtents = FALSE;
3838 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3839 AFS_TRACE_LEVEL_VERBOSE_2,
3840 "AFSValidateEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3841 &DirEntry->NameInformation.FileName,
3842 pObjectInfo->FileId.Cell,
3843 pObjectInfo->FileId.Volume,
3844 pObjectInfo->FileId.Vnode,
3845 pObjectInfo->FileId.Unique);
3847 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
3849 bPurgeExtents = TRUE;
3851 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3852 AFS_TRACE_LEVEL_VERBOSE,
3853 "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3854 &DirEntry->NameInformation.FileName,
3855 pObjectInfo->FileId.Cell,
3856 pObjectInfo->FileId.Volume,
3857 pObjectInfo->FileId.Vnode,
3858 pObjectInfo->FileId.Unique);
3860 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
3866 CcFlushCache( &pCurrentFcb->NPFcb->SectionObjectPointers,
3871 if( !NT_SUCCESS( stIoStatus.Status))
3874 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
3875 AFS_TRACE_LEVEL_ERROR,
3876 "AFSValidateEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
3877 &DirEntry->NameInformation.FileName,
3878 pObjectInfo->FileId.Cell,
3879 pObjectInfo->FileId.Volume,
3880 pObjectInfo->FileId.Vnode,
3881 pObjectInfo->FileId.Unique,
3883 stIoStatus.Information);
3885 ntStatus = stIoStatus.Status;
3891 CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
3897 __except( EXCEPTION_EXECUTE_HANDLER)
3899 ntStatus = GetExceptionCode();
3901 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
3902 AFS_TRACE_LEVEL_ERROR,
3903 "AFSValidateEntry CcFlushCache or CcPurgeCacheSection exception %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
3904 &DirEntry->NameInformation.FileName,
3905 pObjectInfo->FileId.Cell,
3906 pObjectInfo->FileId.Volume,
3907 pObjectInfo->FileId.Vnode,
3908 pObjectInfo->FileId.Unique,
3913 AFSReleaseResource( &pCurrentFcb->NPFcb->Resource);
3917 AFSFlushExtents( pCurrentFcb);
3921 // Reacquire the Fcb to purge the cache
3924 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3925 AFS_TRACE_LEVEL_VERBOSE,
3926 "AFSValidateEntry Acquiring Fcb lock %08lX EXCL %08lX\n",
3927 &pCurrentFcb->NPFcb->Resource,
3928 PsGetCurrentThread());
3930 AFSAcquireExcl( &pCurrentFcb->NPFcb->Resource,
3935 // Update the metadata for the entry
3938 ntStatus = AFSUpdateMetaData( DirEntry,
3941 if( !NT_SUCCESS( ntStatus))
3944 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3945 AFS_TRACE_LEVEL_ERROR,
3946 "AFSValidateEntry Meta Data Update failed %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,
3957 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
3960 // Update file sizes
3963 if( pObjectInfo->Fcb != NULL)
3965 FILE_OBJECT *pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
3967 pObjectInfo->Fcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart;
3968 pObjectInfo->Fcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart;
3969 pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
3971 if ( pCCFileObject != NULL)
3973 CcSetFileSizes( pCCFileObject,
3974 (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
3981 case AFS_FILE_TYPE_DIRECTORY:
3984 AFSDirectoryCB *pCurrentDirEntry = NULL;
3986 if( pCurrentFcb != NULL &&
3987 pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
3991 // For a directory or root entry flush the content of
3992 // the directory enumeration.
3995 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3996 AFS_TRACE_LEVEL_VERBOSE,
3997 "AFSValidateEntry Acquiring DirectoryNodeHdr.TreeLock lock %08lX EXCL %08lX\n",
3998 pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3999 PsGetCurrentThread());
4001 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
4004 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4005 AFS_TRACE_LEVEL_VERBOSE_2,
4006 "AFSValidateEntry Validating directory content for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4007 &DirEntry->NameInformation.FileName,
4008 pObjectInfo->FileId.Cell,
4009 pObjectInfo->FileId.Volume,
4010 pObjectInfo->FileId.Vnode,
4011 pObjectInfo->FileId.Unique);
4013 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
4016 AFSValidateDirectoryCache( pCurrentFcb->ObjectInformation,
4019 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
4022 if( !NT_SUCCESS( ntStatus))
4025 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4026 AFS_TRACE_LEVEL_ERROR,
4027 "AFSValidateEntry Failed to re-enumerate %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4028 &DirEntry->NameInformation.FileName,
4029 pObjectInfo->FileId.Cell,
4030 pObjectInfo->FileId.Volume,
4031 pObjectInfo->FileId.Vnode,
4032 pObjectInfo->FileId.Unique,
4040 // Update the metadata for the entry
4043 ntStatus = AFSUpdateMetaData( DirEntry,
4046 if( NT_SUCCESS( ntStatus))
4049 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
4057 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4058 AFS_TRACE_LEVEL_WARNING,
4059 "AFSValidateEntry Attempt to verify node of type %d\n",
4060 pObjectInfo->FileType);
4070 AFSReleaseResource( &pCurrentFcb->NPFcb->Resource);
4073 if( pDirEnumEntry != NULL)
4076 AFSExFreePool( pDirEnumEntry);
4084 AFSInitializeSpecialShareNameList()
4087 NTSTATUS ntStatus = STATUS_SUCCESS;
4088 AFSDirectoryCB *pDirNode = NULL, *pLastDirNode = NULL;
4089 AFSObjectInfoCB *pObjectInfoCB = NULL;
4090 UNICODE_STRING uniShareName;
4091 ULONG ulEntryLength = 0;
4092 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
4097 RtlInitUnicodeString( &uniShareName,
4100 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
4103 if( pObjectInfoCB == NULL)
4106 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4109 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4110 AFS_TRACE_LEVEL_VERBOSE,
4111 "AFSInitializeSpecialShareNameList (srvsvc) Initializing count (1) on object %08lX\n",
4114 pObjectInfoCB->ObjectReferenceCount = 1;
4116 pObjectInfoCB->FileType = AFS_FILE_TYPE_SPECIAL_SHARE_NAME;
4118 ulEntryLength = sizeof( AFSDirectoryCB) +
4119 uniShareName.Length;
4121 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
4125 if( pDirNode == NULL)
4128 AFSDeleteObjectInfo( pObjectInfoCB);
4130 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4133 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
4134 sizeof( AFSNonPagedDirectoryCB),
4135 AFS_DIR_ENTRY_NP_TAG);
4137 if( pNonPagedDirEntry == NULL)
4140 ExFreePool( pDirNode);
4142 AFSDeleteObjectInfo( pObjectInfoCB);
4144 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4147 RtlZeroMemory( pDirNode,
4150 RtlZeroMemory( pNonPagedDirEntry,
4151 sizeof( AFSNonPagedDirectoryCB));
4153 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
4155 pDirNode->NonPaged = pNonPagedDirEntry;
4157 pDirNode->ObjectInformation = pObjectInfoCB;
4163 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_SERVER_SERVICE);
4165 pDirNode->NameInformation.FileName.Length = uniShareName.Length;
4167 pDirNode->NameInformation.FileName.MaximumLength = uniShareName.Length;
4169 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
4171 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
4172 uniShareName.Buffer,
4173 pDirNode->NameInformation.FileName.Length);
4175 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
4178 AFSSpecialShareNames = pDirNode;
4180 pLastDirNode = pDirNode;
4182 RtlInitUnicodeString( &uniShareName,
4185 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
4188 if( pObjectInfoCB == NULL)
4191 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4194 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4195 AFS_TRACE_LEVEL_VERBOSE,
4196 "AFSInitializeSpecialShareNameList (wkssvc) Initializing count (1) on object %08lX\n",
4199 pObjectInfoCB->ObjectReferenceCount = 1;
4201 pObjectInfoCB->FileType = AFS_FILE_TYPE_SPECIAL_SHARE_NAME;
4203 ulEntryLength = sizeof( AFSDirectoryCB) +
4204 uniShareName.Length;
4206 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
4210 if( pDirNode == NULL)
4213 AFSDeleteObjectInfo( pObjectInfoCB);
4215 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4218 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
4219 sizeof( AFSNonPagedDirectoryCB),
4220 AFS_DIR_ENTRY_NP_TAG);
4222 if( pNonPagedDirEntry == NULL)
4225 ExFreePool( pDirNode);
4227 AFSDeleteObjectInfo( pObjectInfoCB);
4229 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4232 RtlZeroMemory( pDirNode,
4235 RtlZeroMemory( pNonPagedDirEntry,
4236 sizeof( AFSNonPagedDirectoryCB));
4238 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
4240 pDirNode->NonPaged = pNonPagedDirEntry;
4242 pDirNode->ObjectInformation = pObjectInfoCB;
4248 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_WORKSTATION_SERVICE);
4250 pDirNode->NameInformation.FileName.Length = uniShareName.Length;
4252 pDirNode->NameInformation.FileName.MaximumLength = uniShareName.Length;
4254 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
4256 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
4257 uniShareName.Buffer,
4258 pDirNode->NameInformation.FileName.Length);
4260 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
4263 pLastDirNode->ListEntry.fLink = pDirNode;
4265 pDirNode->ListEntry.bLink = pLastDirNode;
4267 pLastDirNode = pDirNode;
4269 RtlInitUnicodeString( &uniShareName,
4272 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
4275 if( pObjectInfoCB == NULL)
4278 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4281 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4282 AFS_TRACE_LEVEL_VERBOSE,
4283 "AFSInitializeSpecialShareNameList (ipc$) Initializing count (1) on object %08lX\n",
4286 pObjectInfoCB->ObjectReferenceCount = 1;
4288 pObjectInfoCB->FileType = AFS_FILE_TYPE_SPECIAL_SHARE_NAME;
4290 ulEntryLength = sizeof( AFSDirectoryCB) +
4291 uniShareName.Length;
4293 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
4297 if( pDirNode == NULL)
4300 AFSDeleteObjectInfo( pObjectInfoCB);
4302 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4305 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
4306 sizeof( AFSNonPagedDirectoryCB),
4307 AFS_DIR_ENTRY_NP_TAG);
4309 if( pNonPagedDirEntry == NULL)
4312 ExFreePool( pDirNode);
4314 AFSDeleteObjectInfo( pObjectInfoCB);
4316 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4319 RtlZeroMemory( pDirNode,
4322 RtlZeroMemory( pNonPagedDirEntry,
4323 sizeof( AFSNonPagedDirectoryCB));
4325 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
4327 pDirNode->NonPaged = pNonPagedDirEntry;
4329 pDirNode->ObjectInformation = pObjectInfoCB;
4335 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_IPC);
4337 pDirNode->NameInformation.FileName.Length = uniShareName.Length;
4339 pDirNode->NameInformation.FileName.MaximumLength = uniShareName.Length;
4341 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
4343 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
4344 uniShareName.Buffer,
4345 pDirNode->NameInformation.FileName.Length);
4347 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
4350 pLastDirNode->ListEntry.fLink = pDirNode;
4352 pDirNode->ListEntry.bLink = pLastDirNode;
4356 if( !NT_SUCCESS( ntStatus))
4359 if( AFSSpecialShareNames != NULL)
4362 pDirNode = AFSSpecialShareNames;
4364 while( pDirNode != NULL)
4367 pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
4369 AFSDeleteObjectInfo( pDirNode->ObjectInformation);
4371 ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
4373 ExFreePool( pDirNode->NonPaged);
4375 ExFreePool( pDirNode);
4377 pDirNode = pLastDirNode;
4380 AFSSpecialShareNames = NULL;
4389 AFSGetSpecialShareNameEntry( IN UNICODE_STRING *ShareName,
4390 IN UNICODE_STRING *SecondaryName)
4393 AFSDirectoryCB *pDirectoryCB = NULL;
4394 ULONGLONG ullHash = 0;
4395 UNICODE_STRING uniFullShareName;
4401 // Build up the entire name here. We are guaranteed that if there is a
4402 // secondary name, it is pointing to a portion of the share name buffer
4405 if( SecondaryName->Length > 0 &&
4406 SecondaryName->Buffer != NULL)
4409 uniFullShareName = *SecondaryName;
4412 // The calling routine strips off the leading slash so add it back in
4415 uniFullShareName.Buffer--;
4416 uniFullShareName.Length += sizeof( WCHAR);
4417 uniFullShareName.MaximumLength += sizeof( WCHAR);
4420 // And the share name
4423 uniFullShareName.Buffer -= (ShareName->Length/sizeof( WCHAR));
4424 uniFullShareName.Length += ShareName->Length;
4425 uniFullShareName.MaximumLength += ShareName->Length;
4430 uniFullShareName = *ShareName;
4434 // Generate our hash value
4437 ullHash = AFSGenerateCRC( &uniFullShareName,
4441 // Loop through our special share names to see if this is one of them
4444 pDirectoryCB = AFSSpecialShareNames;
4446 while( pDirectoryCB != NULL)
4449 if( ullHash == pDirectoryCB->CaseInsensitiveTreeEntry.HashIndex)
4455 pDirectoryCB = (AFSDirectoryCB *)pDirectoryCB->ListEntry.fLink;
4459 return pDirectoryCB;
4463 AFSWaitOnQueuedFlushes( IN AFSFcb *Fcb)
4467 // Block on the queue flush event
4470 KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
4480 AFSWaitOnQueuedReleases()
4483 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
4486 // Block on the queue flush event
4489 KeWaitForSingleObject( &pRDRDeviceExt->Specific.RDR.QueuedReleaseExtentEvent,
4499 AFSIsEqualFID( IN AFSFileID *FileId1,
4500 IN AFSFileID *FileId2)
4503 BOOLEAN bIsEqual = FALSE;
4505 if( FileId1->Unique == FileId2->Unique &&
4506 FileId1->Vnode == FileId2->Vnode &&
4507 FileId1->Volume == FileId2->Volume &&
4508 FileId1->Cell == FileId2->Cell)
4518 AFSResetDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB)
4521 NTSTATUS ntStatus = STATUS_SUCCESS;
4522 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
4527 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
4530 // Reset the directory list information
4533 pCurrentDirEntry = ObjectInfoCB->Specific.Directory.DirectoryNodeListHead;
4535 while( pCurrentDirEntry != NULL)
4538 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
4540 if( pCurrentDirEntry->OpenReferenceCount == 0)
4543 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
4544 AFS_TRACE_LEVEL_VERBOSE,
4545 "AFSResetDirectoryContent Deleting dir entry %p for %wZ\n",
4547 &pCurrentDirEntry->NameInformation.FileName);
4549 AFSDeleteDirEntry( ObjectInfoCB,
4555 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
4556 AFS_TRACE_LEVEL_VERBOSE,
4557 "AFSResetDirectoryContent Setting DELETE flag in dir entry %p for %wZ\n",
4559 &pCurrentDirEntry->NameInformation.FileName);
4561 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
4563 AFSRemoveNameEntry( ObjectInfoCB,
4567 pCurrentDirEntry = pNextDirEntry;
4570 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = NULL;
4572 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = NULL;
4574 ObjectInfoCB->Specific.Directory.ShortNameTree = NULL;
4576 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = NULL;
4578 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = NULL;
4580 ObjectInfoCB->Specific.Directory.DirectoryNodeCount = 0;
4582 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
4583 AFS_TRACE_LEVEL_VERBOSE,
4584 "AFSResetDirectoryContent Reset count to 0 on parent FID %08lX-%08lX-%08lX-%08lX\n",
4585 ObjectInfoCB->FileId.Cell,
4586 ObjectInfoCB->FileId.Volume,
4587 ObjectInfoCB->FileId.Vnode,
4588 ObjectInfoCB->FileId.Unique);
4595 AFSEnumerateGlobalRoot( IN GUID *AuthGroup)
4598 NTSTATUS ntStatus = STATUS_SUCCESS;
4599 AFSDirectoryCB *pDirGlobalDirNode = NULL;
4600 UNICODE_STRING uniFullName;
4605 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4606 AFS_TRACE_LEVEL_VERBOSE,
4607 "AFSEnumerateGlobalRoot Acquiring GlobalRoot DirectoryNodeHdr.TreeLock lock %08lX EXCL %08lX\n",
4608 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4609 PsGetCurrentThread());
4611 AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4614 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
4617 try_return( ntStatus);
4621 // Initialize the root information
4624 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.ContentIndex = 1;
4627 // Enumerate the shares in the volume
4630 ntStatus = AFSEnumerateDirectory( AuthGroup,
4631 &AFSGlobalRoot->ObjectInformation,
4634 if( !NT_SUCCESS( ntStatus))
4637 try_return( ntStatus);
4640 pDirGlobalDirNode = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead;
4643 // Indicate the node is initialized
4646 SetFlag( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
4648 uniFullName.MaximumLength = PAGE_SIZE;
4649 uniFullName.Length = 0;
4651 uniFullName.Buffer = (WCHAR *)AFSLibExAllocatePoolWithTag( PagedPool,
4652 uniFullName.MaximumLength,
4653 AFS_GENERIC_MEMORY_12_TAG);
4655 if( uniFullName.Buffer == NULL)
4659 // Reset the directory content
4662 AFSResetDirectoryContent( &AFSGlobalRoot->ObjectInformation);
4664 ClearFlag( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
4666 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4670 // Populate our list of entries in the NP enumeration list
4673 while( pDirGlobalDirNode != NULL)
4676 uniFullName.Buffer[ 0] = L'\\';
4677 uniFullName.Buffer[ 1] = L'\\';
4679 uniFullName.Length = 2 * sizeof( WCHAR);
4681 RtlCopyMemory( &uniFullName.Buffer[ 2],
4682 AFSServerName.Buffer,
4683 AFSServerName.Length);
4685 uniFullName.Length += AFSServerName.Length;
4687 uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)] = L'\\';
4689 uniFullName.Length += sizeof( WCHAR);
4691 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
4692 pDirGlobalDirNode->NameInformation.FileName.Buffer,
4693 pDirGlobalDirNode->NameInformation.FileName.Length);
4695 uniFullName.Length += pDirGlobalDirNode->NameInformation.FileName.Length;
4697 AFSAddConnectionEx( &uniFullName,
4698 RESOURCEDISPLAYTYPE_SHARE,
4701 pDirGlobalDirNode = (AFSDirectoryCB *)pDirGlobalDirNode->ListEntry.fLink;
4704 AFSExFreePool( uniFullName.Buffer);
4708 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4715 AFSIsRelativeName( IN UNICODE_STRING *Name)
4718 BOOLEAN bIsRelative = FALSE;
4720 if( Name->Buffer[ 0] != L'\\')
4730 AFSUpdateName( IN UNICODE_STRING *Name)
4735 while( usIndex < Name->Length/sizeof( WCHAR))
4738 if( Name->Buffer[ usIndex] == L'/')
4741 Name->Buffer[ usIndex] = L'\\';
4751 AFSUpdateTargetName( IN OUT UNICODE_STRING *TargetName,
4752 IN OUT ULONG *Flags,
4753 IN WCHAR *NameBuffer,
4754 IN USHORT NameLength)
4757 NTSTATUS ntStatus = STATUS_SUCCESS;
4758 WCHAR *pTmpBuffer = NULL;
4764 // If we have enough space then just move in the name otherwise
4765 // allocate a new buffer
4768 if( TargetName->Length < NameLength)
4771 pTmpBuffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4773 AFS_NAME_BUFFER_FIVE_TAG);
4775 if( pTmpBuffer == NULL)
4778 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4781 if( BooleanFlagOn( *Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
4784 AFSExFreePool( TargetName->Buffer);
4787 TargetName->MaximumLength = NameLength;
4789 TargetName->Buffer = pTmpBuffer;
4791 SetFlag( *Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER);
4794 TargetName->Length = NameLength;
4796 RtlCopyMemory( TargetName->Buffer,
4798 TargetName->Length);
4801 // Update the name in the buffer
4804 AFSUpdateName( TargetName);
4815 AFSInitNameArray( IN AFSDirectoryCB *DirectoryCB,
4816 IN ULONG InitialElementCount)
4819 AFSNameArrayHdr *pNameArray = NULL;
4820 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4825 if( InitialElementCount == 0)
4828 InitialElementCount = pDevExt->Specific.RDR.NameArrayLength;
4831 pNameArray = (AFSNameArrayHdr *)AFSExAllocatePoolWithTag( PagedPool,
4832 sizeof( AFSNameArrayHdr) +
4833 (InitialElementCount * sizeof( AFSNameArrayCB)),
4834 AFS_NAME_ARRAY_TAG);
4836 if( pNameArray == NULL)
4839 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4840 AFS_TRACE_LEVEL_ERROR,
4841 "AFSInitNameArray Failed to allocate name array\n");
4843 try_return( pNameArray);
4846 RtlZeroMemory( pNameArray,
4847 sizeof( AFSNameArrayHdr) +
4848 (InitialElementCount * sizeof( AFSNameArrayCB)));
4850 pNameArray->MaxElementCount = InitialElementCount;
4852 if( DirectoryCB != NULL)
4855 pNameArray->CurrentEntry = &pNameArray->ElementArray[ 0];
4857 InterlockedIncrement( &pNameArray->Count);
4859 InterlockedIncrement( &DirectoryCB->OpenReferenceCount);
4861 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4862 AFS_TRACE_LEVEL_VERBOSE,
4863 "AFSInitNameArray Increment count on %wZ DE %p Cnt %d\n",
4864 &DirectoryCB->NameInformation.FileName,
4866 DirectoryCB->OpenReferenceCount);
4868 pNameArray->CurrentEntry->DirectoryCB = DirectoryCB;
4870 pNameArray->CurrentEntry->Component = DirectoryCB->NameInformation.FileName;
4872 pNameArray->CurrentEntry->FileId = DirectoryCB->ObjectInformation->FileId;
4884 AFSPopulateNameArray( IN AFSNameArrayHdr *NameArray,
4885 IN UNICODE_STRING *Path,
4886 IN AFSDirectoryCB *DirectoryCB)
4889 NTSTATUS ntStatus = STATUS_SUCCESS;
4890 AFSNameArrayCB *pCurrentElement = NULL;
4891 UNICODE_STRING uniComponentName, uniRemainingPath;
4892 AFSObjectInfoCB *pCurrentObject = NULL;
4893 ULONG ulTotalCount = 0;
4895 USHORT usLength = 0;
4901 // Init some info in the header
4904 pCurrentElement = &NameArray->ElementArray[ 0];
4906 NameArray->CurrentEntry = pCurrentElement;
4909 // The first entry points at the root
4912 pCurrentElement->DirectoryCB = DirectoryCB->ObjectInformation->VolumeCB->DirectoryCB;
4914 InterlockedIncrement( &pCurrentElement->DirectoryCB->OpenReferenceCount);
4916 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4917 AFS_TRACE_LEVEL_VERBOSE,
4918 "AFSPopulateNameArray Increment count on volume %wZ DE %p Cnt %d\n",
4919 &pCurrentElement->DirectoryCB->NameInformation.FileName,
4920 pCurrentElement->DirectoryCB,
4921 pCurrentElement->DirectoryCB->OpenReferenceCount);
4923 pCurrentElement->Component = DirectoryCB->ObjectInformation->VolumeCB->DirectoryCB->NameInformation.FileName;
4925 pCurrentElement->FileId = DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
4927 NameArray->Count = 1;
4929 NameArray->LinkCount = 0;
4932 // If the root is the parent then we are done ...
4935 if( &DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation == DirectoryCB->ObjectInformation)
4937 try_return( ntStatus);
4949 AFSPopulateNameArrayFromRelatedArray( IN AFSNameArrayHdr *NameArray,
4950 IN AFSNameArrayHdr *RelatedNameArray,
4951 IN AFSDirectoryCB *DirectoryCB)
4954 NTSTATUS ntStatus = STATUS_SUCCESS;
4955 AFSNameArrayCB *pCurrentElement = NULL, *pCurrentRelatedElement = NULL;
4956 UNICODE_STRING uniComponentName, uniRemainingPath;
4957 AFSObjectInfoCB *pObjectInfo = NULL;
4958 ULONG ulTotalCount = 0;
4960 USHORT usLength = 0;
4966 // Init some info in the header
4969 pCurrentElement = &NameArray->ElementArray[ 0];
4971 pCurrentRelatedElement = &RelatedNameArray->ElementArray[ 0];
4973 NameArray->Count = 0;
4975 NameArray->LinkCount = RelatedNameArray->LinkCount;
4978 // Populate the name array with the data from the related array
4984 pCurrentElement->DirectoryCB = pCurrentRelatedElement->DirectoryCB;
4986 pCurrentElement->Component = pCurrentRelatedElement->DirectoryCB->NameInformation.FileName;
4988 pCurrentElement->FileId = pCurrentElement->DirectoryCB->ObjectInformation->FileId;
4990 InterlockedIncrement( &pCurrentElement->DirectoryCB->OpenReferenceCount);
4992 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4993 AFS_TRACE_LEVEL_VERBOSE,
4994 "AFSPopulateNameArrayFromRelatedArray Increment count on %wZ DE %p Cnt %d\n",
4995 &pCurrentElement->DirectoryCB->NameInformation.FileName,
4996 pCurrentElement->DirectoryCB,
4997 pCurrentElement->DirectoryCB->OpenReferenceCount);
4999 InterlockedIncrement( &NameArray->Count);
5001 if( pCurrentElement->DirectoryCB == DirectoryCB ||
5002 NameArray->Count == RelatedNameArray->Count)
5014 pCurrentRelatedElement++;
5017 if( NameArray->Count > 0)
5019 NameArray->CurrentEntry = pCurrentElement;
5027 AFSFreeNameArray( IN AFSNameArrayHdr *NameArray)
5030 NTSTATUS ntStatus = STATUS_SUCCESS;
5031 AFSNameArrayCB *pCurrentElement = NULL;
5036 pCurrentElement = &NameArray->ElementArray[ 0];
5041 if( pCurrentElement->DirectoryCB == NULL)
5047 InterlockedDecrement( &pCurrentElement->DirectoryCB->OpenReferenceCount);
5049 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5050 AFS_TRACE_LEVEL_VERBOSE,
5051 "AFSFreeNameArray Decrement count on %wZ DE %p Cnt %d\n",
5052 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5053 pCurrentElement->DirectoryCB,
5054 pCurrentElement->DirectoryCB->OpenReferenceCount);
5059 AFSExFreePool( NameArray);
5066 AFSInsertNextElement( IN AFSNameArrayHdr *NameArray,
5067 IN AFSDirectoryCB *DirEntry)
5070 NTSTATUS ntStatus = STATUS_SUCCESS;
5071 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
5076 if( NameArray->Count == NameArray->MaxElementCount)
5079 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5082 if( NameArray->CurrentEntry != NULL &&
5083 NameArray->CurrentEntry->DirectoryCB == DirEntry)
5086 try_return( ntStatus);
5089 if( NameArray->Count > 0)
5092 NameArray->CurrentEntry++;
5096 NameArray->CurrentEntry = &NameArray->ElementArray[ 0];
5099 InterlockedIncrement( &NameArray->Count);
5101 InterlockedIncrement( &DirEntry->OpenReferenceCount);
5103 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5104 AFS_TRACE_LEVEL_VERBOSE,
5105 "AFSInsertNextElement Increment count on %wZ DE %p Cnt %d\n",
5106 &DirEntry->NameInformation.FileName,
5108 DirEntry->OpenReferenceCount);
5110 NameArray->CurrentEntry->DirectoryCB = DirEntry;
5112 NameArray->CurrentEntry->Component = DirEntry->NameInformation.FileName;
5114 NameArray->CurrentEntry->FileId = DirEntry->ObjectInformation->FileId;
5125 AFSReplaceCurrentElement( IN AFSNameArrayHdr *NameArray,
5126 IN AFSDirectoryCB *DirectoryCB)
5129 ASSERT( NameArray->CurrentEntry != NULL);
5131 InterlockedDecrement( &NameArray->CurrentEntry->DirectoryCB->OpenReferenceCount);
5133 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5134 AFS_TRACE_LEVEL_VERBOSE,
5135 "AFSReplaceCurrentElement Decrement count on %wZ DE %p Cnt %d\n",
5136 &NameArray->CurrentEntry->DirectoryCB->NameInformation.FileName,
5137 NameArray->CurrentEntry->DirectoryCB,
5138 NameArray->CurrentEntry->DirectoryCB->OpenReferenceCount);
5140 InterlockedIncrement( &DirectoryCB->OpenReferenceCount);
5142 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5143 AFS_TRACE_LEVEL_VERBOSE,
5144 "AFSReplaceCurrentElement Increment count on %wZ DE %p Cnt %d\n",
5145 &DirectoryCB->NameInformation.FileName,
5147 DirectoryCB->OpenReferenceCount);
5149 NameArray->CurrentEntry->DirectoryCB = DirectoryCB;
5151 NameArray->CurrentEntry->Component = DirectoryCB->NameInformation.FileName;
5153 NameArray->CurrentEntry->FileId = DirectoryCB->ObjectInformation->FileId;
5155 if( DirectoryCB->ObjectInformation->ParentObjectInformation == NULL)
5158 SetFlag( NameArray->CurrentEntry->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5165 AFSBackupEntry( IN AFSNameArrayHdr *NameArray)
5168 AFSDirectoryCB *pCurrentDirEntry = NULL;
5173 if( NameArray->Count == 0)
5175 try_return( pCurrentDirEntry);
5178 InterlockedDecrement( &NameArray->CurrentEntry->DirectoryCB->OpenReferenceCount);
5180 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5181 AFS_TRACE_LEVEL_VERBOSE,
5182 "AFSBackupEntry Decrement count on %wZ DE %p Cnt %d\n",
5183 &NameArray->CurrentEntry->DirectoryCB->NameInformation.FileName,
5184 NameArray->CurrentEntry->DirectoryCB,
5185 NameArray->CurrentEntry->DirectoryCB->OpenReferenceCount);
5187 NameArray->CurrentEntry->DirectoryCB = NULL;
5189 if( InterlockedDecrement( &NameArray->Count) == 0)
5191 NameArray->CurrentEntry = NULL;
5195 NameArray->CurrentEntry--;
5196 pCurrentDirEntry = NameArray->CurrentEntry->DirectoryCB;
5204 return pCurrentDirEntry;
5208 AFSGetParentEntry( IN AFSNameArrayHdr *NameArray)
5211 AFSDirectoryCB *pDirEntry = NULL;
5212 AFSNameArrayCB *pElement = NULL;
5217 if( NameArray->Count == 0 ||
5218 NameArray->Count == 1)
5221 try_return( pDirEntry = NULL);
5224 pElement = &NameArray->ElementArray[ NameArray->Count - 2];
5226 pDirEntry = pElement->DirectoryCB;
5237 AFSResetNameArray( IN AFSNameArrayHdr *NameArray,
5238 IN AFSDirectoryCB *DirEntry)
5241 AFSNameArrayCB *pCurrentElement = NULL;
5242 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
5247 pCurrentElement = &NameArray->ElementArray[ 0];
5252 if( pCurrentElement->DirectoryCB == NULL)
5258 InterlockedDecrement( &pCurrentElement->DirectoryCB->OpenReferenceCount);
5260 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5261 AFS_TRACE_LEVEL_VERBOSE,
5262 "AFSResetNameArray Decrement count on %wZ DE %p Cnt %d\n",
5263 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5264 pCurrentElement->DirectoryCB,
5265 pCurrentElement->DirectoryCB->OpenReferenceCount);
5270 RtlZeroMemory( NameArray,
5271 sizeof( AFSNameArrayHdr) +
5272 ((pDevExt->Specific.RDR.NameArrayLength - 1) * sizeof( AFSNameArrayCB)));
5274 NameArray->MaxElementCount = pDevExt->Specific.RDR.NameArrayLength;
5276 if( DirEntry != NULL)
5279 NameArray->CurrentEntry = &NameArray->ElementArray[ 0];
5281 InterlockedIncrement( &NameArray->Count);
5283 InterlockedIncrement( &DirEntry->OpenReferenceCount);
5285 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5286 AFS_TRACE_LEVEL_VERBOSE,
5287 "AFSResetNameArray Increment count on %wZ DE %p Cnt %d\n",
5288 &DirEntry->NameInformation.FileName,
5290 DirEntry->OpenReferenceCount);
5292 NameArray->CurrentEntry->DirectoryCB = DirEntry;
5294 NameArray->CurrentEntry->Component = DirEntry->NameInformation.FileName;
5296 NameArray->CurrentEntry->FileId = DirEntry->ObjectInformation->FileId;
5304 AFSDumpNameArray( IN AFSNameArrayHdr *NameArray)
5307 AFSNameArrayCB *pCurrentElement = NULL;
5309 pCurrentElement = &NameArray->ElementArray[ 0];
5311 AFSPrint("AFSDumpNameArray Start (%d)\n", NameArray->Count);
5313 while( pCurrentElement->DirectoryCB != NULL)
5316 AFSPrint("FID %08lX-%08lX-%08lX-%08lX %wZ\n",
5317 pCurrentElement->FileId.Cell,
5318 pCurrentElement->FileId.Volume,
5319 pCurrentElement->FileId.Vnode,
5320 pCurrentElement->FileId.Unique,
5321 &pCurrentElement->DirectoryCB->NameInformation.FileName);
5326 AFSPrint("AFSDumpNameArray End\n\n");
5332 AFSSetEnumerationEvent( IN AFSFcb *Fcb)
5336 // Depending on the type of node, set the event
5339 switch( Fcb->Header.NodeTypeCode)
5342 case AFS_DIRECTORY_FCB:
5345 KeSetEvent( &Fcb->NPFcb->Specific.Directory.DirectoryEnumEvent,
5349 InterlockedIncrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
5358 KeSetEvent( &Fcb->NPFcb->Specific.Directory.DirectoryEnumEvent,
5362 InterlockedIncrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
5372 AFSClearEnumerationEvent( IN AFSFcb *Fcb)
5376 // Depending on the type of node, set the event
5379 switch( Fcb->Header.NodeTypeCode)
5382 case AFS_DIRECTORY_FCB:
5385 ASSERT( Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0);
5387 if( InterlockedDecrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount) == 0)
5390 KeClearEvent( &Fcb->NPFcb->Specific.Directory.DirectoryEnumEvent);
5400 ASSERT( Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0);
5402 if( InterlockedDecrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount) == 0)
5405 KeClearEvent( &Fcb->NPFcb->Specific.Directory.DirectoryEnumEvent);
5416 AFSIsEnumerationInProcess( IN AFSObjectInfoCB *ObjectInfo)
5419 BOOLEAN bIsInProcess = FALSE;
5424 if( ObjectInfo->Fcb == NULL)
5427 try_return( bIsInProcess);
5431 // Depending on the type of node, set the event
5434 switch( ObjectInfo->Fcb->Header.NodeTypeCode)
5437 case AFS_DIRECTORY_FCB:
5440 if( KeReadStateEvent( &ObjectInfo->Fcb->NPFcb->Specific.Directory.DirectoryEnumEvent))
5443 bIsInProcess = TRUE;
5453 if( KeReadStateEvent( &ObjectInfo->Fcb->NPFcb->Specific.Directory.DirectoryEnumEvent))
5456 bIsInProcess = TRUE;
5468 return bIsInProcess;
5472 AFSVerifyVolume( IN ULONGLONG ProcessId,
5473 IN AFSVolumeCB *VolumeCB)
5476 NTSTATUS ntStatus = STATUS_SUCCESS;
5483 AFSInitPIOCtlDirectoryCB( IN AFSObjectInfoCB *ObjectInfo)
5486 NTSTATUS ntStatus = STATUS_SUCCESS;
5487 AFSObjectInfoCB *pObjectInfoCB = NULL;
5488 AFSDirectoryCB *pDirNode = NULL;
5489 ULONG ulEntryLength = 0;
5490 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
5495 pObjectInfoCB = AFSAllocateObjectInfo( ObjectInfo,
5498 if( pObjectInfoCB == NULL)
5501 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5504 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
5505 AFS_TRACE_LEVEL_VERBOSE,
5506 "AFSInitPIOCtlDirectoryCB Initializing count (1) on object %08lX\n",
5509 pObjectInfoCB->ObjectReferenceCount = 1;
5511 pObjectInfoCB->FileType = AFS_FILE_TYPE_PIOCTL;
5513 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
5515 ulEntryLength = sizeof( AFSDirectoryCB) + AFSPIOCtlName.Length;
5517 pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
5521 if( pDirNode == NULL)
5524 AFSDeleteObjectInfo( pObjectInfoCB);
5526 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5529 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
5530 sizeof( AFSNonPagedDirectoryCB),
5531 AFS_DIR_ENTRY_NP_TAG);
5533 if( pNonPagedDirEntry == NULL)
5536 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5539 RtlZeroMemory( pDirNode,
5542 RtlZeroMemory( pNonPagedDirEntry,
5543 sizeof( AFSNonPagedDirectoryCB));
5545 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
5547 pDirNode->NonPaged = pNonPagedDirEntry;
5549 pDirNode->ObjectInformation = pObjectInfoCB;
5551 pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_PIOCTL_INDEX;
5557 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_FAKE);
5559 pDirNode->NameInformation.FileName.Length = AFSPIOCtlName.Length;
5561 pDirNode->NameInformation.FileName.MaximumLength = AFSPIOCtlName.Length;
5563 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
5565 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
5566 AFSPIOCtlName.Buffer,
5567 pDirNode->NameInformation.FileName.Length);
5569 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
5572 ObjectInfo->Specific.Directory.PIOCtlDirectoryCB = pDirNode;
5576 if ( !NT_SUCCESS( ntStatus))
5579 if ( pDirNode != NULL)
5582 AFSExFreePool( pDirNode);
5585 if ( pObjectInfoCB != NULL)
5588 AFSDeleteObjectInfo( pObjectInfoCB);
5597 AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB,
5598 IN AFSDirectoryCB *DirectoryCB,
5599 IN UNICODE_STRING *ParentPathName,
5600 IN AFSNameArrayHdr *RelatedNameArray,
5601 OUT AFSFileInfoCB *FileInfo)
5604 NTSTATUS ntStatus = STATUS_SUCCESS;
5605 AFSDirEnumEntry *pDirEntry = NULL, *pLastDirEntry = NULL;
5606 UNICODE_STRING uniFullPathName;
5607 AFSNameArrayHdr *pNameArray = NULL;
5608 AFSVolumeCB *pVolumeCB = NULL;
5609 AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
5610 WCHAR *pwchBuffer = NULL;
5611 UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
5612 ULONG ulNameDifference = 0;
5613 GUID *pAuthGroup = NULL;
5619 // Retrieve a target name for the entry
5622 AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
5625 if( DirectoryCB->NameInformation.TargetName.Length == 0)
5628 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5630 if( ParentDirectoryCB->ObjectInformation->Fcb != NULL)
5632 pAuthGroup = &ParentDirectoryCB->ObjectInformation->Fcb->AuthGroup;
5634 else if( DirectoryCB->ObjectInformation->Fcb != NULL)
5636 pAuthGroup = &DirectoryCB->ObjectInformation->Fcb->AuthGroup;
5639 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
5644 if( !NT_SUCCESS( ntStatus) ||
5645 pDirEntry->TargetNameLength == 0)
5648 if( pDirEntry != NULL)
5651 ntStatus = STATUS_ACCESS_DENIED;
5654 try_return( ntStatus);
5657 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
5660 if( DirectoryCB->NameInformation.TargetName.Length == 0)
5664 // Update the target name
5667 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
5668 &DirectoryCB->Flags,
5669 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
5670 (USHORT)pDirEntry->TargetNameLength);
5672 if( !NT_SUCCESS( ntStatus))
5675 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5677 try_return( ntStatus);
5681 AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
5685 // Need to pass the full path in for parsing.
5688 if( AFSIsRelativeName( &DirectoryCB->NameInformation.TargetName))
5691 uniFullPathName.Length = 0;
5692 uniFullPathName.MaximumLength = ParentPathName->Length +
5694 DirectoryCB->NameInformation.TargetName.Length;
5696 uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5697 uniFullPathName.MaximumLength,
5698 AFS_NAME_BUFFER_SIX_TAG);
5700 if( uniFullPathName.Buffer == NULL)
5703 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5705 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5708 pwchBuffer = uniFullPathName.Buffer;
5710 RtlZeroMemory( uniFullPathName.Buffer,
5711 uniFullPathName.MaximumLength);
5713 RtlCopyMemory( uniFullPathName.Buffer,
5714 ParentPathName->Buffer,
5715 ParentPathName->Length);
5717 uniFullPathName.Length = ParentPathName->Length;
5719 if( uniFullPathName.Buffer[ (uniFullPathName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
5720 DirectoryCB->NameInformation.TargetName.Buffer[ 0] != L'\\')
5723 uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)] = L'\\';
5725 uniFullPathName.Length += sizeof( WCHAR);
5728 RtlCopyMemory( &uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)],
5729 DirectoryCB->NameInformation.TargetName.Buffer,
5730 DirectoryCB->NameInformation.TargetName.Length);
5732 uniFullPathName.Length += DirectoryCB->NameInformation.TargetName.Length;
5734 uniParsedName.Length = uniFullPathName.Length - ParentPathName->Length;
5735 uniParsedName.MaximumLength = uniParsedName.Length;
5737 uniParsedName.Buffer = &uniFullPathName.Buffer[ ParentPathName->Length/sizeof( WCHAR)];
5739 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5742 // We populate up to the current parent
5745 if( RelatedNameArray != NULL)
5748 pNameArray = AFSInitNameArray( NULL,
5749 RelatedNameArray->MaxElementCount);
5751 if( pNameArray == NULL)
5754 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5757 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
5764 pNameArray = AFSInitNameArray( NULL,
5767 if( pNameArray == NULL)
5770 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5773 ntStatus = AFSPopulateNameArray( pNameArray,
5778 if( !NT_SUCCESS( ntStatus))
5781 try_return( ntStatus);
5784 pVolumeCB = ParentDirectoryCB->ObjectInformation->VolumeCB;
5786 AFSAcquireShared( pVolumeCB->VolumeLock,
5789 pParentDirEntry = ParentDirectoryCB;
5794 uniFullPathName.Length = 0;
5795 uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
5797 uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5798 uniFullPathName.MaximumLength,
5799 AFS_NAME_BUFFER_SEVEN_TAG);
5801 if( uniFullPathName.Buffer == NULL)
5804 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5806 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5809 pwchBuffer = uniFullPathName.Buffer;
5811 RtlZeroMemory( uniFullPathName.Buffer,
5812 uniFullPathName.MaximumLength);
5814 RtlCopyMemory( uniFullPathName.Buffer,
5815 DirectoryCB->NameInformation.TargetName.Buffer,
5816 DirectoryCB->NameInformation.TargetName.Length);
5818 uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
5821 // This name should begin with the \afs server so parse it off and check it
5824 FsRtlDissectName( uniFullPathName,
5828 if( RtlCompareUnicodeString( &uniComponentName,
5833 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5835 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
5836 AFS_TRACE_LEVEL_ERROR,
5837 "AFSRetrieveFileAttributes Name %wZ contains invalid server name\n",
5840 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
5843 uniFullPathName = uniRemainingPath;
5845 uniParsedName = uniFullPathName;
5847 ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
5849 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5855 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
5858 if( pNameArray == NULL)
5861 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5864 pVolumeCB = AFSGlobalRoot;
5866 AFSAcquireShared( pVolumeCB->VolumeLock,
5869 pParentDirEntry = AFSGlobalRoot->DirectoryCB;
5873 // Increment the ref count on the volume and dir entry for correct processing below
5876 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
5878 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
5879 AFS_TRACE_LEVEL_VERBOSE,
5880 "AFSRetrieveFileAttributes Increment count on volume %08lX Cnt %d\n",
5882 pVolumeCB->VolumeReferenceCount);
5884 InterlockedIncrement( &pParentDirEntry->OpenReferenceCount);
5886 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5887 AFS_TRACE_LEVEL_VERBOSE,
5888 "AFSRetrieveFileAttributes Increment count on %wZ DE %p Ccb %p Cnt %d\n",
5889 &pParentDirEntry->NameInformation.FileName,
5892 pParentDirEntry->OpenReferenceCount);
5894 ntStatus = AFSLocateNameEntry( NULL,
5899 AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL,
5905 if( !NT_SUCCESS( ntStatus))
5909 // The volume lock was released on failure above
5910 // Except for STATUS_OBJECT_NAME_NOT_FOUND
5913 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
5916 if( pVolumeCB != NULL)
5919 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
5921 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
5922 AFS_TRACE_LEVEL_VERBOSE,
5923 "AFSRetrieveFileAttributes Decrement count on volume %08lX Cnt %d\n",
5925 pVolumeCB->VolumeReferenceCount);
5927 AFSReleaseResource( pVolumeCB->VolumeLock);
5930 if( pDirectoryEntry != NULL)
5933 InterlockedDecrement( &pDirectoryEntry->OpenReferenceCount);
5935 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5936 AFS_TRACE_LEVEL_VERBOSE,
5937 "AFSRetrieveFileAttributes Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
5938 &pDirectoryEntry->NameInformation.FileName,
5941 pDirectoryEntry->OpenReferenceCount);
5946 InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
5948 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5949 AFS_TRACE_LEVEL_VERBOSE,
5950 "AFSRetrieveFileAttributes Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
5951 &pParentDirEntry->NameInformation.FileName,
5954 pParentDirEntry->OpenReferenceCount);
5960 try_return( ntStatus);
5964 // Store off the information
5967 FileInfo->FileAttributes = pDirectoryEntry->ObjectInformation->FileAttributes;
5970 // Check for the mount point being returned
5973 if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT)
5976 FileInfo->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
5978 else if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK ||
5979 pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DFSLINK)
5982 if ( FileInfo->FileAttributes == FILE_ATTRIBUTE_NORMAL)
5985 FileInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
5990 FileInfo->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
5994 FileInfo->AllocationSize = pDirectoryEntry->ObjectInformation->AllocationSize;
5996 FileInfo->EndOfFile = pDirectoryEntry->ObjectInformation->EndOfFile;
5998 FileInfo->CreationTime = pDirectoryEntry->ObjectInformation->CreationTime;
6000 FileInfo->LastAccessTime = pDirectoryEntry->ObjectInformation->LastAccessTime;
6002 FileInfo->LastWriteTime = pDirectoryEntry->ObjectInformation->LastWriteTime;
6004 FileInfo->ChangeTime = pDirectoryEntry->ObjectInformation->ChangeTime;
6007 // Remove the reference made above
6010 InterlockedDecrement( &pDirectoryEntry->OpenReferenceCount);
6012 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6013 AFS_TRACE_LEVEL_VERBOSE,
6014 "AFSRetrieveFileAttributes Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
6015 &pDirectoryEntry->NameInformation.FileName,
6018 pDirectoryEntry->OpenReferenceCount);
6022 if( pDirEntry != NULL)
6025 AFSExFreePool( pDirEntry);
6028 if( pVolumeCB != NULL)
6031 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6033 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6034 AFS_TRACE_LEVEL_VERBOSE,
6035 "AFSRetrieveFileAttributes Decrement2 count on volume %08lX Cnt %d\n",
6037 pVolumeCB->VolumeReferenceCount);
6039 AFSReleaseResource( pVolumeCB->VolumeLock);
6042 if( pNameArray != NULL)
6045 AFSFreeNameArray( pNameArray);
6048 if( pwchBuffer != NULL)
6052 // Always free the buffer that we allocated as AFSLocateNameEntry
6053 // will not free it. If uniFullPathName.Buffer was allocated by
6054 // AFSLocateNameEntry, then we must free that as well.
6055 // Check that the uniFullPathName.Buffer in the string is not the same
6056 // offset by the length of the server name
6059 if( uniFullPathName.Length > 0 &&
6060 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
6063 AFSExFreePool( uniFullPathName.Buffer);
6066 AFSExFreePool( pwchBuffer);
6074 AFSAllocateObjectInfo( IN AFSObjectInfoCB *ParentObjectInfo,
6075 IN ULONGLONG HashIndex)
6078 NTSTATUS ntStatus = STATUS_SUCCESS;
6079 AFSObjectInfoCB *pObjectInfo = NULL;
6084 pObjectInfo = (AFSObjectInfoCB *)AFSExAllocatePoolWithTag( PagedPool,
6085 sizeof( AFSObjectInfoCB),
6086 AFS_OBJECT_INFO_TAG);
6088 if( pObjectInfo == NULL)
6091 try_return( pObjectInfo);
6094 RtlZeroMemory( pObjectInfo,
6095 sizeof( AFSObjectInfoCB));
6097 pObjectInfo->NonPagedInfo = (AFSNonPagedObjectInfoCB *)AFSExAllocatePoolWithTag( NonPagedPool,
6098 sizeof( AFSNonPagedObjectInfoCB),
6099 AFS_NP_OBJECT_INFO_TAG);
6101 if( pObjectInfo->NonPagedInfo == NULL)
6104 AFSExFreePool( pObjectInfo);
6106 try_return( pObjectInfo = NULL);
6109 ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6111 pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock = &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock;
6113 pObjectInfo->VolumeCB = ParentObjectInfo->VolumeCB;
6115 pObjectInfo->ParentObjectInformation = ParentObjectInfo;
6117 if( ParentObjectInfo != NULL)
6119 InterlockedIncrement( &ParentObjectInfo->ObjectReferenceCount);
6123 // Initialize the access time
6126 KeQueryTickCount( &pObjectInfo->LastAccessCount);
6132 // Insert the entry into the object tree and list
6135 pObjectInfo->TreeEntry.HashIndex = HashIndex;
6137 if( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead == NULL)
6140 ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead = &pObjectInfo->TreeEntry;
6145 ntStatus = AFSInsertHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
6146 &pObjectInfo->TreeEntry);
6148 ASSERT( NT_SUCCESS( ntStatus));
6152 // And the object list in the volume
6155 if( ParentObjectInfo->VolumeCB->ObjectInfoListHead == NULL)
6158 ParentObjectInfo->VolumeCB->ObjectInfoListHead = pObjectInfo;
6163 ParentObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = (void *)pObjectInfo;
6165 pObjectInfo->ListEntry.bLink = (void *)ParentObjectInfo->VolumeCB->ObjectInfoListTail;
6168 ParentObjectInfo->VolumeCB->ObjectInfoListTail = pObjectInfo;
6171 // Indicate the object is in the hash tree and linked list in the volume
6174 SetFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE | AFS_OBJECT_INSERTED_VOLUME_LIST);
6186 AFSDeleteObjectInfo( IN AFSObjectInfoCB *ObjectInfo)
6189 BOOLEAN bAcquiredTreeLock = FALSE;
6191 if( !ExIsResourceAcquiredExclusiveLite( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock))
6194 ASSERT( !ExIsResourceAcquiredLite( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock));
6196 AFSAcquireExcl( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
6199 bAcquiredTreeLock = TRUE;
6203 // Remove it from the tree and list if it was inserted
6206 if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
6209 AFSRemoveHashEntry( &ObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
6210 &ObjectInfo->TreeEntry);
6213 if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_INSERTED_VOLUME_LIST))
6216 if( ObjectInfo->ListEntry.fLink == NULL)
6219 ObjectInfo->VolumeCB->ObjectInfoListTail = (AFSObjectInfoCB *)ObjectInfo->ListEntry.bLink;
6221 if( ObjectInfo->VolumeCB->ObjectInfoListTail != NULL)
6224 ObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = NULL;
6230 ((AFSObjectInfoCB *)(ObjectInfo->ListEntry.fLink))->ListEntry.bLink = ObjectInfo->ListEntry.bLink;
6233 if( ObjectInfo->ListEntry.bLink == NULL)
6236 ObjectInfo->VolumeCB->ObjectInfoListHead = (AFSObjectInfoCB *)ObjectInfo->ListEntry.fLink;
6238 if( ObjectInfo->VolumeCB->ObjectInfoListHead != NULL)
6241 ObjectInfo->VolumeCB->ObjectInfoListHead->ListEntry.bLink = NULL;
6247 ((AFSObjectInfoCB *)(ObjectInfo->ListEntry.bLink))->ListEntry.fLink = ObjectInfo->ListEntry.fLink;
6251 if( ObjectInfo->ParentObjectInformation != NULL)
6253 InterlockedDecrement( &ObjectInfo->ParentObjectInformation->ObjectReferenceCount);
6256 if( bAcquiredTreeLock)
6259 AFSReleaseResource( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
6263 // Release the fid in the service
6266 if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_HELD_IN_SERVICE))
6269 AFSReleaseFid( &ObjectInfo->FileId);
6272 ExDeleteResourceLite( &ObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6274 AFSExFreePool( ObjectInfo->NonPagedInfo);
6276 AFSExFreePool( ObjectInfo);
6282 AFSEvaluateRootEntry( IN AFSDirectoryCB *DirectoryCB,
6283 OUT AFSDirectoryCB **TargetDirEntry)
6286 NTSTATUS ntStatus = STATUS_SUCCESS;
6287 AFSDirEnumEntry *pDirEntry = NULL, *pLastDirEntry = NULL;
6288 UNICODE_STRING uniFullPathName;
6289 AFSNameArrayHdr *pNameArray = NULL;
6290 AFSVolumeCB *pVolumeCB = NULL;
6291 AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
6292 WCHAR *pwchBuffer = NULL;
6293 UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
6294 ULONG ulNameDifference = 0;
6295 GUID *pAuthGroup = NULL;
6301 // Retrieve a target name for the entry
6304 AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
6307 if( DirectoryCB->NameInformation.TargetName.Length == 0)
6310 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6312 if( DirectoryCB->ObjectInformation->Fcb != NULL)
6314 pAuthGroup = &DirectoryCB->ObjectInformation->Fcb->AuthGroup;
6317 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
6322 if( !NT_SUCCESS( ntStatus) ||
6323 pDirEntry->TargetNameLength == 0)
6326 if( pDirEntry != NULL)
6329 ntStatus = STATUS_ACCESS_DENIED;
6332 try_return( ntStatus);
6335 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
6338 if( DirectoryCB->NameInformation.TargetName.Length == 0)
6342 // Update the target name
6345 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
6346 &DirectoryCB->Flags,
6347 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
6348 (USHORT)pDirEntry->TargetNameLength);
6350 if( !NT_SUCCESS( ntStatus))
6353 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6355 try_return( ntStatus);
6359 AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
6363 // Need to pass the full path in for parsing.
6366 uniFullPathName.Length = 0;
6367 uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
6369 uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6370 uniFullPathName.MaximumLength,
6371 AFS_NAME_BUFFER_EIGHT_TAG);
6373 if( uniFullPathName.Buffer == NULL)
6376 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6378 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6381 pwchBuffer = uniFullPathName.Buffer;
6383 RtlZeroMemory( uniFullPathName.Buffer,
6384 uniFullPathName.MaximumLength);
6386 RtlCopyMemory( uniFullPathName.Buffer,
6387 DirectoryCB->NameInformation.TargetName.Buffer,
6388 DirectoryCB->NameInformation.TargetName.Length);
6390 uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6393 // This name should begin with the \afs server so parse it off and chech it
6396 FsRtlDissectName( uniFullPathName,
6400 if( RtlCompareUnicodeString( &uniComponentName,
6406 // Try evaluating the full path
6409 uniFullPathName.Buffer = pwchBuffer;
6411 uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6413 uniFullPathName.MaximumLength = uniFullPathName.Length;
6418 uniFullPathName = uniRemainingPath;
6421 uniParsedName = uniFullPathName;
6423 ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
6425 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6431 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
6434 if( pNameArray == NULL)
6437 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6440 pVolumeCB = AFSGlobalRoot;
6442 AFSAcquireShared( pVolumeCB->VolumeLock,
6445 pParentDirEntry = AFSGlobalRoot->DirectoryCB;
6447 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
6449 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6450 AFS_TRACE_LEVEL_VERBOSE,
6451 "AFSEvaluateRootEntry Increment count on volume %08lX Cnt %d\n",
6453 pVolumeCB->VolumeReferenceCount);
6455 InterlockedIncrement( &pParentDirEntry->OpenReferenceCount);
6457 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6458 AFS_TRACE_LEVEL_VERBOSE,
6459 "AFSEvaluateRootEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
6460 &pParentDirEntry->NameInformation.FileName,
6463 pParentDirEntry->OpenReferenceCount);
6465 ntStatus = AFSLocateNameEntry( NULL,
6476 if( !NT_SUCCESS( ntStatus))
6480 // The volume lock was released on failure above
6481 // Except for STATUS_OBJECT_NAME_NOT_FOUND
6484 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
6487 if( pVolumeCB != NULL)
6490 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6492 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6493 AFS_TRACE_LEVEL_VERBOSE,
6494 "AFSEvaluateRootEntry Decrement count on volume %08lX Cnt %d\n",
6496 pVolumeCB->VolumeReferenceCount);
6498 AFSReleaseResource( pVolumeCB->VolumeLock);
6501 if( pDirectoryEntry != NULL)
6504 InterlockedDecrement( &pDirectoryEntry->OpenReferenceCount);
6506 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6507 AFS_TRACE_LEVEL_VERBOSE,
6508 "AFSEvaluateRootEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6509 &pDirectoryEntry->NameInformation.FileName,
6512 pDirectoryEntry->OpenReferenceCount);
6517 InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
6519 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6520 AFS_TRACE_LEVEL_VERBOSE,
6521 "AFSEvaluateRootEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6522 &pParentDirEntry->NameInformation.FileName,
6525 pParentDirEntry->OpenReferenceCount);
6531 try_return( ntStatus);
6535 // Pass back the target dir entry for this request
6538 *TargetDirEntry = pDirectoryEntry;
6542 if( pDirEntry != NULL)
6545 AFSExFreePool( pDirEntry);
6548 if( pVolumeCB != NULL)
6551 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6553 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6554 AFS_TRACE_LEVEL_VERBOSE,
6555 "AFSEvaluateRootEntry2 Decrement count on volume %08lX Cnt %d\n",
6557 pVolumeCB->VolumeReferenceCount);
6559 AFSReleaseResource( pVolumeCB->VolumeLock);
6562 if( pNameArray != NULL)
6565 AFSFreeNameArray( pNameArray);
6568 if( pwchBuffer != NULL)
6572 // Always free the buffer that we allocated as AFSLocateNameEntry
6573 // will not free it. If uniFullPathName.Buffer was allocated by
6574 // AFSLocateNameEntry, then we must free that as well.
6575 // Check that the uniFullPathName.Buffer in the string is not the same
6576 // offset by the length of the server name
6579 if( uniFullPathName.Length > 0 &&
6580 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
6583 AFSExFreePool( uniFullPathName.Buffer);
6586 AFSExFreePool( pwchBuffer);
6594 AFSCleanupFcb( IN AFSFcb *Fcb,
6595 IN BOOLEAN ForceFlush)
6598 NTSTATUS ntStatus = STATUS_SUCCESS;
6599 AFSDeviceExt *pRDRDeviceExt = NULL, *pControlDeviceExt = NULL;
6600 LARGE_INTEGER liTime;
6601 IO_STATUS_BLOCK stIoStatus;
6606 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
6608 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
6610 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
6613 if( !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) &&
6614 !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
6617 AFSAcquireExcl( &Fcb->NPFcb->Resource,
6620 if( Fcb->OpenReferenceCount > 0)
6626 CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
6631 if( !NT_SUCCESS( stIoStatus.Status))
6634 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
6635 AFS_TRACE_LEVEL_ERROR,
6636 "AFSCleanupFcb CcFlushCache [1] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
6637 Fcb->ObjectInformation->FileId.Cell,
6638 Fcb->ObjectInformation->FileId.Volume,
6639 Fcb->ObjectInformation->FileId.Vnode,
6640 Fcb->ObjectInformation->FileId.Unique,
6642 stIoStatus.Information);
6644 ntStatus = stIoStatus.Status;
6647 CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
6652 __except( EXCEPTION_EXECUTE_HANDLER)
6654 ntStatus = GetExceptionCode();
6658 AFSReleaseResource( &Fcb->NPFcb->Resource);
6661 // Wait for any currently running flush or release requests to complete
6664 AFSWaitOnQueuedFlushes( Fcb);
6667 // Now perform another flush on the file
6670 if( !NT_SUCCESS( AFSFlushExtents( Fcb)))
6673 AFSReleaseExtentsWithFlush( Fcb);
6677 if( Fcb->OpenReferenceCount == 0 ||
6678 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
6679 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
6682 AFSTearDownFcbExtents( Fcb);
6685 try_return( ntStatus);
6688 KeQueryTickCount( &liTime);
6691 // First up are there dirty extents in the cache to flush?
6695 ( !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) &&
6696 !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
6697 ( Fcb->Specific.File.ExtentsDirtyCount ||
6698 Fcb->Specific.File.ExtentCount) &&
6699 (liTime.QuadPart - Fcb->Specific.File.LastServerFlush.QuadPart)
6700 >= pControlDeviceExt->Specific.Control.FcbFlushTimeCount.QuadPart))
6703 if( !NT_SUCCESS( AFSFlushExtents( Fcb)) &&
6704 Fcb->OpenReferenceCount == 0)
6707 AFSReleaseExtentsWithFlush( Fcb);
6710 else if( BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
6711 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
6715 // The file has been marked as invalid. Dump it
6718 AFSTearDownFcbExtents( Fcb);
6722 // If there are extents and they haven't been used recently *and*
6723 // are not being used
6727 ( 0 != Fcb->Specific.File.ExtentCount &&
6728 0 != Fcb->Specific.File.LastExtentAccess.QuadPart &&
6729 (liTime.QuadPart - Fcb->Specific.File.LastExtentAccess.QuadPart) >=
6730 (AFS_SERVER_PURGE_SLEEP * pControlDeviceExt->Specific.Control.FcbPurgeTimeCount.QuadPart))) &&
6731 AFSAcquireExcl( &Fcb->NPFcb->Resource,
6738 CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
6743 if( !NT_SUCCESS( stIoStatus.Status))
6746 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
6747 AFS_TRACE_LEVEL_ERROR,
6748 "AFSCleanupFcb CcFlushCache [2] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
6749 Fcb->ObjectInformation->FileId.Cell,
6750 Fcb->ObjectInformation->FileId.Volume,
6751 Fcb->ObjectInformation->FileId.Vnode,
6752 Fcb->ObjectInformation->FileId.Unique,
6754 stIoStatus.Information);
6756 ntStatus = stIoStatus.Status;
6762 CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
6768 __except( EXCEPTION_EXECUTE_HANDLER)
6770 ntStatus = GetExceptionCode();
6773 AFSReleaseResource( &Fcb->NPFcb->Resource);
6775 if( Fcb->OpenReferenceCount == 0)
6779 // Tear em down we'll not be needing them again
6782 AFSTearDownFcbExtents( Fcb);
6795 AFSUpdateDirEntryName( IN AFSDirectoryCB *DirectoryCB,
6796 IN UNICODE_STRING *NewFileName)
6799 NTSTATUS ntStatus = STATUS_SUCCESS;
6800 WCHAR *pTmpBuffer = NULL;
6805 if( NewFileName->Length > DirectoryCB->NameInformation.FileName.Length)
6808 if( BooleanFlagOn( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
6811 AFSExFreePool( DirectoryCB->NameInformation.FileName.Buffer);
6813 ClearFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
6815 DirectoryCB->NameInformation.FileName.Buffer = NULL;
6819 // OK, we need to allocate a new name buffer
6822 pTmpBuffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6823 NewFileName->Length,
6824 AFS_NAME_BUFFER_NINE_TAG);
6826 if( pTmpBuffer == NULL)
6829 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6832 DirectoryCB->NameInformation.FileName.Buffer = pTmpBuffer;
6834 DirectoryCB->NameInformation.FileName.MaximumLength = NewFileName->Length;
6836 SetFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
6839 DirectoryCB->NameInformation.FileName.Length = NewFileName->Length;
6841 RtlCopyMemory( DirectoryCB->NameInformation.FileName.Buffer,
6842 NewFileName->Buffer,
6843 NewFileName->Length);
6854 AFSReadCacheFile( IN void *ReadBuffer,
6855 IN LARGE_INTEGER *ReadOffset,
6856 IN ULONG RequestedDataLength,
6857 IN OUT PULONG BytesRead)
6860 NTSTATUS ntStatus = STATUS_SUCCESS;
6863 PIO_STACK_LOCATION pIoStackLocation = NULL;
6864 AFSDeviceExt *pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
6865 DEVICE_OBJECT *pTargetDeviceObject = NULL;
6866 FILE_OBJECT *pCacheFileObject = NULL;
6871 pCacheFileObject = AFSReferenceCacheFileObject();
6873 if( pCacheFileObject == NULL)
6875 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
6878 pTargetDeviceObject = IoGetRelatedDeviceObject( pCacheFileObject);
6881 // Initialize the event
6884 KeInitializeEvent( &kEvent,
6885 SynchronizationEvent,
6889 // Allocate an irp for this request. This could also come from a
6890 // private pool, for instance.
6893 pIrp = IoAllocateIrp( pTargetDeviceObject->StackSize,
6899 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6903 // Build the IRP's main body
6906 pIrp->UserBuffer = ReadBuffer;
6908 pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
6909 pIrp->RequestorMode = KernelMode;
6910 pIrp->Flags |= IRP_READ_OPERATION;
6913 // Set up the I/O stack location.
6916 pIoStackLocation = IoGetNextIrpStackLocation( pIrp);
6917 pIoStackLocation->MajorFunction = IRP_MJ_READ;
6918 pIoStackLocation->DeviceObject = pTargetDeviceObject;
6919 pIoStackLocation->FileObject = pCacheFileObject;
6920 pIoStackLocation->Parameters.Read.Length = RequestedDataLength;
6922 pIoStackLocation->Parameters.Read.ByteOffset.QuadPart = ReadOffset->QuadPart;
6925 // Set the completion routine.
6928 IoSetCompletionRoutine( pIrp,
6936 // Send it to the FSD
6939 ntStatus = IoCallDriver( pTargetDeviceObject,
6942 if( NT_SUCCESS( ntStatus))
6949 ntStatus = KeWaitForSingleObject( &kEvent,
6955 if( NT_SUCCESS( ntStatus))
6958 ntStatus = pIrp->IoStatus.Status;
6960 *BytesRead = (ULONG)pIrp->IoStatus.Information;
6966 if( pCacheFileObject != NULL)
6968 AFSReleaseCacheFileObject( pCacheFileObject);
6974 if( pIrp->MdlAddress != NULL)
6977 if( FlagOn( pIrp->MdlAddress->MdlFlags, MDL_PAGES_LOCKED))
6980 MmUnlockPages( pIrp->MdlAddress);
6983 IoFreeMdl( pIrp->MdlAddress);
6986 pIrp->MdlAddress = NULL;
7000 AFSIrpComplete( IN PDEVICE_OBJECT DeviceObject,
7005 KEVENT *pEvent = (KEVENT *)Context;
7011 return STATUS_MORE_PROCESSING_REQUIRED;
7015 AFSIsDirectoryEmptyForDelete( IN AFSFcb *Fcb)
7018 BOOLEAN bIsEmpty = FALSE;
7019 AFSDirectoryCB *pDirEntry = NULL;
7024 AFSAcquireShared( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
7029 if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
7032 pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
7034 while( pDirEntry != NULL)
7037 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
7038 !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
7046 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
7051 AFSReleaseResource( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
7058 AFSRemoveNameEntry( IN AFSObjectInfoCB *ParentObjectInfo,
7059 IN AFSDirectoryCB *DirEntry)
7062 NTSTATUS ntStatus = STATUS_SUCCESS;
7067 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7070 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7071 AFS_TRACE_LEVEL_VERBOSE,
7072 "AFSRemoveNameEntry DE %p for %wZ has NOT_IN flag set\n",
7074 &DirEntry->NameInformation.FileName);
7076 try_return( ntStatus);
7079 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
7082 // Remove the entry from the parent tree
7085 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7086 AFS_TRACE_LEVEL_VERBOSE,
7087 "AFSRemoveNameEntry DE %p for %wZ removing from case sensitive tree\n",
7089 &DirEntry->NameInformation.FileName);
7091 AFSRemoveCaseSensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7094 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7095 AFS_TRACE_LEVEL_VERBOSE,
7096 "AFSRemoveNameEntry DE %p for %wZ removing from case insensitive tree\n",
7098 &DirEntry->NameInformation.FileName);
7100 AFSRemoveCaseInsensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
7103 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
7107 // From the short name tree
7110 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7111 AFS_TRACE_LEVEL_VERBOSE,
7112 "AFSRemoveNameEntry DE %p for %wZ removing from shortname tree\n",
7114 &DirEntry->NameInformation.FileName);
7116 AFSRemoveShortNameDirEntry( &ParentObjectInfo->Specific.Directory.ShortNameTree,
7119 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
7122 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7123 AFS_TRACE_LEVEL_VERBOSE,
7124 "AFSRemoveNameEntry DE %p for %wZ setting NOT_IN flag\n",
7126 &DirEntry->NameInformation.FileName);
7128 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
7130 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
7141 AFSGetAuthenticationId()
7144 LARGE_INTEGER liAuthId = {0,0};
7145 NTSTATUS ntStatus = STATUS_SUCCESS;
7146 PACCESS_TOKEN hToken = NULL;
7147 PTOKEN_STATISTICS pTokenInfo = NULL;
7148 BOOLEAN bCopyOnOpen = FALSE;
7149 BOOLEAN bEffectiveOnly = FALSE;
7150 BOOLEAN bPrimaryToken = FALSE;
7151 SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
7156 hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
7159 &stImpersonationLevel);
7164 hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
7169 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7170 AFS_TRACE_LEVEL_ERROR,
7171 "AFSGetAuthenticationId Failed to retrieve impersonation or primary token\n");
7173 try_return( ntStatus);
7176 bPrimaryToken = TRUE;
7179 ntStatus = SeQueryInformationToken( hToken,
7181 (PVOID *)&pTokenInfo);
7183 if( !NT_SUCCESS( ntStatus))
7186 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7187 AFS_TRACE_LEVEL_ERROR,
7188 "AFSGetAuthenticationId Failed to retrieve information Status %08lX\n", ntStatus);
7190 try_return( ntStatus);
7193 liAuthId.HighPart = pTokenInfo->AuthenticationId.HighPart;
7194 liAuthId.LowPart = pTokenInfo->AuthenticationId.LowPart;
7196 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7197 AFS_TRACE_LEVEL_VERBOSE,
7198 "AFSGetAuthenticationId Successfully retrieved authentication ID %I64X\n",
7209 PsDereferenceImpersonationToken( hToken);
7214 PsDereferencePrimaryToken( hToken);
7218 if( pTokenInfo != NULL)
7221 AFSExFreePool( pTokenInfo);
7229 AFSUnwindFileInfo( IN AFSFcb *Fcb,
7233 if( Ccb->FileUnwindInfo.FileAttributes != (ULONG)-1)
7235 Ccb->DirectoryCB->ObjectInformation->FileAttributes = Ccb->FileUnwindInfo.FileAttributes;
7238 if( Ccb->FileUnwindInfo.CreationTime.QuadPart != (ULONGLONG)-1)
7240 Ccb->DirectoryCB->ObjectInformation->CreationTime.QuadPart = Ccb->FileUnwindInfo.CreationTime.QuadPart;
7243 if( Ccb->FileUnwindInfo.LastAccessTime.QuadPart != (ULONGLONG)-1)
7245 Ccb->DirectoryCB->ObjectInformation->LastAccessTime.QuadPart = Ccb->FileUnwindInfo.LastAccessTime.QuadPart;
7248 if( Ccb->FileUnwindInfo.LastWriteTime.QuadPart != (ULONGLONG)-1)
7250 Ccb->DirectoryCB->ObjectInformation->LastWriteTime.QuadPart = Ccb->FileUnwindInfo.LastWriteTime.QuadPart;
7253 if( Ccb->FileUnwindInfo.ChangeTime.QuadPart != (ULONGLONG)-1)
7255 Ccb->DirectoryCB->ObjectInformation->ChangeTime.QuadPart = Ccb->FileUnwindInfo.ChangeTime.QuadPart;
7262 AFSValidateDirList( IN AFSObjectInfoCB *ObjectInfo)
7265 BOOLEAN bIsValid = TRUE;
7267 AFSDirectoryCB *pCurrentDirEntry = NULL, *pDirEntry = NULL;
7269 pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
7271 while( pCurrentDirEntry != NULL)
7274 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
7278 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7283 AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7284 (ULONG)pCurrentDirEntry->CaseSensitiveTreeEntry.HashIndex,
7287 if( pDirEntry == NULL)
7294 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
7297 if( ulCount != ObjectInfo->Specific.Directory.DirectoryNodeCount)
7300 AFSPrint("AFSValidateDirList Count off Calc: %d Stored: %d\n",
7302 ObjectInfo->Specific.Directory.DirectoryNodeCount);
7304 ObjectInfo->Specific.Directory.DirectoryNodeCount = ulCount;
7313 AFSReferenceCacheFileObject()
7316 AFSDeviceExt *pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
7317 FILE_OBJECT *pCacheFileObject = NULL;
7319 AFSAcquireShared( &pRdrDevExt->Specific.RDR.CacheFileLock,
7322 pCacheFileObject = pRdrDevExt->Specific.RDR.CacheFileObject;
7324 if( pCacheFileObject != NULL)
7326 ObReferenceObject( pCacheFileObject);
7329 AFSReleaseResource( &pRdrDevExt->Specific.RDR.CacheFileLock);
7331 return pCacheFileObject;
7335 AFSReleaseCacheFileObject( IN PFILE_OBJECT CacheFileObject)
7338 ASSERT( CacheFileObject != NULL);
7340 ObDereferenceObject( CacheFileObject);
7346 AFSInitializeLibrary( IN AFSLibraryInitCB *LibraryInit)
7349 NTSTATUS ntStatus = STATUS_SUCCESS;
7350 AFSDeviceExt *pControlDevExt = NULL;
7351 ULONG ulTimeIncrement = 0;
7356 AFSControlDeviceObject = LibraryInit->AFSControlDeviceObject;
7358 AFSRDRDeviceObject = LibraryInit->AFSRDRDeviceObject;
7360 AFSServerName = LibraryInit->AFSServerName;
7362 AFSDebugFlags = LibraryInit->AFSDebugFlags;
7365 // Callbacks in the framework
7368 AFSProcessRequest = LibraryInit->AFSProcessRequest;
7370 AFSDbgLogMsg = LibraryInit->AFSDbgLogMsg;
7372 AFSAddConnectionEx = LibraryInit->AFSAddConnectionEx;
7374 AFSExAllocatePoolWithTag = LibraryInit->AFSExAllocatePoolWithTag;
7376 AFSExFreePool = LibraryInit->AFSExFreePool;
7378 AFSDumpTraceFilesFnc = LibraryInit->AFSDumpTraceFiles;
7380 AFSRetrieveAuthGroupFnc = LibraryInit->AFSRetrieveAuthGroup;
7382 AFSLibCacheManagerCallbacks = LibraryInit->AFSCacheManagerCallbacks;
7384 if( LibraryInit->AFSCacheBaseAddress != NULL)
7387 SetFlag( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE);
7389 AFSLibCacheBaseAddress = LibraryInit->AFSCacheBaseAddress;
7391 AFSLibCacheLength = LibraryInit->AFSCacheLength;
7395 // Initialize some flush parameters
7398 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
7400 ulTimeIncrement = KeQueryTimeIncrement();
7402 pControlDevExt->Specific.Control.ObjectLifeTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_OBJECT_LIFETIME / (ULONGLONG)ulTimeIncrement);
7403 pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart = AFS_ONE_SECOND;
7404 pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart *= AFS_SERVER_PURGE_DELAY;
7405 pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart /= ulTimeIncrement;
7406 pControlDevExt->Specific.Control.FcbFlushTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)(AFS_ONE_SECOND * AFS_SERVER_FLUSH_DELAY) / (ULONGLONG)ulTimeIncrement);
7407 pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_EXTENT_REQUEST_TIME/(ULONGLONG)ulTimeIncrement);
7410 // Initialize the global root entry
7413 ntStatus = AFSInitVolume( NULL,
7414 &LibraryInit->GlobalRootFid,
7417 if( !NT_SUCCESS( ntStatus))
7420 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
7421 AFS_TRACE_LEVEL_ERROR,
7422 "AFSInitializeLibrary AFSInitVolume failure %08lX\n",
7425 try_return( ntStatus);
7428 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
7431 if( !NT_SUCCESS( ntStatus))
7434 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
7435 AFS_TRACE_LEVEL_ERROR,
7436 "AFSInitializeLibrary AFSInitRootFcb failure %08lX\n",
7439 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
7441 try_return( ntStatus);
7445 // Update the node type code to AFS_ROOT_ALL
7448 AFSGlobalRoot->ObjectInformation.Fcb->Header.NodeTypeCode = AFS_ROOT_ALL;
7450 SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_ACTIVE_GLOBAL_ROOT);
7453 // Drop the locks acquired above
7456 AFSInitVolumeWorker( AFSGlobalRoot);
7458 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
7460 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Fcb->Header.Resource);
7474 NTSTATUS ntStatus = STATUS_SUCCESS;
7475 AFSDirectoryCB *pDirNode = NULL, *pLastDirNode = NULL;
7480 if( AFSGlobalDotDirEntry != NULL)
7483 AFSDeleteObjectInfo( AFSGlobalDotDirEntry->ObjectInformation);
7485 ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
7487 ExFreePool( AFSGlobalDotDirEntry->NonPaged);
7489 ExFreePool( AFSGlobalDotDirEntry);
7491 AFSGlobalDotDirEntry = NULL;
7494 if( AFSGlobalDotDotDirEntry != NULL)
7497 AFSDeleteObjectInfo( AFSGlobalDotDotDirEntry->ObjectInformation);
7499 ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
7501 ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
7503 ExFreePool( AFSGlobalDotDotDirEntry);
7505 AFSGlobalDotDotDirEntry = NULL;
7508 if( AFSSpecialShareNames != NULL)
7511 pDirNode = AFSSpecialShareNames;
7513 while( pDirNode != NULL)
7516 pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
7518 AFSDeleteObjectInfo( pDirNode->ObjectInformation);
7520 ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
7522 ExFreePool( pDirNode->NonPaged);
7524 ExFreePool( pDirNode);
7526 pDirNode = pLastDirNode;
7529 AFSSpecialShareNames = NULL;
7537 AFSDefaultLogMsg( IN ULONG Subsystem,
7543 NTSTATUS ntStatus = STATUS_SUCCESS;
7545 char chDebugBuffer[ 256];
7550 va_start( va_args, Format);
7552 ntStatus = RtlStringCbVPrintfA( chDebugBuffer,
7557 if( NT_SUCCESS( ntStatus))
7559 DbgPrint( chDebugBuffer);
7569 AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
7570 IN ULONG InputBufferLength,
7571 IN AFSStatusInfoCB *StatusInfo,
7572 OUT ULONG *ReturnLength)
7575 NTSTATUS ntStatus = STATUS_SUCCESS;
7576 AFSFcb *pFcb = NULL;
7577 AFSVolumeCB *pVolumeCB = NULL;
7578 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
7579 AFSObjectInfoCB *pObjectInfo = NULL;
7580 ULONGLONG ullIndex = 0;
7581 UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName, uniParsedName;
7582 AFSNameArrayHdr *pNameArray = NULL;
7583 AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
7589 // If we are given a FID then look up the entry by that, otherwise
7593 if( GetStatusInfo->FileID.Cell != 0 &&
7594 GetStatusInfo->FileID.Volume != 0 &&
7595 GetStatusInfo->FileID.Vnode != 0 &&
7596 GetStatusInfo->FileID.Unique != 0)
7599 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
7602 // Locate the volume node
7605 ullIndex = AFSCreateHighIndex( &GetStatusInfo->FileID);
7607 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
7609 (AFSBTreeEntry **)&pVolumeCB);
7611 if( pVolumeCB != NULL)
7614 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
7616 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7617 AFS_TRACE_LEVEL_VERBOSE,
7618 "AFSGetObjectStatus Increment count on volume %08lX Cnt %d\n",
7620 pVolumeCB->VolumeReferenceCount);
7623 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
7625 if( !NT_SUCCESS( ntStatus) ||
7628 try_return( ntStatus = STATUS_INVALID_PARAMETER);
7631 if( AFSIsVolumeFID( &GetStatusInfo->FileID))
7634 pObjectInfo = &pVolumeCB->ObjectInformation;
7636 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
7638 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
7643 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
7646 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
7648 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7649 AFS_TRACE_LEVEL_VERBOSE,
7650 "AFSGetObjectStatus Decrement count on volume %08lX Cnt %d\n",
7652 pVolumeCB->VolumeReferenceCount);
7654 ullIndex = AFSCreateLowIndex( &GetStatusInfo->FileID);
7656 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
7658 (AFSBTreeEntry **)&pObjectInfo);
7660 if( pObjectInfo != NULL)
7664 // Reference the node so it won't be torn down
7667 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
7669 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
7670 AFS_TRACE_LEVEL_VERBOSE,
7671 "AFSGetObjectStatus Increment count on object %08lX Cnt %d\n",
7673 pObjectInfo->ObjectReferenceCount);
7676 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
7678 if( !NT_SUCCESS( ntStatus) ||
7679 pObjectInfo == NULL)
7681 try_return( ntStatus = STATUS_INVALID_PARAMETER);
7688 if( GetStatusInfo->FileNameLength == 0 ||
7689 InputBufferLength < (ULONG)(FIELD_OFFSET( AFSGetStatusInfoCB, FileName) + GetStatusInfo->FileNameLength))
7691 try_return( ntStatus = STATUS_INVALID_PARAMETER);
7694 uniFullPathName.Length = GetStatusInfo->FileNameLength;
7695 uniFullPathName.MaximumLength = uniFullPathName.Length;
7697 uniFullPathName.Buffer = (WCHAR *)GetStatusInfo->FileName;
7700 // This name should begin with the \afs server so parse it off and check it
7703 FsRtlDissectName( uniFullPathName,
7707 if( RtlCompareUnicodeString( &uniComponentName,
7711 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7712 AFS_TRACE_LEVEL_ERROR,
7713 "AFSGetObjectStatus Name %wZ contains invalid server name\n",
7716 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
7719 uniFullPathName = uniRemainingPath;
7721 uniParsedName = uniFullPathName;
7727 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
7730 if( pNameArray == NULL)
7732 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7735 pVolumeCB = AFSGlobalRoot;
7737 AFSAcquireShared( pVolumeCB->VolumeLock,
7740 pParentDirEntry = AFSGlobalRoot->DirectoryCB;
7743 // Increment the ref count on the volume and dir entry for correct processing below
7746 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
7748 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7749 AFS_TRACE_LEVEL_VERBOSE,
7750 "AFSGetObjectStatus Increment count on volume %08lX Cnt %d\n",
7752 pVolumeCB->VolumeReferenceCount);
7754 InterlockedIncrement( &pParentDirEntry->OpenReferenceCount);
7756 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
7757 AFS_TRACE_LEVEL_VERBOSE,
7758 "AFSGetObjectStatus Increment count on %wZ DE %p Ccb %p Cnt %d\n",
7759 &pParentDirEntry->NameInformation.FileName,
7762 pParentDirEntry->OpenReferenceCount);
7764 ntStatus = AFSLocateNameEntry( NULL,
7769 AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL |
7770 AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL,
7776 if( !NT_SUCCESS( ntStatus))
7780 // The volume lock was released on failure above
7781 // Except for STATUS_OBJECT_NAME_NOT_FOUND
7784 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
7787 if( pVolumeCB != NULL)
7790 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
7792 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7793 AFS_TRACE_LEVEL_VERBOSE,
7794 "AFSGetObjectStatus Decrement count on volume %08lX Cnt %d\n",
7796 pVolumeCB->VolumeReferenceCount);
7798 AFSReleaseResource( pVolumeCB->VolumeLock);
7801 if( pDirectoryEntry != NULL)
7804 InterlockedDecrement( &pDirectoryEntry->OpenReferenceCount);
7806 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
7807 AFS_TRACE_LEVEL_VERBOSE,
7808 "AFSGetObjectStatus Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
7809 &pDirectoryEntry->NameInformation.FileName,
7812 pDirectoryEntry->OpenReferenceCount);
7817 InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
7819 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
7820 AFS_TRACE_LEVEL_VERBOSE,
7821 "AFSGetObjectStatus Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
7822 &pParentDirEntry->NameInformation.FileName,
7825 pParentDirEntry->OpenReferenceCount);
7831 try_return( ntStatus);
7835 // Remove the reference made above
7838 InterlockedDecrement( &pDirectoryEntry->OpenReferenceCount);
7840 pObjectInfo = pDirectoryEntry->ObjectInformation;
7842 InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
7844 if( pVolumeCB != NULL)
7847 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
7849 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7850 AFS_TRACE_LEVEL_VERBOSE,
7851 "AFSRetrieveFileAttributes Decrement2 count on volume %08lX Cnt %d\n",
7853 pVolumeCB->VolumeReferenceCount);
7855 AFSReleaseResource( pVolumeCB->VolumeLock);
7860 // At this point we have an object info block, return the information
7863 StatusInfo->FileId = pObjectInfo->FileId;
7865 StatusInfo->TargetFileId = pObjectInfo->TargetFileId;
7867 StatusInfo->Expiration = pObjectInfo->Expiration;
7869 StatusInfo->DataVersion = pObjectInfo->DataVersion;
7871 StatusInfo->FileType = pObjectInfo->FileType;
7873 StatusInfo->ObjectFlags = pObjectInfo->Flags;
7875 StatusInfo->CreationTime = pObjectInfo->CreationTime;
7877 StatusInfo->LastAccessTime = pObjectInfo->LastAccessTime;
7879 StatusInfo->LastWriteTime = pObjectInfo->LastWriteTime;
7881 StatusInfo->ChangeTime = pObjectInfo->ChangeTime;
7883 StatusInfo->FileAttributes = pObjectInfo->FileAttributes;
7885 StatusInfo->EndOfFile = pObjectInfo->EndOfFile;
7887 StatusInfo->AllocationSize = pObjectInfo->AllocationSize;
7889 StatusInfo->EaSize = pObjectInfo->EaSize;
7891 StatusInfo->Links = pObjectInfo->Links;
7894 // Return the information length
7897 *ReturnLength = sizeof( AFSStatusInfoCB);
7901 if( pObjectInfo != NULL)
7904 InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
7907 if( pNameArray != NULL)
7910 AFSFreeNameArray( pNameArray);
7918 AFSCheckSymlinkAccess( IN AFSDirectoryCB *ParentDirectoryCB,
7919 IN UNICODE_STRING *ComponentName)
7922 NTSTATUS ntStatus = STATUS_SUCCESS;
7923 AFSDirectoryCB *pDirEntry = NULL;
7930 // Search for the entry in the parent
7933 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7934 AFS_TRACE_LEVEL_VERBOSE_2,
7935 "AFSCheckSymlinkAccess Searching for entry %wZ case sensitive\n",
7938 ulCRC = AFSGenerateCRC( ComponentName,
7941 AFSAcquireShared( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
7944 AFSLocateCaseSensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7948 if( pDirEntry == NULL)
7952 // Missed so perform a case insensitive lookup
7955 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7956 AFS_TRACE_LEVEL_VERBOSE_2,
7957 "AFSCheckSymlinkAccess Searching for entry %wZ case insensitive\n",
7960 ulCRC = AFSGenerateCRC( ComponentName,
7963 AFSLocateCaseInsensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
7967 if( pDirEntry == NULL)
7971 // OK, if this component is a valid short name then try
7972 // a lookup in the short name tree
7975 if( RtlIsNameLegalDOS8Dot3( ComponentName,
7980 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7981 AFS_TRACE_LEVEL_VERBOSE_2,
7982 "AFSCheckSymlinkAccess Searching for entry %wZ short name\n",
7985 AFSLocateShortNameDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.ShortNameTree,
7992 if( pDirEntry != NULL)
7994 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
7997 AFSReleaseResource( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
7999 if( pDirEntry == NULL)
8002 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8003 AFS_TRACE_LEVEL_VERBOSE_2,
8004 "AFSCheckSymlinkAccess Failed to locate entry %wZ\n",
8007 try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
8011 // We have the symlink object but previously failed to process it so return access
8015 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8016 AFS_TRACE_LEVEL_VERBOSE_2,
8017 "AFSCheckSymlinkAccess Failing symlink access to entry %wZ ACCESS_DENIED\n",
8020 ntStatus = STATUS_ACCESS_DENIED;
8022 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
8033 AFSRetrieveFinalComponent( IN UNICODE_STRING *FullPathName,
8034 OUT UNICODE_STRING *ComponentName)
8037 NTSTATUS ntStatus = STATUS_SUCCESS;
8038 UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName;
8040 uniFullPathName = *FullPathName;
8045 FsRtlDissectName( uniFullPathName,
8049 if( uniRemainingPath.Length == 0)
8054 uniFullPathName = uniRemainingPath;
8057 if( uniComponentName.Length > 0)
8059 *ComponentName = uniComponentName;
8066 AFSDumpTraceFiles_Default()
8072 AFSValidNameFormat( IN UNICODE_STRING *FileName)
8075 BOOLEAN bIsValidName = TRUE;
8081 while( usIndex < FileName->Length/sizeof( WCHAR))
8084 if( FileName->Buffer[ usIndex] == L':' ||
8085 FileName->Buffer[ usIndex] == L'*' ||
8086 FileName->Buffer[ usIndex] == L'?' ||
8087 FileName->Buffer[ usIndex] == L'"' ||
8088 FileName->Buffer[ usIndex] == L'<' ||
8089 FileName->Buffer[ usIndex] == L'>')
8091 bIsValidName = FALSE;
8099 return bIsValidName;
8103 AFSCreateDefaultSecurityDescriptor()
8106 NTSTATUS ntStatus = STATUS_SUCCESS;
8108 ULONG ulSACLSize = 0;
8109 SYSTEM_MANDATORY_LABEL_ACE* pACE = NULL;
8110 ULONG ulACESize = 0;
8111 SECURITY_DESCRIPTOR *pSecurityDescr = NULL;
8112 ULONG ulSDLength = 0;
8113 SECURITY_DESCRIPTOR *pRelativeSecurityDescr = NULL;
8114 PSID pWorldSID = NULL;
8115 ULONG *pulSubAuthority = NULL;
8116 ULONG ulWorldSIDLEngth = 0;
8121 ulWorldSIDLEngth = RtlLengthRequiredSid( 1);
8123 pWorldSID = (PSID)ExAllocatePoolWithTag( PagedPool,
8125 AFS_GENERIC_MEMORY_29_TAG);
8127 if( pWorldSID == NULL)
8129 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate World SID\n");
8130 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8133 RtlZeroMemory( pWorldSID,
8136 RtlInitializeSid( pWorldSID,
8137 &SeWorldSidAuthority,
8140 pulSubAuthority = RtlSubAuthoritySid(pWorldSID, 0);
8141 *pulSubAuthority = SECURITY_WORLD_RID;
8143 if( AFSRtlSetSaclSecurityDescriptor == NULL)
8146 AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor == NULL\n");
8151 ulACESize = sizeof( SYSTEM_MANDATORY_LABEL_ACE) + 128;
8153 pACE = (SYSTEM_MANDATORY_LABEL_ACE *)ExAllocatePoolWithTag( PagedPool,
8155 AFS_GENERIC_MEMORY_29_TAG);
8160 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8162 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8165 RtlZeroMemory( pACE,
8168 pACE->Header.AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
8169 pACE->Header.AceType = SYSTEM_MANDATORY_LABEL_ACE_TYPE;
8170 pACE->Header.AceSize = FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + (USHORT)RtlLengthSid( SeExports->SeLowMandatorySid);
8171 pACE->Mask = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP;
8173 RtlCopySid( RtlLengthSid( SeExports->SeLowMandatorySid),
8175 SeExports->SeLowMandatorySid);
8177 ulSACLSize = sizeof(ACL) + RtlLengthSid( SeExports->SeLowMandatorySid) +
8178 FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + ulACESize;
8180 pSACL = (PACL)ExAllocatePoolWithTag( PagedPool,
8182 AFS_GENERIC_MEMORY_29_TAG);
8187 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8189 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8192 ntStatus = RtlCreateAcl( pSACL,
8196 if( !NT_SUCCESS( ntStatus))
8199 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateAcl ntStatus %08lX\n",
8202 try_return( ntStatus);
8205 ntStatus = RtlAddAce( pSACL,
8209 pACE->Header.AceSize);
8211 if( !NT_SUCCESS( ntStatus))
8214 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAddAce ntStatus %08lX\n",
8217 try_return( ntStatus);
8221 pSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
8222 sizeof( SECURITY_DESCRIPTOR),
8223 AFS_GENERIC_MEMORY_27_TAG);
8225 if( pSecurityDescr == NULL)
8228 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8230 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8233 ntStatus = RtlCreateSecurityDescriptor( pSecurityDescr,
8234 SECURITY_DESCRIPTOR_REVISION);
8236 if( !NT_SUCCESS( ntStatus))
8239 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateSecurityDescriptor ntStatus %08lX\n",
8242 try_return( ntStatus);
8245 if( AFSRtlSetSaclSecurityDescriptor != NULL)
8247 ntStatus = AFSRtlSetSaclSecurityDescriptor( pSecurityDescr,
8252 if( !NT_SUCCESS( ntStatus))
8255 AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor ntStatus %08lX\n",
8258 try_return( ntStatus);
8263 // Add in the group and owner to the SD
8266 if( AFSRtlSetGroupSecurityDescriptor != NULL)
8268 ntStatus = AFSRtlSetGroupSecurityDescriptor( pSecurityDescr,
8272 if( !NT_SUCCESS( ntStatus))
8275 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetGroupSecurityDescriptor failed ntStatus %08lX\n",
8278 try_return( ntStatus);
8282 ntStatus = RtlSetOwnerSecurityDescriptor( pSecurityDescr,
8286 if( !NT_SUCCESS( ntStatus))
8289 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetOwnerSecurityDescriptor failed ntStatus %08lX\n",
8292 try_return( ntStatus);
8295 if( !RtlValidSecurityDescriptor( pSecurityDescr))
8298 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlValidSecurityDescriptor NOT\n");
8300 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8303 pRelativeSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
8305 AFS_GENERIC_MEMORY_27_TAG);
8307 if( pRelativeSecurityDescr == NULL)
8310 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8312 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8315 ulSDLength = PAGE_SIZE;
8317 ntStatus = RtlAbsoluteToSelfRelativeSD( pSecurityDescr,
8318 pRelativeSecurityDescr,
8321 if( !NT_SUCCESS( ntStatus))
8324 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAbsoluteToSelfRelativeSD ntStatus %08lX\n",
8327 try_return( ntStatus);
8330 AFSDefaultSD = pRelativeSecurityDescr;
8334 if( !NT_SUCCESS( ntStatus))
8337 if( pRelativeSecurityDescr != NULL)
8339 ExFreePool( pRelativeSecurityDescr);
8343 if( pSecurityDescr != NULL)
8345 ExFreePool( pSecurityDescr);
8358 if( pWorldSID != NULL)
8360 ExFreePool( pWorldSID);
8368 AFSRetrieveParentPath( IN UNICODE_STRING *FullFileName,
8369 OUT UNICODE_STRING *ParentPath)
8374 *ParentPath = *FullFileName;
8377 // If the final character is a \, jump over it
8380 if( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] == L'\\')
8382 ParentPath->Length -= sizeof( WCHAR);
8385 while( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] != L'\\')
8387 ParentPath->Length -= sizeof( WCHAR);
8391 // And the separator
8394 ParentPath->Length -= sizeof( WCHAR);