2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSGeneric.cpp
39 #include "AFSCommon.h"
42 // Function: AFSExceptionFilter
46 // This function is the exception handler
50 // A status is returned for the function
54 AFSExceptionFilter( IN ULONG Code,
55 IN PEXCEPTION_POINTERS ExceptPtrs)
58 PEXCEPTION_RECORD ExceptRec;
64 ExceptRec = ExceptPtrs->ExceptionRecord;
66 Context = ExceptPtrs->ContextRecord;
70 "AFSExceptionFilter (Library) - EXR %p CXR %p Code %08lX Address %p Routine %p\n",
73 ExceptRec->ExceptionCode,
74 ExceptRec->ExceptionAddress,
75 (void *)AFSExceptionFilter);
77 DbgPrint("**** Exception Caught in AFS Redirector Library ****\n");
79 DbgPrint("\n\nPerform the following WnDbg Cmds:\n");
80 DbgPrint("\n\t.exr %p ; .cxr %p\n\n", ExceptRec, Context);
82 DbgPrint("**** Exception Complete from AFS Redirector Library ****\n");
84 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION))
87 KeBugCheck( (ULONG)-2);
95 __except( EXCEPTION_EXECUTE_HANDLER)
101 return EXCEPTION_EXECUTE_HANDLER;
105 // Function: AFSLibExAllocatePoolWithTag()
107 // Purpose: Allocate Pool Memory. If BugCheck Exception flag
108 // is configured on, then bugcheck the system if
109 // a memory allocation fails. The routine should be
110 // used for all memory allocations that are to be freed
111 // when the library is unloaded. Memory allocations that
112 // are to survive library unload and reload should be
113 // performed using AFSExAllocatePoolWithTag() which is
114 // provided by the AFS Framework.
117 // POOL_TYPE PoolType - Paged or NonPaged
118 // SIZE_T NumberOfBytes - requested allocation size
119 // ULONG Tag - Pool Allocation Tag to be applied for tracking
122 // void * - the memory allocation
126 AFSLibExAllocatePoolWithTag( IN POOL_TYPE PoolType,
127 IN SIZE_T NumberOfBytes,
131 void *pBuffer = NULL;
133 pBuffer = ExAllocatePoolWithTag( PoolType,
140 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION))
143 KeBugCheck( (ULONG)-2);
150 "AFSLibExAllocatePoolWithTag failure Type %08lX Size %08lX Tag %08lX %08lX\n",
154 PsGetCurrentThread());
164 // Function: AFSAcquireExcl()
166 // Purpose: Called to acquire a resource exclusive with optional wait
169 // PERESOURCE Resource - Resource to acquire
170 // BOOLEAN Wait - Whether to block
173 // BOOLEAN - Whether the mask was acquired
177 AFSAcquireExcl( IN PERESOURCE Resource,
181 BOOLEAN bStatus = FALSE;
184 // Normal kernel APCs must be disabled before calling
185 // ExAcquireResourceExclusiveLite. Otherwise a bugcheck occurs.
188 KeEnterCriticalRegion();
190 bStatus = ExAcquireResourceExclusiveLite( Resource,
196 KeLeaveCriticalRegion();
203 AFSAcquireSharedStarveExclusive( IN PERESOURCE Resource,
207 BOOLEAN bStatus = FALSE;
209 KeEnterCriticalRegion();
211 bStatus = ExAcquireSharedStarveExclusive( Resource,
217 KeLeaveCriticalRegion();
224 // Function: AFSAcquireShared()
226 // Purpose: Called to acquire a resource shared with optional wait
229 // PERESOURCE Resource - Resource to acquire
230 // BOOLEAN Wait - Whether to block
233 // BOOLEAN - Whether the mask was acquired
237 AFSAcquireShared( IN PERESOURCE Resource,
241 BOOLEAN bStatus = FALSE;
243 KeEnterCriticalRegion();
245 bStatus = ExAcquireResourceSharedLite( Resource,
251 KeLeaveCriticalRegion();
258 // Function: AFSReleaseResource()
260 // Purpose: Called to release a resource
263 // PERESOURCE Resource - Resource to release
270 AFSReleaseResource( IN PERESOURCE Resource)
273 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
274 AFS_TRACE_LEVEL_VERBOSE,
275 "AFSReleaseResource Releasing lock %08lX Thread %08lX\n",
277 PsGetCurrentThread());
279 ExReleaseResourceLite( Resource);
281 KeLeaveCriticalRegion();
287 AFSConvertToShared( IN PERESOURCE Resource)
290 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
291 AFS_TRACE_LEVEL_VERBOSE,
292 "AFSConvertToShared Converting lock %08lX Thread %08lX\n",
294 PsGetCurrentThread());
296 ExConvertExclusiveToSharedLite( Resource);
302 // Function: AFSCompleteRequest
306 // This function completes irps
310 // A status is returned for the function
314 AFSCompleteRequest( IN PIRP Irp,
318 Irp->IoStatus.Status = Status;
320 IoCompleteRequest( Irp,
327 // Function: AFSGenerateCRC
331 // Given a device and filename this function generates a CRC
335 // A status is returned for the function
339 AFSGenerateCRC( IN PUNICODE_STRING FileName,
340 IN BOOLEAN UpperCaseName)
344 NTSTATUS ntStatus = STATUS_SUCCESS;
346 ntStatus = RtlHashUnicodeString( FileName,
348 HASH_STRING_ALGORITHM_DEFAULT,
351 if( !NT_SUCCESS( ntStatus))
360 AFSLockSystemBuffer( IN PIRP Irp,
364 NTSTATUS Status = STATUS_SUCCESS;
365 void *pAddress = NULL;
367 if( Irp->MdlAddress != NULL)
370 pAddress = MmGetSystemAddressForMdlSafe( Irp->MdlAddress,
373 else if( Irp->AssociatedIrp.SystemBuffer != NULL)
376 pAddress = Irp->AssociatedIrp.SystemBuffer;
378 else if( Irp->UserBuffer != NULL)
381 Irp->MdlAddress = IoAllocateMdl( Irp->UserBuffer,
387 if( Irp->MdlAddress != NULL)
391 // Lock the new Mdl in memory.
396 PIO_STACK_LOCATION pIoStack;
397 pIoStack = IoGetCurrentIrpStackLocation( Irp);
400 MmProbeAndLockPages( Irp->MdlAddress, KernelMode,
401 (pIoStack->MajorFunction == IRP_MJ_READ) ? IoWriteAccess : IoReadAccess);
403 pAddress = MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority );
406 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
409 IoFreeMdl( Irp->MdlAddress );
410 Irp->MdlAddress = NULL;
420 AFSLockUserBuffer( IN void *UserBuffer,
421 IN ULONG BufferLength,
425 NTSTATUS ntStatus = STATUS_SUCCESS;
426 void *pAddress = NULL;
432 pMdl = IoAllocateMdl( UserBuffer,
441 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
445 // Lock the new Mdl in memory.
451 MmProbeAndLockPages( pMdl,
455 pAddress = MmGetSystemAddressForMdlSafe( pMdl,
458 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
481 AFSMapToService( IN PIRP Irp,
485 NTSTATUS ntStatus = STATUS_SUCCESS;
486 void *pMappedBuffer = NULL;
487 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
493 if( pDevExt->Specific.Control.ServiceProcess == NULL)
496 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
499 if( Irp->MdlAddress == NULL)
502 if( AFSLockSystemBuffer( Irp,
506 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
511 // Attach to the service process for mapping
514 KeStackAttachProcess( pDevExt->Specific.Control.ServiceProcess,
515 (PRKAPC_STATE)&stApcState);
517 pMappedBuffer = MmMapLockedPagesSpecifyCache( Irp->MdlAddress,
524 KeUnstackDetachProcess( (PRKAPC_STATE)&stApcState);
531 return pMappedBuffer;
535 AFSUnmapServiceMappedBuffer( IN void *MappedBuffer,
539 NTSTATUS ntStatus = STATUS_SUCCESS;
540 void *pMappedBuffer = NULL;
541 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
547 if( pDevExt->Specific.Control.ServiceProcess == NULL)
550 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
557 // Attach to the service process for mapping
560 KeStackAttachProcess( pDevExt->Specific.Control.ServiceProcess,
561 (PRKAPC_STATE)&stApcState);
563 MmUnmapLockedPages( MappedBuffer,
566 KeUnstackDetachProcess( (PRKAPC_STATE)&stApcState);
578 AFSInitializeLibraryDevice()
581 NTSTATUS ntStatus = STATUS_SUCCESS;
582 AFSDeviceExt *pDeviceExt = NULL;
587 pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
590 // The PIOCtl file name
593 RtlInitUnicodeString( &AFSPIOCtlName,
594 AFS_PIOCTL_FILE_INTERFACE_NAME);
597 // And the global root share name
600 RtlInitUnicodeString( &AFSGlobalRootName,
601 AFS_GLOBAL_ROOT_SHARE_NAME);
609 AFSRemoveLibraryDevice()
612 NTSTATUS ntStatus = STATUS_SUCCESS;
623 AFSDefaultDispatch( IN PDEVICE_OBJECT DeviceObject,
627 NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
628 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
630 AFSCompleteRequest( Irp,
637 AFSInitializeGlobalDirectoryEntries()
640 NTSTATUS ntStatus = STATUS_SUCCESS;
641 AFSDirectoryCB *pDirNode = NULL;
642 ULONG ulEntryLength = 0;
643 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
644 AFSObjectInfoCB *pObjectInfoCB = NULL;
645 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
652 // Initialize the global . entry
655 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
658 if( pObjectInfoCB == NULL)
661 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
662 AFS_TRACE_LEVEL_ERROR,
663 "AFSInitializeGlobalDirectory AFSAllocateObjectInfo failure %08lX\n",
666 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
669 lCount = InterlockedIncrement( &pObjectInfoCB->ObjectReferenceCount);
671 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
672 AFS_TRACE_LEVEL_VERBOSE,
673 "AFSInitializeGlobalDirectoryEntries Increment count on object %08lX Cnt %d\n",
677 ntStatus = STATUS_SUCCESS;
679 ulEntryLength = sizeof( AFSDirectoryCB) +
682 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
686 if( pDirNode == NULL)
689 AFSDeleteObjectInfo( pObjectInfoCB);
691 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
692 AFS_TRACE_LEVEL_ERROR,
693 "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_TAG allocation failure\n");
695 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
698 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
699 sizeof( AFSNonPagedDirectoryCB),
700 AFS_DIR_ENTRY_NP_TAG);
702 if( pNonPagedDirEntry == NULL)
705 ExFreePool( pDirNode);
707 AFSDeleteObjectInfo( pObjectInfoCB);
709 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
710 AFS_TRACE_LEVEL_ERROR,
711 "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_NP_TAG allocation failure\n");
713 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
716 RtlZeroMemory( pDirNode,
719 RtlZeroMemory( pNonPagedDirEntry,
720 sizeof( AFSNonPagedDirectoryCB));
722 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
724 pDirNode->NonPaged = pNonPagedDirEntry;
726 pDirNode->ObjectInformation = pObjectInfoCB;
732 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE | AFS_DIR_ENTRY_FAKE | AFS_DIR_ENTRY_VALID);
734 pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_DOT_INDEX;
737 // Setup the names in the entry
740 pDirNode->NameInformation.FileName.Length = sizeof( WCHAR);
742 pDirNode->NameInformation.FileName.MaximumLength = sizeof( WCHAR);
744 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
746 pDirNode->NameInformation.FileName.Buffer[ 0] = L'.';
749 // Populate the rest of the data
752 pObjectInfoCB->FileType = AFS_FILE_TYPE_DIRECTORY;
754 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
756 AFSGlobalDotDirEntry = pDirNode;
762 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
765 if( pObjectInfoCB == NULL)
768 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
769 AFS_TRACE_LEVEL_ERROR,
770 "AFSInitializeGlobalDirectory AFSAllocateObjectInfo (2) failure %08lX\n",
773 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
776 lCount = InterlockedIncrement( &pObjectInfoCB->ObjectReferenceCount);
778 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
779 AFS_TRACE_LEVEL_VERBOSE,
780 "AFSInitializeGlobalDirectoryEntries Increment count on object %08lX Cnt %d\n",
784 ntStatus = STATUS_SUCCESS;
786 ulEntryLength = sizeof( AFSDirectoryCB) +
787 ( 2 * sizeof( WCHAR));
789 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
793 if( pDirNode == NULL)
796 AFSDeleteObjectInfo( pObjectInfoCB);
798 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
801 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
802 sizeof( AFSNonPagedDirectoryCB),
803 AFS_DIR_ENTRY_NP_TAG);
805 if( pNonPagedDirEntry == NULL)
808 ExFreePool( pDirNode);
810 AFSDeleteObjectInfo( pObjectInfoCB);
812 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
815 RtlZeroMemory( pDirNode,
818 RtlZeroMemory( pNonPagedDirEntry,
819 sizeof( AFSNonPagedDirectoryCB));
821 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
823 pDirNode->NonPaged = pNonPagedDirEntry;
825 pDirNode->ObjectInformation = pObjectInfoCB;
831 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE | AFS_DIR_ENTRY_FAKE | AFS_DIR_ENTRY_VALID);
833 pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX;
836 // Setup the names in the entry
839 pDirNode->NameInformation.FileName.Length = 2 * sizeof( WCHAR);
841 pDirNode->NameInformation.FileName.MaximumLength = 2 * sizeof( WCHAR);
843 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
845 pDirNode->NameInformation.FileName.Buffer[ 0] = L'.';
847 pDirNode->NameInformation.FileName.Buffer[ 1] = L'.';
850 // Populate the rest of the data
853 pObjectInfoCB->FileType = AFS_FILE_TYPE_DIRECTORY;
855 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
857 AFSGlobalDotDotDirEntry = pDirNode;
861 if( !NT_SUCCESS( ntStatus))
864 if( AFSGlobalDotDirEntry != NULL)
867 AFSDeleteObjectInfo( AFSGlobalDotDirEntry->ObjectInformation);
869 ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
871 ExFreePool( AFSGlobalDotDirEntry->NonPaged);
873 ExFreePool( AFSGlobalDotDirEntry);
875 AFSGlobalDotDirEntry = NULL;
878 if( AFSGlobalDotDotDirEntry != NULL)
881 AFSDeleteObjectInfo( AFSGlobalDotDotDirEntry->ObjectInformation);
883 ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
885 ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
887 ExFreePool( AFSGlobalDotDotDirEntry);
889 AFSGlobalDotDotDirEntry = NULL;
898 AFSInitDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
899 IN PUNICODE_STRING FileName,
900 IN PUNICODE_STRING TargetName,
901 IN AFSDirEnumEntry *DirEnumEntry,
905 AFSDirectoryCB *pDirNode = NULL;
906 NTSTATUS ntStatus = STATUS_SUCCESS;
907 ULONG ulEntryLength = 0;
908 AFSDirEnumEntry *pDirEnumCB = NULL;
909 AFSFileID stTargetFileID;
911 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
912 AFSObjectInfoCB *pObjectInfoCB = NULL;
913 BOOLEAN bAllocatedObjectCB = FALSE;
914 ULONGLONG ullIndex = 0;
915 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
921 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
922 AFS_TRACE_LEVEL_VERBOSE,
923 "AFSInitDirEntry Initializing entry %wZ parent FID %08lX-%08lX-%08lX-%08lX\n",
925 ParentObjectInfo->FileId.Cell,
926 ParentObjectInfo->FileId.Volume,
927 ParentObjectInfo->FileId.Vnode,
928 ParentObjectInfo->FileId.Unique);
931 // First thing is to locate/create our object information block
935 AFSAcquireExcl( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
938 ullIndex = AFSCreateLowIndex( &DirEnumEntry->FileId);
940 ntStatus = AFSLocateHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
942 (AFSBTreeEntry **)&pObjectInfoCB);
944 if( !NT_SUCCESS( ntStatus) ||
945 pObjectInfoCB == NULL)
949 // Allocate our object info cb
952 pObjectInfoCB = AFSAllocateObjectInfo( ParentObjectInfo,
955 if( pObjectInfoCB == NULL)
958 AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
960 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
963 bAllocatedObjectCB = TRUE;
965 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
966 AFS_TRACE_LEVEL_VERBOSE,
967 "AFSInitDirEntry initialized object %08lX Parent Object %08lX for %wZ\n",
973 lCount = InterlockedIncrement( &pObjectInfoCB->ObjectReferenceCount);
975 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
976 AFS_TRACE_LEVEL_VERBOSE,
977 "AFSInitDirEntry Increment count on object %08lX Cnt %d\n",
981 AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
983 ntStatus = STATUS_SUCCESS;
985 ulEntryLength = sizeof( AFSDirectoryCB) +
988 if( TargetName != NULL)
991 ulEntryLength += TargetName->Length;
994 pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
998 if( pDirNode == NULL)
1001 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1004 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
1005 sizeof( AFSNonPagedDirectoryCB),
1006 AFS_DIR_ENTRY_NP_TAG);
1008 if( pNonPagedDirEntry == NULL)
1011 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1014 RtlZeroMemory( pDirNode,
1017 RtlZeroMemory( pNonPagedDirEntry,
1018 sizeof( AFSNonPagedDirectoryCB));
1020 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
1022 pDirNode->NonPaged = pNonPagedDirEntry;
1024 pDirNode->ObjectInformation = pObjectInfoCB;
1027 // Set valid entry and NOT_IN_PARENT flag
1030 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1032 pDirNode->FileIndex = FileIndex;
1035 // Setup the names in the entry
1038 if( FileName->Length > 0)
1041 pDirNode->NameInformation.FileName.Length = FileName->Length;
1043 pDirNode->NameInformation.FileName.MaximumLength = FileName->Length;
1045 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
1047 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
1049 pDirNode->NameInformation.FileName.Length);
1052 // Create a CRC for the file
1055 pDirNode->CaseSensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1058 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1062 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1063 AFS_TRACE_LEVEL_VERBOSE,
1064 "AFSInitDirEntry Initialized DE %p for %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1067 ParentObjectInfo->FileId.Cell,
1068 ParentObjectInfo->FileId.Volume,
1069 ParentObjectInfo->FileId.Vnode,
1070 ParentObjectInfo->FileId.Unique);
1072 if( TargetName != NULL &&
1073 TargetName->Length > 0)
1076 pDirNode->NameInformation.TargetName.Length = TargetName->Length;
1078 pDirNode->NameInformation.TargetName.MaximumLength = pDirNode->NameInformation.TargetName.Length;
1080 pDirNode->NameInformation.TargetName.Buffer = (WCHAR *)((char *)pDirNode +
1081 sizeof( AFSDirectoryCB) +
1082 pDirNode->NameInformation.FileName.Length);
1084 RtlCopyMemory( pDirNode->NameInformation.TargetName.Buffer,
1086 pDirNode->NameInformation.TargetName.Length);
1090 // If we allocated the object information cb then update the information
1093 if( bAllocatedObjectCB)
1097 // Populate the rest of the data
1100 pObjectInfoCB->FileId = DirEnumEntry->FileId;
1102 pObjectInfoCB->TargetFileId = DirEnumEntry->TargetFileId;
1104 pObjectInfoCB->FileType = DirEnumEntry->FileType;
1106 pObjectInfoCB->CreationTime = DirEnumEntry->CreationTime;
1108 pObjectInfoCB->LastAccessTime = DirEnumEntry->LastAccessTime;
1110 pObjectInfoCB->LastWriteTime = DirEnumEntry->LastWriteTime;
1112 pObjectInfoCB->ChangeTime = DirEnumEntry->ChangeTime;
1114 pObjectInfoCB->EndOfFile = DirEnumEntry->EndOfFile;
1116 pObjectInfoCB->AllocationSize = DirEnumEntry->AllocationSize;
1118 pObjectInfoCB->FileAttributes = DirEnumEntry->FileAttributes;
1120 if( pObjectInfoCB->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1123 pObjectInfoCB->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1126 if (pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK ||
1127 pObjectInfoCB->FileType == AFS_FILE_TYPE_DFSLINK)
1130 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1133 pObjectInfoCB->EaSize = DirEnumEntry->EaSize;
1136 // Object specific information
1139 pObjectInfoCB->Links = DirEnumEntry->Links;
1141 pObjectInfoCB->Expiration = DirEnumEntry->Expiration;
1143 pObjectInfoCB->DataVersion = DirEnumEntry->DataVersion;
1146 // Check for the case where we have a filetype of SymLink but both the TargetFid and the
1147 // TargetName are empty. In this case set the filetype to zero so we evaluate it later in
1151 if( pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK &&
1152 pObjectInfoCB->TargetFileId.Vnode == 0 &&
1153 pObjectInfoCB->TargetFileId.Unique == 0 &&
1154 pDirNode->NameInformation.TargetName.Length == 0)
1158 // This will ensure we perform a validation on the node
1161 pObjectInfoCB->FileType = AFS_FILE_TYPE_UNKNOWN;
1164 if( pObjectInfoCB->FileType == AFS_FILE_TYPE_UNKNOWN)
1167 SetFlag( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
1173 if( !NT_SUCCESS( ntStatus))
1176 if( pNonPagedDirEntry != NULL)
1179 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
1181 AFSExFreePool( pNonPagedDirEntry);
1184 if( pDirNode != NULL)
1187 AFSExFreePool( pDirNode);
1193 // Dereference our object info block if we have one
1196 if( pObjectInfoCB != NULL)
1199 lCount = InterlockedDecrement( &pObjectInfoCB->ObjectReferenceCount);
1201 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1202 AFS_TRACE_LEVEL_VERBOSE,
1203 "AFSInitDirEntry Decrement count on object %08lX Cnt %d\n",
1207 if( bAllocatedObjectCB)
1210 ASSERT( pObjectInfoCB->ObjectReferenceCount == 0);
1212 AFSDeleteObjectInfo( pObjectInfoCB);
1222 AFSCheckForReadOnlyAccess( IN ACCESS_MASK DesiredAccess,
1223 IN BOOLEAN DirectoryEntry)
1226 BOOLEAN bReturn = TRUE;
1227 ACCESS_MASK stAccessMask = 0;
1230 // Get rid of anything we don't know about
1233 DesiredAccess = (DesiredAccess &
1239 ACCESS_SYSTEM_SECURITY |
1243 FILE_READ_ATTRIBUTES |
1244 FILE_WRITE_ATTRIBUTES |
1245 FILE_LIST_DIRECTORY |
1251 // Our 'read only' access mask. These are the accesses we will
1252 // allow for a read only file
1255 stAccessMask = DELETE |
1260 ACCESS_SYSTEM_SECURITY |
1264 FILE_READ_ATTRIBUTES |
1265 FILE_WRITE_ATTRIBUTES |
1267 FILE_LIST_DIRECTORY |
1271 // For a directory, add in the directory specific accesses
1277 stAccessMask |= FILE_ADD_SUBDIRECTORY |
1282 if( FlagOn( DesiredAccess, ~stAccessMask))
1286 // A write access is set ...
1296 AFSEvaluateNode( IN GUID *AuthGroup,
1297 IN AFSDirectoryCB *DirEntry)
1300 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1301 NTSTATUS ntStatus = STATUS_SUCCESS;
1302 AFSDirEnumEntry *pDirEntry = NULL;
1303 UNICODE_STRING uniTargetName;
1308 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1313 if( !NT_SUCCESS( ntStatus))
1316 try_return( ntStatus);
1319 DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1321 DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1323 DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1325 DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1327 DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1329 DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1331 DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1333 DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1335 DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1337 DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1339 DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1341 if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1344 DirEntry->ObjectInformation->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1347 if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK ||
1348 pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1351 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1354 DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1356 DirEntry->ObjectInformation->Links = pDirEntry->Links;
1359 // If we have a target name then see if it needs updating ...
1362 if( pDirEntry->TargetNameLength > 0)
1366 // Update the target name information if needed
1369 uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1371 uniTargetName.MaximumLength = uniTargetName.Length;
1373 uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1375 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1378 if( DirEntry->NameInformation.TargetName.Length == 0 ||
1379 RtlCompareUnicodeString( &uniTargetName,
1380 &DirEntry->NameInformation.TargetName,
1385 // Update the target name
1388 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1390 uniTargetName.Buffer,
1391 uniTargetName.Length);
1393 if( !NT_SUCCESS( ntStatus))
1396 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1398 try_return( ntStatus);
1402 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1407 if( pDirEntry != NULL)
1410 AFSExFreePool( pDirEntry);
1418 AFSValidateSymLink( IN GUID *AuthGroup,
1419 IN AFSDirectoryCB *DirEntry)
1422 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1423 NTSTATUS ntStatus = STATUS_SUCCESS;
1424 AFSDirEnumEntry *pDirEntry = NULL;
1425 UNICODE_STRING uniTargetName;
1430 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1435 if( !NT_SUCCESS( ntStatus))
1438 try_return( ntStatus);
1441 if( pDirEntry->FileType == AFS_FILE_TYPE_UNKNOWN ||
1442 pDirEntry->FileType == AFS_FILE_TYPE_INVALID)
1445 try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
1448 DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1450 DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1452 DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1455 // Update the target name information if needed
1458 uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1460 uniTargetName.MaximumLength = uniTargetName.Length;
1462 uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1464 if( uniTargetName.Length > 0)
1467 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1470 if( DirEntry->NameInformation.TargetName.Length == 0 ||
1471 RtlCompareUnicodeString( &uniTargetName,
1472 &DirEntry->NameInformation.TargetName,
1477 // Update the target name
1480 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1482 uniTargetName.Buffer,
1483 uniTargetName.Length);
1485 if( !NT_SUCCESS( ntStatus))
1488 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1490 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1494 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1498 // If the FileType is the same then nothing to do since it IS
1502 if( pDirEntry->FileType == DirEntry->ObjectInformation->FileType)
1505 ASSERT( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK);
1507 try_return( ntStatus = STATUS_SUCCESS);
1510 DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1512 DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1514 DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1516 DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1518 DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1520 DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1522 DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1524 DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1526 if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1529 DirEntry->ObjectInformation->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1532 if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK ||
1533 pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1536 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1539 DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1541 DirEntry->ObjectInformation->Links = pDirEntry->Links;
1545 if( pDirEntry != NULL)
1548 AFSExFreePool( pDirEntry);
1556 AFSInvalidateObject( IN OUT AFSObjectInfoCB **ppObjectInfo,
1560 NTSTATUS ntStatus = STATUS_SUCCESS;
1561 IO_STATUS_BLOCK stIoStatus;
1564 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1565 AFS_TRACE_LEVEL_VERBOSE,
1566 "AFSInvalidateObject Invalidation on node type %d for fid %08lX-%08lX-%08lX-%08lX Reason %d\n",
1567 (*ppObjectInfo)->FileType,
1568 (*ppObjectInfo)->FileId.Cell,
1569 (*ppObjectInfo)->FileId.Volume,
1570 (*ppObjectInfo)->FileId.Vnode,
1571 (*ppObjectInfo)->FileId.Unique,
1574 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_SYMLINK ||
1575 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DFSLINK ||
1576 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1579 // We only act on the mount point itself, not the target. If the
1580 // node has been deleted then mark it as such otherwise indicate
1581 // it requires verification
1584 if( Reason == AFS_INVALIDATE_DELETED)
1586 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
1591 if( Reason == AFS_INVALIDATE_FLUSHED)
1594 (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1596 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1599 (*ppObjectInfo)->Expiration.QuadPart = 0;
1601 (*ppObjectInfo)->TargetFileId.Vnode = 0;
1603 (*ppObjectInfo)->TargetFileId.Unique = 0;
1605 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1606 AFS_TRACE_LEVEL_VERBOSE,
1607 "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1608 (*ppObjectInfo)->FileId.Cell,
1609 (*ppObjectInfo)->FileId.Volume,
1610 (*ppObjectInfo)->FileId.Vnode,
1611 (*ppObjectInfo)->FileId.Unique);
1613 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1616 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1618 if( Reason == AFS_INVALIDATE_CREDS)
1620 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1623 if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1624 Reason == AFS_INVALIDATE_FLUSHED)
1626 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1630 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1633 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
1635 FILE_NOTIFY_CHANGE_FILE_NAME |
1636 FILE_NOTIFY_CHANGE_ATTRIBUTES,
1637 FILE_ACTION_MODIFIED);
1639 try_return( ntStatus);
1643 // Depending on the reason for invalidation then perform work on the node
1649 case AFS_INVALIDATE_DELETED:
1653 // Mark this node as invalid
1656 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_DELETED);
1658 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1659 AFS_TRACE_LEVEL_VERBOSE,
1660 "AFSInvalidateObject Set DELETE flag on fid %08lX-%08lX-%08lX-%08lX\n",
1661 (*ppObjectInfo)->FileId.Cell,
1662 (*ppObjectInfo)->FileId.Volume,
1663 (*ppObjectInfo)->FileId.Vnode,
1664 (*ppObjectInfo)->FileId.Unique);
1666 if( (*ppObjectInfo)->ParentObjectInformation != NULL)
1669 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1670 AFS_TRACE_LEVEL_VERBOSE,
1671 "AFSInvalidateObject Set VERIFY flag on parent fid %08lX-%08lX-%08lX-%08lX\n",
1672 (*ppObjectInfo)->ParentObjectInformation->FileId.Cell,
1673 (*ppObjectInfo)->ParentObjectInformation->FileId.Volume,
1674 (*ppObjectInfo)->ParentObjectInformation->FileId.Vnode,
1675 (*ppObjectInfo)->ParentObjectInformation->FileId.Unique);
1677 SetFlag( (*ppObjectInfo)->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1679 (*ppObjectInfo)->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1681 (*ppObjectInfo)->ParentObjectInformation->Expiration.QuadPart = 0;
1684 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1686 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1690 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1693 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
1696 FILE_ACTION_REMOVED);
1698 if( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1701 (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1707 case AFS_INVALIDATE_FLUSHED:
1710 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1711 (*ppObjectInfo)->Fcb != NULL)
1714 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1715 AFS_TRACE_LEVEL_VERBOSE,
1716 "AFSInvalidateObject Flush/purge file fid %08lX-%08lX-%08lX-%08lX\n",
1717 (*ppObjectInfo)->FileId.Cell,
1718 (*ppObjectInfo)->FileId.Volume,
1719 (*ppObjectInfo)->FileId.Vnode,
1720 (*ppObjectInfo)->FileId.Unique);
1722 AFSAcquireExcl( &(*ppObjectInfo)->Fcb->NPFcb->Resource,
1728 CcFlushCache( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1733 if( !NT_SUCCESS( stIoStatus.Status))
1736 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1737 AFS_TRACE_LEVEL_ERROR,
1738 "AFSInvalidateObject CcFlushCache failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1739 (*ppObjectInfo)->FileId.Cell,
1740 (*ppObjectInfo)->FileId.Volume,
1741 (*ppObjectInfo)->FileId.Vnode,
1742 (*ppObjectInfo)->FileId.Unique,
1744 stIoStatus.Information);
1746 ntStatus = stIoStatus.Status;
1749 CcPurgeCacheSection( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1754 __except( EXCEPTION_EXECUTE_HANDLER)
1757 ntStatus = GetExceptionCode();
1760 AFSReleaseResource( &(*ppObjectInfo)->Fcb->NPFcb->Resource);
1763 // Clear out the extents
1764 // Get rid of them (note this involves waiting
1765 // for any writes or reads to the cache to complete)
1768 (VOID) AFSTearDownFcbExtents( (*ppObjectInfo)->Fcb,
1772 (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1775 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE)
1778 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1779 AFS_TRACE_LEVEL_VERBOSE,
1780 "AFSInvalidateObject Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
1781 (*ppObjectInfo)->FileId.Cell,
1782 (*ppObjectInfo)->FileId.Volume,
1783 (*ppObjectInfo)->FileId.Vnode,
1784 (*ppObjectInfo)->FileId.Unique);
1786 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1789 // Fall through to the default processing
1795 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1797 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1801 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1804 if( Reason == AFS_INVALIDATE_CREDS)
1806 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1809 if( Reason == AFS_INVALIDATE_DATA_VERSION)
1811 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1815 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1818 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
1821 FILE_ACTION_MODIFIED);
1824 // Indicate this node requires re-evaluation for the remaining reasons
1827 (*ppObjectInfo)->Expiration.QuadPart = 0;
1829 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1830 AFS_TRACE_LEVEL_VERBOSE,
1831 "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1832 (*ppObjectInfo)->FileId.Cell,
1833 (*ppObjectInfo)->FileId.Volume,
1834 (*ppObjectInfo)->FileId.Vnode,
1835 (*ppObjectInfo)->FileId.Unique);
1837 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1839 if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1840 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1841 ( Reason == AFS_INVALIDATE_CALLBACK ||
1842 Reason == AFS_INVALIDATE_EXPIRED))
1844 if ( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1845 AFS_INVALIDATE_DATA_VERSION)))
1848 (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1862 AFSInvalidateCache( IN AFSInvalidateCacheCB *InvalidateCB)
1865 NTSTATUS ntStatus = STATUS_SUCCESS;
1866 AFSFcb *pDcb = NULL, *pFcb = NULL, *pNextFcb = NULL;
1867 AFSVolumeCB *pVolumeCB = NULL;
1868 AFSFcb *pTargetDcb = NULL;
1869 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1870 AFSDirectoryCB *pCurrentDirEntry = NULL;
1871 BOOLEAN bIsChild = FALSE;
1872 ULONGLONG ullIndex = 0;
1873 AFSObjectInfoCB *pObjectInfo = NULL;
1879 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1880 AFS_TRACE_LEVEL_VERBOSE,
1881 "AFSInvalidateCache Invalidation FID %08lX-%08lX-%08lX-%08lX Type %d WholeVolume %d Reason %d\n",
1882 InvalidateCB->FileID.Cell,
1883 InvalidateCB->FileID.Volume,
1884 InvalidateCB->FileID.Vnode,
1885 InvalidateCB->FileID.Unique,
1886 InvalidateCB->FileType,
1887 InvalidateCB->WholeVolume,
1888 InvalidateCB->Reason);
1891 // Need to locate the Fcb for the directory to purge
1894 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1895 AFS_TRACE_LEVEL_VERBOSE,
1896 "AFSInvalidateCache Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1897 &pDevExt->Specific.RDR.VolumeTreeLock,
1898 PsGetCurrentThread());
1901 // Starve any exclusive waiters on this paticular call
1904 AFSAcquireSharedStarveExclusive( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1907 // Locate the volume node
1910 ullIndex = AFSCreateHighIndex( &InvalidateCB->FileID);
1912 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1914 (AFSBTreeEntry **)&pVolumeCB);
1916 if( pVolumeCB != NULL)
1919 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1921 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1922 AFS_TRACE_LEVEL_VERBOSE,
1923 "AFSInvalidateCache Increment count on volume %08lX Cnt %d\n",
1928 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1930 if( !NT_SUCCESS( ntStatus) ||
1934 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1935 AFS_TRACE_LEVEL_WARNING,
1936 "AFSInvalidateCache Invalidation FAILURE Unable to locate volume node FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1937 InvalidateCB->FileID.Cell,
1938 InvalidateCB->FileID.Volume,
1939 InvalidateCB->FileID.Vnode,
1940 InvalidateCB->FileID.Unique,
1943 try_return( ntStatus = STATUS_SUCCESS);
1947 // If this is a whole volume invalidation then go do it now
1950 if( InvalidateCB->WholeVolume)
1953 ntStatus = AFSInvalidateVolume( pVolumeCB,
1954 InvalidateCB->Reason);
1956 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1958 try_return( ntStatus);
1961 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1964 if ( AFSIsVolumeFID( &InvalidateCB->FileID))
1967 pObjectInfo = &pVolumeCB->ObjectInformation;
1972 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1974 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1975 AFS_TRACE_LEVEL_VERBOSE,
1976 "AFSInvalidateCache Decrement count on volume %08lX Cnt %d\n",
1978 pVolumeCB->VolumeReferenceCount);
1980 ullIndex = AFSCreateLowIndex( &InvalidateCB->FileID);
1982 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1984 (AFSBTreeEntry **)&pObjectInfo);
1987 if( pObjectInfo != NULL)
1991 // Reference the node so it won't be torn down
1994 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1996 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1997 AFS_TRACE_LEVEL_VERBOSE,
1998 "AFSInvalidateCache Increment count on object %08lX Cnt %d\n",
2003 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2005 if( !NT_SUCCESS( ntStatus) ||
2006 pObjectInfo == NULL)
2009 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2010 AFS_TRACE_LEVEL_WARNING,
2011 "AFSInvalidateCache Invalidation FAILURE Unable to locate object FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2012 InvalidateCB->FileID.Cell,
2013 InvalidateCB->FileID.Volume,
2014 InvalidateCB->FileID.Vnode,
2015 InvalidateCB->FileID.Unique,
2018 try_return( ntStatus = STATUS_SUCCESS);
2021 AFSInvalidateObject( &pObjectInfo,
2022 InvalidateCB->Reason);
2026 if( pObjectInfo != NULL)
2029 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2031 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2032 AFS_TRACE_LEVEL_VERBOSE,
2033 "AFSInvalidateCache Decrement count on object %08lX Cnt %d\n",
2043 AFSIsChildOfParent( IN AFSFcb *Dcb,
2047 BOOLEAN bIsChild = FALSE;
2048 AFSFcb *pCurrentFcb = Fcb;
2050 while( pCurrentFcb != NULL)
2053 if( pCurrentFcb->ObjectInformation->ParentObjectInformation == Dcb->ObjectInformation)
2061 pCurrentFcb = pCurrentFcb->ObjectInformation->ParentObjectInformation->Fcb;
2069 AFSCreateHighIndex( IN AFSFileID *FileID)
2072 ULONGLONG ullIndex = 0;
2074 ullIndex = (((ULONGLONG)FileID->Cell << 32) | FileID->Volume);
2081 AFSCreateLowIndex( IN AFSFileID *FileID)
2084 ULONGLONG ullIndex = 0;
2086 ullIndex = (((ULONGLONG)FileID->Vnode << 32) | FileID->Unique);
2092 AFSCheckAccess( IN ACCESS_MASK DesiredAccess,
2093 IN ACCESS_MASK GrantedAccess,
2094 IN BOOLEAN DirectoryEntry)
2097 BOOLEAN bAccessGranted = TRUE;
2100 // Check if we are asking for read/write and granted only read only
2101 // NOTE: There will be more checks here
2104 if( !AFSCheckForReadOnlyAccess( DesiredAccess,
2106 AFSCheckForReadOnlyAccess( GrantedAccess,
2110 bAccessGranted = FALSE;
2113 return bAccessGranted;
2117 AFSGetDriverStatus( IN AFSDriverStatusRespCB *DriverStatus)
2120 NTSTATUS ntStatus = STATUS_SUCCESS;
2121 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2127 DriverStatus->Status = AFS_DRIVER_STATUS_READY;
2129 if( AFSGlobalRoot == NULL)
2136 DriverStatus->Status = AFS_DRIVER_STATUS_NOT_READY;
2139 if( pControlDevExt->Specific.Control.CommServiceCB.IrpPoolControlFlag != POOL_ACTIVE)
2146 DriverStatus->Status = AFS_DRIVER_STATUS_NO_SERVICE;
2153 AFSSubstituteSysName( IN UNICODE_STRING *ComponentName,
2154 IN UNICODE_STRING *SubstituteName,
2155 IN ULONG StringIndex)
2158 NTSTATUS ntStatus = STATUS_SUCCESS;
2159 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2160 AFSSysNameCB *pSysName = NULL;
2161 ERESOURCE *pSysNameLock = NULL;
2164 UNICODE_STRING uniSysName;
2171 if( IoIs32bitProcess( NULL))
2174 pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2176 pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2181 pSysNameLock = &pControlDevExt->Specific.Control.SysName64ListLock;
2183 pSysName = pControlDevExt->Specific.Control.SysName64ListHead;
2187 pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2189 pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2193 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2194 AFS_TRACE_LEVEL_VERBOSE,
2195 "AFSSubstituteSysName Acquiring SysName lock %08lX SHARED %08lX\n",
2197 PsGetCurrentThread());
2199 AFSAcquireShared( pSysNameLock,
2203 // Find where we are in the list
2206 while( pSysName != NULL &&
2207 ulIndex < StringIndex)
2210 pSysName = pSysName->fLink;
2215 if( pSysName == NULL)
2218 try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
2221 RtlInitUnicodeString( &uniSysName,
2224 // If it is a full component of @SYS then just substitue the
2228 if( RtlCompareUnicodeString( &uniSysName,
2233 SubstituteName->Length = pSysName->SysName.Length;
2234 SubstituteName->MaximumLength = SubstituteName->Length;
2236 SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2237 SubstituteName->Length,
2238 AFS_SUBST_BUFFER_TAG);
2240 if( SubstituteName->Buffer == NULL)
2243 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2246 RtlCopyMemory( SubstituteName->Buffer,
2247 pSysName->SysName.Buffer,
2248 pSysName->SysName.Length);
2255 while( ComponentName->Buffer[ usIndex] != L'@')
2261 SubstituteName->Length = (usIndex * sizeof( WCHAR)) + pSysName->SysName.Length;
2262 SubstituteName->MaximumLength = SubstituteName->Length;
2264 SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2265 SubstituteName->Length,
2266 AFS_SUBST_BUFFER_TAG);
2268 if( SubstituteName->Buffer == NULL)
2271 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2274 RtlCopyMemory( SubstituteName->Buffer,
2275 ComponentName->Buffer,
2276 usIndex * sizeof( WCHAR));
2278 RtlCopyMemory( &SubstituteName->Buffer[ usIndex],
2279 pSysName->SysName.Buffer,
2280 pSysName->SysName.Length);
2285 AFSReleaseResource( pSysNameLock);
2292 AFSSubstituteNameInPath( IN OUT UNICODE_STRING *FullPathName,
2293 IN OUT UNICODE_STRING *ComponentName,
2294 IN UNICODE_STRING *SubstituteName,
2295 IN OUT UNICODE_STRING *RemainingPath,
2296 IN BOOLEAN FreePathName)
2299 NTSTATUS ntStatus = STATUS_SUCCESS;
2300 UNICODE_STRING uniPathName;
2301 USHORT usPrefixNameLen = 0;
2302 SHORT sNameLenDelta = 0;
2308 // If the passed in name can handle the additional length
2309 // then just moves things around
2312 sNameLenDelta = SubstituteName->Length - ComponentName->Length;
2314 usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2316 if( FullPathName->MaximumLength > FullPathName->Length + sNameLenDelta)
2319 if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2322 RtlMoveMemory( &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + SubstituteName->Length)/sizeof( WCHAR))],
2323 &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + ComponentName->Length)/sizeof( WCHAR))],
2324 FullPathName->Length - usPrefixNameLen*sizeof( WCHAR) - ComponentName->Length);
2327 RtlCopyMemory( &FullPathName->Buffer[ usPrefixNameLen],
2328 SubstituteName->Buffer,
2329 SubstituteName->Length);
2331 FullPathName->Length += sNameLenDelta;
2333 ComponentName->Length += sNameLenDelta;
2335 ComponentName->MaximumLength = ComponentName->Length;
2337 if ( RemainingPath->Buffer)
2340 RemainingPath->Buffer += sNameLenDelta/sizeof( WCHAR);
2343 try_return( ntStatus);
2347 // Need to re-allocate the buffer
2350 uniPathName.Length = FullPathName->Length -
2351 ComponentName->Length +
2352 SubstituteName->Length;
2354 uniPathName.MaximumLength = FullPathName->MaximumLength + PAGE_SIZE;
2356 uniPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2357 uniPathName.MaximumLength,
2358 AFS_NAME_BUFFER_FOUR_TAG);
2360 if( uniPathName.Buffer == NULL)
2363 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2366 usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2368 usPrefixNameLen *= sizeof( WCHAR);
2370 RtlZeroMemory( uniPathName.Buffer,
2371 uniPathName.MaximumLength);
2373 RtlCopyMemory( uniPathName.Buffer,
2374 FullPathName->Buffer,
2377 RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen/sizeof( WCHAR))],
2378 SubstituteName->Buffer,
2379 SubstituteName->Length);
2381 if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2384 RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen + SubstituteName->Length)/sizeof( WCHAR)],
2385 &FullPathName->Buffer[ (usPrefixNameLen + ComponentName->Length)/sizeof( WCHAR)],
2386 FullPathName->Length - usPrefixNameLen - ComponentName->Length);
2389 ComponentName->Buffer = uniPathName.Buffer + (ComponentName->Buffer - FullPathName->Buffer);
2391 ComponentName->Length += sNameLenDelta;
2393 ComponentName->MaximumLength = ComponentName->Length;
2395 if ( RemainingPath->Buffer)
2398 RemainingPath->Buffer = uniPathName.Buffer
2399 + (RemainingPath->Buffer - FullPathName->Buffer)
2400 + sNameLenDelta/sizeof( WCHAR);
2405 AFSExFreePool( FullPathName->Buffer);
2408 *FullPathName = uniPathName;
2419 AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
2423 NTSTATUS ntStatus = STATUS_SUCCESS;
2424 AFSObjectInfoCB *pCurrentObject = NULL;
2425 AFSObjectInfoCB *pNextObject = NULL;
2427 AFSFcb *pFcb = NULL;
2433 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2434 AFS_TRACE_LEVEL_VERBOSE,
2435 "AFSInvalidateVolume Invalidate volume fid %08lX-%08lX-%08lX-%08lX Reason %08lX\n",
2436 VolumeCB->ObjectInformation.FileId.Cell,
2437 VolumeCB->ObjectInformation.FileId.Volume,
2438 VolumeCB->ObjectInformation.FileId.Vnode,
2439 VolumeCB->ObjectInformation.FileId.Unique,
2443 // Depending on the reason for invalidation then perform work on the node
2449 case AFS_INVALIDATE_DELETED:
2453 // Mark this volume as invalid
2456 SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
2458 SetFlag( VolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE);
2465 // Invalidate the volume root directory
2468 pCurrentObject = &VolumeCB->ObjectInformation;
2470 if ( pCurrentObject )
2473 lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
2475 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2476 AFS_TRACE_LEVEL_VERBOSE,
2477 "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2481 AFSInvalidateObject( &pCurrentObject,
2484 lCount = InterlockedDecrement( &pCurrentObject->ObjectReferenceCount);
2486 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2487 AFS_TRACE_LEVEL_VERBOSE,
2488 "AFSInvalidateVolumeObjects Decrement count on object %08lX Cnt %d\n",
2494 // Apply invalidation to all other volume objects
2497 AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2500 pCurrentObject = VolumeCB->ObjectInfoListHead;
2502 if ( pCurrentObject)
2506 // Reference the node so it won't be torn down
2509 lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
2511 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2512 AFS_TRACE_LEVEL_VERBOSE,
2513 "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2518 while( pCurrentObject != NULL)
2521 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2527 // Reference the node so it won't be torn down
2530 lCount = InterlockedIncrement( &pNextObject->ObjectReferenceCount);
2532 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2533 AFS_TRACE_LEVEL_VERBOSE,
2534 "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2539 AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2541 AFSInvalidateObject( &pCurrentObject,
2544 if ( pCurrentObject )
2547 lCount = InterlockedDecrement( &pCurrentObject->ObjectReferenceCount);
2549 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2550 AFS_TRACE_LEVEL_VERBOSE,
2551 "AFSInvalidateVolumeObjects Decrement count on object %08lX Cnt %d\n",
2556 AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2559 pCurrentObject = pNextObject;
2562 AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2569 AFSInvalidateAllVolumes( VOID)
2571 AFSVolumeCB *pVolumeCB = NULL;
2572 AFSVolumeCB *pNextVolumeCB = NULL;
2573 AFSDeviceExt *pRDRDeviceExt = NULL;
2576 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2578 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2579 AFS_TRACE_LEVEL_VERBOSE,
2580 "AFSInvalidateAllVolumes Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
2581 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2582 PsGetCurrentThread());
2584 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2587 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
2592 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2593 AFS_TRACE_LEVEL_VERBOSE,
2594 "AFSInvalidateAllVolumes Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
2595 pVolumeCB->ObjectInfoTree.TreeLock,
2596 PsGetCurrentThread());
2598 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2601 while( pVolumeCB != NULL)
2604 pNextVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2609 lCount = InterlockedIncrement( &pNextVolumeCB->VolumeReferenceCount);
2612 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2614 // do I need to hold the volume lock here?
2616 AFSInvalidateVolume( pVolumeCB, AFS_INVALIDATE_EXPIRED);
2618 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2621 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2623 pVolumeCB = pNextVolumeCB;
2626 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2630 AFSVerifyEntry( IN GUID *AuthGroup,
2631 IN AFSDirectoryCB *DirEntry)
2634 NTSTATUS ntStatus = STATUS_SUCCESS;
2635 AFSDirEnumEntry *pDirEnumEntry = NULL;
2636 AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
2637 IO_STATUS_BLOCK stIoStatus;
2642 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2643 AFS_TRACE_LEVEL_VERBOSE_2,
2644 "AFSVerifyEntry Verifying entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2645 &DirEntry->NameInformation.FileName,
2646 pObjectInfo->FileId.Cell,
2647 pObjectInfo->FileId.Volume,
2648 pObjectInfo->FileId.Vnode,
2649 pObjectInfo->FileId.Unique);
2651 ntStatus = AFSEvaluateTargetByID( pObjectInfo,
2656 if( !NT_SUCCESS( ntStatus))
2659 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2660 AFS_TRACE_LEVEL_ERROR,
2661 "AFSValidateEntry Evaluate Target failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2662 &DirEntry->NameInformation.FileName,
2663 pObjectInfo->FileId.Cell,
2664 pObjectInfo->FileId.Volume,
2665 pObjectInfo->FileId.Vnode,
2666 pObjectInfo->FileId.Unique,
2669 try_return( ntStatus);
2673 // Check the data version of the file
2676 if( pObjectInfo->DataVersion.QuadPart == pDirEnumEntry->DataVersion.QuadPart &&
2677 !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2680 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2681 AFS_TRACE_LEVEL_VERBOSE,
2682 "AFSVerifyEntry No DV change %I64X for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2683 pObjectInfo->DataVersion.QuadPart,
2684 &DirEntry->NameInformation.FileName,
2685 pObjectInfo->FileId.Cell,
2686 pObjectInfo->FileId.Volume,
2687 pObjectInfo->FileId.Vnode,
2688 pObjectInfo->FileId.Unique);
2691 // We are ok, just get out
2694 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2696 try_return( ntStatus = STATUS_SUCCESS);
2700 // New data version so we will need to process the node based on the type
2703 switch( pDirEnumEntry->FileType)
2706 case AFS_FILE_TYPE_MOUNTPOINT:
2710 // For a mount point we need to ensure the target is the same
2713 if( !AFSIsEqualFID( &pObjectInfo->TargetFileId,
2714 &pDirEnumEntry->TargetFileId))
2720 // Update the metadata for the entry
2723 ntStatus = AFSUpdateMetaData( DirEntry,
2726 if( NT_SUCCESS( ntStatus))
2729 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2735 case AFS_FILE_TYPE_SYMLINK:
2738 ASSERT( pDirEnumEntry->TargetNameLength > 0);
2741 // Update the metadata for the entry
2744 ntStatus = AFSUpdateMetaData( DirEntry,
2747 if( NT_SUCCESS( ntStatus))
2750 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2756 case AFS_FILE_TYPE_FILE:
2758 FILE_OBJECT * pCCFileObject = NULL;
2759 BOOLEAN bPurgeExtents = FALSE;
2761 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2763 bPurgeExtents = TRUE;
2765 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2766 AFS_TRACE_LEVEL_VERBOSE,
2767 "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2768 &DirEntry->NameInformation.FileName,
2769 pObjectInfo->FileId.Cell,
2770 pObjectInfo->FileId.Volume,
2771 pObjectInfo->FileId.Vnode,
2772 pObjectInfo->FileId.Unique);
2774 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
2778 // Update the metadata for the entry
2781 ntStatus = AFSUpdateMetaData( DirEntry,
2784 if( !NT_SUCCESS( ntStatus))
2787 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2788 AFS_TRACE_LEVEL_ERROR,
2789 "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
2790 &DirEntry->NameInformation.FileName,
2791 pObjectInfo->FileId.Cell,
2792 pObjectInfo->FileId.Volume,
2793 pObjectInfo->FileId.Vnode,
2794 pObjectInfo->FileId.Unique,
2800 if( pObjectInfo->Fcb != NULL)
2803 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2804 AFS_TRACE_LEVEL_VERBOSE,
2805 "AFSVerifyEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2806 &DirEntry->NameInformation.FileName,
2807 pObjectInfo->FileId.Cell,
2808 pObjectInfo->FileId.Volume,
2809 pObjectInfo->FileId.Vnode,
2810 pObjectInfo->FileId.Unique);
2812 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
2818 CcFlushCache( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2823 if( !NT_SUCCESS( stIoStatus.Status))
2826 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2827 AFS_TRACE_LEVEL_ERROR,
2828 "AFSVerifyEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
2829 &DirEntry->NameInformation.FileName,
2830 pObjectInfo->FileId.Cell,
2831 pObjectInfo->FileId.Volume,
2832 pObjectInfo->FileId.Vnode,
2833 pObjectInfo->FileId.Unique,
2835 stIoStatus.Information);
2837 ntStatus = stIoStatus.Status;
2843 CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2849 __except( EXCEPTION_EXECUTE_HANDLER)
2851 ntStatus = GetExceptionCode();
2853 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2854 AFS_TRACE_LEVEL_ERROR,
2855 "AFSVerifyEntry CcFlushCache or CcPurgeCacheSection Exception %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2856 &DirEntry->NameInformation.FileName,
2857 pObjectInfo->FileId.Cell,
2858 pObjectInfo->FileId.Volume,
2859 pObjectInfo->FileId.Vnode,
2860 pObjectInfo->FileId.Unique,
2864 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
2868 AFSFlushExtents( pObjectInfo->Fcb,
2873 // Reacquire the Fcb to purge the cache
2876 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2877 AFS_TRACE_LEVEL_VERBOSE,
2878 "AFSVerifyEntry Acquiring Fcb lock %08lX EXCL %08lX\n",
2879 &pObjectInfo->Fcb->NPFcb->Resource,
2880 PsGetCurrentThread());
2882 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
2886 // Update file sizes
2889 pObjectInfo->Fcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart;
2890 pObjectInfo->Fcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart;
2891 pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
2893 pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
2895 if ( pCCFileObject != NULL)
2897 CcSetFileSizes( pCCFileObject,
2898 (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
2901 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
2905 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2906 AFS_TRACE_LEVEL_WARNING,
2907 "AFSValidateEntry Fcb NULL %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2908 &DirEntry->NameInformation.FileName,
2909 pObjectInfo->FileId.Cell,
2910 pObjectInfo->FileId.Volume,
2911 pObjectInfo->FileId.Vnode,
2912 pObjectInfo->FileId.Unique);
2915 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2920 case AFS_FILE_TYPE_DIRECTORY:
2923 AFSFcb *pCurrentFcb = NULL;
2924 AFSDirectoryCB *pCurrentDirEntry = NULL;
2927 // For a directory or root entry flush the content of
2928 // the directory enumeration.
2931 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
2934 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2935 AFS_TRACE_LEVEL_VERBOSE_2,
2936 "AFSVerifyEntry Validating directory content for entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2937 &DirEntry->NameInformation.FileName,
2938 pObjectInfo->FileId.Cell,
2939 pObjectInfo->FileId.Volume,
2940 pObjectInfo->FileId.Vnode,
2941 pObjectInfo->FileId.Unique);
2943 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2946 ntStatus = AFSValidateDirectoryCache( pObjectInfo,
2949 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2951 if ( !NT_SUCCESS( ntStatus))
2954 try_return( ntStatus);
2959 // Update the metadata for the entry
2962 ntStatus = AFSUpdateMetaData( DirEntry,
2965 if( NT_SUCCESS( ntStatus))
2968 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2974 case AFS_FILE_TYPE_DFSLINK:
2977 UNICODE_STRING uniTargetName;
2980 // For a DFS link need to check the target name has not changed
2983 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
2985 uniTargetName.MaximumLength = uniTargetName.Length;
2987 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
2989 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
2992 if( DirEntry->NameInformation.TargetName.Length == 0 ||
2993 RtlCompareUnicodeString( &uniTargetName,
2994 &DirEntry->NameInformation.TargetName,
2999 // Update the target name
3002 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3004 uniTargetName.Buffer,
3005 uniTargetName.Length);
3007 if( !NT_SUCCESS( ntStatus))
3010 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3016 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3019 // Update the metadata for the entry
3022 ntStatus = AFSUpdateMetaData( DirEntry,
3025 if( NT_SUCCESS( ntStatus))
3028 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3036 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3037 AFS_TRACE_LEVEL_WARNING,
3038 "AFSVerifyEntry Attempt to verify node of type %d %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3039 pObjectInfo->FileType,
3040 &DirEntry->NameInformation.FileName,
3041 pObjectInfo->FileId.Cell,
3042 pObjectInfo->FileId.Volume,
3043 pObjectInfo->FileId.Vnode,
3044 pObjectInfo->FileId.Unique);
3051 if( pDirEnumEntry != NULL)
3054 AFSExFreePool( pDirEnumEntry);
3062 AFSSetVolumeState( IN AFSVolumeStatusCB *VolumeStatus)
3065 NTSTATUS ntStatus = STATUS_SUCCESS;
3066 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
3067 ULONGLONG ullIndex = 0;
3068 AFSVolumeCB *pVolumeCB = NULL;
3069 AFSFcb *pFcb = NULL;
3070 AFSObjectInfoCB *pCurrentObject = NULL;
3076 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3077 AFS_TRACE_LEVEL_VERBOSE,
3078 "AFSSetVolumeState Marking volume state %d Volume Cell %08lX Volume %08lX\n",
3079 VolumeStatus->Online,
3080 VolumeStatus->FileID.Cell,
3081 VolumeStatus->FileID.Volume);
3084 // Need to locate the Fcb for the directory to purge
3087 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3088 AFS_TRACE_LEVEL_VERBOSE,
3089 "AFSSetVolumeState Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
3090 &pDevExt->Specific.RDR.VolumeTreeLock,
3091 PsGetCurrentThread());
3093 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
3096 // Locate the volume node
3099 ullIndex = AFSCreateHighIndex( &VolumeStatus->FileID);
3101 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
3103 (AFSBTreeEntry **)&pVolumeCB);
3105 if( pVolumeCB != NULL)
3108 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
3110 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3113 // Set the volume state accordingly
3116 if( VolumeStatus->Online)
3119 InterlockedAnd( (LONG *)&(pVolumeCB->Flags), ~AFS_VOLUME_FLAGS_OFFLINE);
3124 InterlockedOr( (LONG *)&(pVolumeCB->Flags), AFS_VOLUME_FLAGS_OFFLINE);
3127 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
3130 pCurrentObject = pVolumeCB->ObjectInfoListHead;;
3132 while( pCurrentObject != NULL)
3135 if( VolumeStatus->Online)
3138 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
3140 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
3142 pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
3147 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
3150 pFcb = pCurrentObject->Fcb;
3153 !(VolumeStatus->Online) &&
3154 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
3157 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3158 AFS_TRACE_LEVEL_ERROR,
3159 "AFSSetVolumeState Marking volume offline and canceling extents Volume Cell %08lX Volume %08lX\n",
3160 VolumeStatus->FileID.Cell,
3161 VolumeStatus->FileID.Volume);
3164 // Clear out the extents
3167 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3168 AFS_TRACE_LEVEL_VERBOSE,
3169 "AFSSetVolumeState Acquiring Fcb extents lock %08lX EXCL %08lX\n",
3170 &pFcb->NPFcb->Specific.File.ExtentsResource,
3171 PsGetCurrentThread());
3173 AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
3176 pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
3178 KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
3182 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3183 AFS_TRACE_LEVEL_VERBOSE,
3184 "AFSSetVolumeState Releasing Fcb extents lock %08lX EXCL %08lX\n",
3185 &pFcb->NPFcb->Specific.File.ExtentsResource,
3186 PsGetCurrentThread());
3188 AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
3191 // And get rid of them (note this involves waiting
3192 // for any writes or reads to the cache to complete)
3195 (VOID) AFSTearDownFcbExtents( pFcb,
3199 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
3202 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
3204 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
3209 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3217 AFSSetNetworkState( IN AFSNetworkStatusCB *NetworkStatus)
3220 NTSTATUS ntStatus = STATUS_SUCCESS;
3225 if( AFSGlobalRoot == NULL)
3228 try_return( ntStatus);
3231 AFSAcquireExcl( AFSGlobalRoot->VolumeLock,
3235 // Set the network state according to the information
3238 if( NetworkStatus->Online)
3241 ClearFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3246 SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3249 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3260 AFSValidateDirectoryCache( IN AFSObjectInfoCB *ObjectInfo,
3264 NTSTATUS ntStatus = STATUS_SUCCESS;
3265 BOOLEAN bAcquiredLock = FALSE;
3266 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
3267 AFSFcb *pFcb = NULL;
3272 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3273 AFS_TRACE_LEVEL_VERBOSE,
3274 "AFSValidateDirectoryCache Validating content for FID %08lX-%08lX-%08lX-%08lX\n",
3275 ObjectInfo->FileId.Cell,
3276 ObjectInfo->FileId.Volume,
3277 ObjectInfo->FileId.Vnode,
3278 ObjectInfo->FileId.Unique);
3280 if( !ExIsResourceAcquiredLite( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock))
3283 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3284 AFS_TRACE_LEVEL_VERBOSE,
3285 "AFSValidateDirectoryCache Acquiring DirectoryNodeHdr.TreeLock lock %08lX EXCL %08lX\n",
3286 ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3287 PsGetCurrentThread());
3289 AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3292 bAcquiredLock = TRUE;
3296 // Check for inconsistency between DirectoryNodeList and DirectoryNodeCount
3299 if ( ObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL &&
3300 ObjectInfo->Specific.Directory.DirectoryNodeCount > 0)
3303 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3304 AFS_TRACE_LEVEL_ERROR,
3305 "AFSValidateDirectoryCache Empty Node List but Non-Zero Node Count %08lX for dir FID %08lX-%08lX-%08lX-%08lX\n",
3306 ObjectInfo->Specific.Directory.DirectoryNodeCount,
3307 ObjectInfo->FileId.Cell,
3308 ObjectInfo->FileId.Volume,
3309 ObjectInfo->FileId.Vnode,
3310 ObjectInfo->FileId.Unique);
3314 // Reset the directory list information by clearing all valid entries
3317 pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3319 while( pCurrentDirEntry != NULL)
3322 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3324 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
3328 // If this entry has been deleted then process it here
3331 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
3332 pCurrentDirEntry->OpenReferenceCount == 0)
3335 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3336 AFS_TRACE_LEVEL_VERBOSE,
3337 "AFSValidateDirectoryCache Deleting dir entry %p name %wZ\n",
3339 &pCurrentDirEntry->NameInformation.FileName);
3341 AFSDeleteDirEntry( ObjectInfo,
3347 ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID);
3349 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3350 AFS_TRACE_LEVEL_VERBOSE,
3351 "AFSValidateDirectoryCache Clear VALID flag on DE %p Reference count %08lX\n",
3353 pCurrentDirEntry->OpenReferenceCount);
3356 // We pull the short name from the parent tree since it could change below
3359 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
3362 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3363 AFS_TRACE_LEVEL_VERBOSE,
3364 "AFSValidateDirectoryCache Removing DE %p (%08lX) from shortname tree for %wZ\n",
3366 pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3367 &pCurrentDirEntry->NameInformation.FileName);
3369 AFSRemoveShortNameDirEntry( &ObjectInfo->Specific.Directory.ShortNameTree,
3372 ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3377 pCurrentDirEntry = pNextDirEntry;
3381 // Reget the directory contents
3384 ntStatus = AFSVerifyDirectoryContent( ObjectInfo,
3387 if ( !NT_SUCCESS( ntStatus))
3389 try_return( ntStatus);
3393 // Now start again and tear down any entries not valid
3396 pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3398 while( pCurrentDirEntry != NULL)
3401 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3403 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID))
3406 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME) &&
3407 pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex > 0)
3410 if( ObjectInfo->Specific.Directory.ShortNameTree == NULL)
3413 ObjectInfo->Specific.Directory.ShortNameTree = pCurrentDirEntry;
3415 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3416 AFS_TRACE_LEVEL_VERBOSE,
3417 "AFSValidateDirectoryCache Insert DE %p to head of shortname tree for %wZ\n",
3419 &pCurrentDirEntry->NameInformation.FileName);
3421 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3426 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfo->Specific.Directory.ShortNameTree,
3429 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3430 AFS_TRACE_LEVEL_VERBOSE,
3431 "AFSValidateDirectoryCache Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
3433 pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3434 &pCurrentDirEntry->NameInformation.FileName);
3438 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3440 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3441 AFS_TRACE_LEVEL_VERBOSE,
3442 "AFSValidateDirectoryCache Insert DE %p to shortname tree for %wZ\n",
3444 &pCurrentDirEntry->NameInformation.FileName);
3449 pCurrentDirEntry = pNextDirEntry;
3454 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3455 AFS_TRACE_LEVEL_VERBOSE,
3456 "AFSValidateDirectoryCache Processing INVALID DE %p Reference count %08lX\n",
3458 pCurrentDirEntry->OpenReferenceCount);
3460 if( pCurrentDirEntry->OpenReferenceCount == 0)
3463 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3464 AFS_TRACE_LEVEL_VERBOSE,
3465 "AFSValidateDirectoryCache Deleting dir entry %wZ from parent FID %08lX-%08lX-%08lX-%08lX\n",
3466 &pCurrentDirEntry->NameInformation.FileName,
3467 ObjectInfo->FileId.Cell,
3468 ObjectInfo->FileId.Volume,
3469 ObjectInfo->FileId.Vnode,
3470 ObjectInfo->FileId.Unique);
3472 AFSDeleteDirEntry( ObjectInfo,
3478 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3479 AFS_TRACE_LEVEL_VERBOSE,
3480 "AFSValidateDirectoryCache Setting dir entry %p Name %wZ DELETED in parent FID %08lX-%08lX-%08lX-%08lX\n",
3482 &pCurrentDirEntry->NameInformation.FileName,
3483 ObjectInfo->FileId.Cell,
3484 ObjectInfo->FileId.Volume,
3485 ObjectInfo->FileId.Vnode,
3486 ObjectInfo->FileId.Unique);
3488 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
3490 AFSRemoveNameEntry( ObjectInfo,
3494 pCurrentDirEntry = pNextDirEntry;
3498 if( !AFSValidateDirList( ObjectInfo))
3501 AFSPrint("AFSValidateDirectoryCache Invalid count ...\n");
3510 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3518 AFSIsVolumeFID( IN AFSFileID *FileID)
3521 BOOLEAN bIsVolume = FALSE;
3523 if( FileID->Vnode == 1 &&
3524 FileID->Unique == 1)
3534 AFSIsFinalNode( IN AFSFcb *Fcb)
3537 BOOLEAN bIsFinalNode = FALSE;
3539 if( Fcb->Header.NodeTypeCode == AFS_ROOT_FCB ||
3540 Fcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB ||
3541 Fcb->Header.NodeTypeCode == AFS_FILE_FCB ||
3542 Fcb->Header.NodeTypeCode == AFS_DFS_LINK_FCB ||
3543 Fcb->Header.NodeTypeCode == AFS_INVALID_FCB )
3546 bIsFinalNode = TRUE;
3551 ASSERT( Fcb->Header.NodeTypeCode == AFS_MOUNT_POINT_FCB ||
3552 Fcb->Header.NodeTypeCode == AFS_SYMBOLIC_LINK_FCB);
3555 return bIsFinalNode;
3559 AFSUpdateMetaData( IN AFSDirectoryCB *DirEntry,
3560 IN AFSDirEnumEntry *DirEnumEntry)
3563 NTSTATUS ntStatus = STATUS_SUCCESS;
3564 UNICODE_STRING uniTargetName;
3565 AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
3570 pObjectInfo->TargetFileId = DirEnumEntry->TargetFileId;
3572 pObjectInfo->Expiration = DirEnumEntry->Expiration;
3574 pObjectInfo->DataVersion = DirEnumEntry->DataVersion;
3576 pObjectInfo->FileType = DirEnumEntry->FileType;
3578 pObjectInfo->CreationTime = DirEnumEntry->CreationTime;
3580 pObjectInfo->LastAccessTime = DirEnumEntry->LastAccessTime;
3582 pObjectInfo->LastWriteTime = DirEnumEntry->LastWriteTime;
3584 pObjectInfo->ChangeTime = DirEnumEntry->ChangeTime;
3586 pObjectInfo->EndOfFile = DirEnumEntry->EndOfFile;
3588 pObjectInfo->AllocationSize = DirEnumEntry->AllocationSize;
3590 pObjectInfo->FileAttributes = DirEnumEntry->FileAttributes;
3592 if( pObjectInfo->FileType == AFS_FILE_TYPE_MOUNTPOINT)
3595 pObjectInfo->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
3598 if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK ||
3599 pObjectInfo->FileType == AFS_FILE_TYPE_DFSLINK)
3602 pObjectInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
3605 pObjectInfo->EaSize = DirEnumEntry->EaSize;
3607 pObjectInfo->Links = DirEnumEntry->Links;
3609 if( DirEnumEntry->TargetNameLength > 0)
3613 // Update the target name information if needed
3616 uniTargetName.Length = (USHORT)DirEnumEntry->TargetNameLength;
3618 uniTargetName.MaximumLength = uniTargetName.Length;
3620 uniTargetName.Buffer = (WCHAR *)((char *)DirEnumEntry + DirEnumEntry->TargetNameOffset);
3622 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3625 if( DirEntry->NameInformation.TargetName.Length == 0 ||
3626 RtlCompareUnicodeString( &uniTargetName,
3627 &DirEntry->NameInformation.TargetName,
3632 // Update the target name
3635 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3637 uniTargetName.Buffer,
3638 uniTargetName.Length);
3640 if( !NT_SUCCESS( ntStatus))
3643 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3645 try_return( ntStatus);
3649 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3651 else if( DirEntry->NameInformation.TargetName.Length > 0)
3654 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3657 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER) &&
3658 DirEntry->NameInformation.TargetName.Buffer != NULL)
3660 AFSExFreePool( DirEntry->NameInformation.TargetName.Buffer);
3663 ClearFlag( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER);
3665 DirEntry->NameInformation.TargetName.Length = 0;
3666 DirEntry->NameInformation.TargetName.MaximumLength = 0;
3667 DirEntry->NameInformation.TargetName.Buffer = NULL;
3669 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3681 AFSValidateEntry( IN AFSDirectoryCB *DirEntry,
3683 IN BOOLEAN PurgeContent,
3684 IN BOOLEAN FastCall)
3687 NTSTATUS ntStatus = STATUS_SUCCESS;
3688 LARGE_INTEGER liSystemTime;
3689 AFSDirEnumEntry *pDirEnumEntry = NULL;
3690 AFSFcb *pCurrentFcb = NULL;
3691 BOOLEAN bReleaseFcb = FALSE;
3692 AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
3698 // If we have an Fcb hanging off the directory entry then be sure to acquire the locks in the
3702 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3703 AFS_TRACE_LEVEL_VERBOSE_2,
3704 "AFSValidateEntry Validating entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3705 &DirEntry->NameInformation.FileName,
3706 pObjectInfo->FileId.Cell,
3707 pObjectInfo->FileId.Volume,
3708 pObjectInfo->FileId.Vnode,
3709 pObjectInfo->FileId.Unique);
3712 // If this is a fake node then bail since the service knows nothing about it
3715 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_FAKE))
3718 try_return( ntStatus);
3722 pObjectInfo->Fcb != NULL)
3725 pCurrentFcb = pObjectInfo->Fcb;
3727 if( !ExIsResourceAcquiredLite( &pCurrentFcb->NPFcb->Resource))
3730 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3731 AFS_TRACE_LEVEL_VERBOSE,
3732 "AFSValidateEntry Acquiring Fcb lock %08lX EXCL %08lX\n",
3733 &pCurrentFcb->NPFcb->Resource,
3734 PsGetCurrentThread());
3736 AFSAcquireExcl( &pCurrentFcb->NPFcb->Resource,
3744 // This routine ensures that the current entry is valid by:
3746 // 1) Checking that the expiration time is non-zero and after where we
3750 KeQuerySystemTime( &liSystemTime);
3752 if( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) &&
3753 !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
3754 !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA) &&
3755 pObjectInfo->Expiration.QuadPart >= liSystemTime.QuadPart)
3758 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3759 AFS_TRACE_LEVEL_VERBOSE_2,
3760 "AFSValidateEntry Directory entry %wZ FID %08lX-%08lX-%08lX-%08lX VALID\n",
3761 &DirEntry->NameInformation.FileName,
3762 pObjectInfo->FileId.Cell,
3763 pObjectInfo->FileId.Volume,
3764 pObjectInfo->FileId.Vnode,
3765 pObjectInfo->FileId.Unique);
3767 try_return( ntStatus);
3771 // This node requires updating
3774 ntStatus = AFSEvaluateTargetByID( pObjectInfo,
3779 if( !NT_SUCCESS( ntStatus))
3782 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3783 AFS_TRACE_LEVEL_ERROR,
3784 "AFSValidateEntry Failed to evaluate entry FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3786 &DirEntry->NameInformation.FileName,
3787 pObjectInfo->FileId.Cell,
3788 pObjectInfo->FileId.Volume,
3789 pObjectInfo->FileId.Vnode,
3790 pObjectInfo->FileId.Unique,
3794 // Failed validation of node so return access-denied
3797 try_return( ntStatus);
3800 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3801 AFS_TRACE_LEVEL_VERBOSE,
3802 "AFSValidateEntry Validating entry FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX DV %I64X returned DV %I64X FT %d\n",
3804 &DirEntry->NameInformation.FileName,
3805 pObjectInfo->FileId.Cell,
3806 pObjectInfo->FileId.Volume,
3807 pObjectInfo->FileId.Vnode,
3808 pObjectInfo->FileId.Unique,
3809 pObjectInfo->DataVersion.QuadPart,
3810 pDirEnumEntry->DataVersion.QuadPart,
3811 pDirEnumEntry->FileType);
3815 // Based on the file type, process the node
3818 switch( pDirEnumEntry->FileType)
3821 case AFS_FILE_TYPE_MOUNTPOINT:
3825 // Update the metadata for the entry
3828 ntStatus = AFSUpdateMetaData( DirEntry,
3831 if( NT_SUCCESS( ntStatus))
3834 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
3840 case AFS_FILE_TYPE_SYMLINK:
3841 case AFS_FILE_TYPE_DFSLINK:
3845 // Update the metadata for the entry
3848 ntStatus = AFSUpdateMetaData( DirEntry,
3851 if( NT_SUCCESS( ntStatus))
3854 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
3860 case AFS_FILE_TYPE_FILE:
3864 // For a file where the data version has become invalid we need to
3865 // fail any current extent requests and purge the cache for the file
3866 // Can't hold the Fcb resource while doing this
3869 if( pCurrentFcb != NULL &&
3870 (pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart ||
3871 BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA)))
3874 IO_STATUS_BLOCK stIoStatus;
3875 BOOLEAN bPurgeExtents = FALSE;
3877 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3878 AFS_TRACE_LEVEL_VERBOSE_2,
3879 "AFSValidateEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3880 &DirEntry->NameInformation.FileName,
3881 pObjectInfo->FileId.Cell,
3882 pObjectInfo->FileId.Volume,
3883 pObjectInfo->FileId.Vnode,
3884 pObjectInfo->FileId.Unique);
3886 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
3888 bPurgeExtents = TRUE;
3890 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3891 AFS_TRACE_LEVEL_VERBOSE,
3892 "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3893 &DirEntry->NameInformation.FileName,
3894 pObjectInfo->FileId.Cell,
3895 pObjectInfo->FileId.Volume,
3896 pObjectInfo->FileId.Vnode,
3897 pObjectInfo->FileId.Unique);
3899 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
3905 CcFlushCache( &pCurrentFcb->NPFcb->SectionObjectPointers,
3910 if( !NT_SUCCESS( stIoStatus.Status))
3913 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
3914 AFS_TRACE_LEVEL_ERROR,
3915 "AFSValidateEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
3916 &DirEntry->NameInformation.FileName,
3917 pObjectInfo->FileId.Cell,
3918 pObjectInfo->FileId.Volume,
3919 pObjectInfo->FileId.Vnode,
3920 pObjectInfo->FileId.Unique,
3922 stIoStatus.Information);
3924 ntStatus = stIoStatus.Status;
3930 CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
3936 __except( EXCEPTION_EXECUTE_HANDLER)
3938 ntStatus = GetExceptionCode();
3940 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
3941 AFS_TRACE_LEVEL_ERROR,
3942 "AFSValidateEntry CcFlushCache or CcPurgeCacheSection exception %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
3943 &DirEntry->NameInformation.FileName,
3944 pObjectInfo->FileId.Cell,
3945 pObjectInfo->FileId.Volume,
3946 pObjectInfo->FileId.Vnode,
3947 pObjectInfo->FileId.Unique,
3952 AFSReleaseResource( &pCurrentFcb->NPFcb->Resource);
3956 AFSFlushExtents( pCurrentFcb,
3961 // Reacquire the Fcb to purge the cache
3964 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3965 AFS_TRACE_LEVEL_VERBOSE,
3966 "AFSValidateEntry Acquiring Fcb lock %08lX EXCL %08lX\n",
3967 &pCurrentFcb->NPFcb->Resource,
3968 PsGetCurrentThread());
3970 AFSAcquireExcl( &pCurrentFcb->NPFcb->Resource,
3975 // Update the metadata for the entry
3978 ntStatus = AFSUpdateMetaData( DirEntry,
3981 if( !NT_SUCCESS( ntStatus))
3984 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3985 AFS_TRACE_LEVEL_ERROR,
3986 "AFSValidateEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
3987 &DirEntry->NameInformation.FileName,
3988 pObjectInfo->FileId.Cell,
3989 pObjectInfo->FileId.Volume,
3990 pObjectInfo->FileId.Vnode,
3991 pObjectInfo->FileId.Unique,
3997 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
4000 // Update file sizes
4003 if( pObjectInfo->Fcb != NULL)
4005 FILE_OBJECT *pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
4007 pObjectInfo->Fcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart;
4008 pObjectInfo->Fcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart;
4009 pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
4011 if ( pCCFileObject != NULL)
4013 CcSetFileSizes( pCCFileObject,
4014 (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
4021 case AFS_FILE_TYPE_DIRECTORY:
4024 AFSDirectoryCB *pCurrentDirEntry = NULL;
4026 if( pCurrentFcb != NULL &&
4027 pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
4031 // For a directory or root entry flush the content of
4032 // the directory enumeration.
4035 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4036 AFS_TRACE_LEVEL_VERBOSE,
4037 "AFSValidateEntry Acquiring DirectoryNodeHdr.TreeLock lock %08lX EXCL %08lX\n",
4038 pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
4039 PsGetCurrentThread());
4041 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
4044 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4045 AFS_TRACE_LEVEL_VERBOSE_2,
4046 "AFSValidateEntry Validating directory content for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4047 &DirEntry->NameInformation.FileName,
4048 pObjectInfo->FileId.Cell,
4049 pObjectInfo->FileId.Volume,
4050 pObjectInfo->FileId.Vnode,
4051 pObjectInfo->FileId.Unique);
4053 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
4056 AFSValidateDirectoryCache( pCurrentFcb->ObjectInformation,
4059 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
4062 if( !NT_SUCCESS( ntStatus))
4065 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4066 AFS_TRACE_LEVEL_ERROR,
4067 "AFSValidateEntry Failed to re-enumerate %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4068 &DirEntry->NameInformation.FileName,
4069 pObjectInfo->FileId.Cell,
4070 pObjectInfo->FileId.Volume,
4071 pObjectInfo->FileId.Vnode,
4072 pObjectInfo->FileId.Unique,
4080 // Update the metadata for the entry
4083 ntStatus = AFSUpdateMetaData( DirEntry,
4086 if( NT_SUCCESS( ntStatus))
4089 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
4097 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4098 AFS_TRACE_LEVEL_WARNING,
4099 "AFSValidateEntry Attempt to verify node of type %d FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4100 pObjectInfo->FileType,
4102 &DirEntry->NameInformation.FileName,
4103 pObjectInfo->FileId.Cell,
4104 pObjectInfo->FileId.Volume,
4105 pObjectInfo->FileId.Vnode,
4106 pObjectInfo->FileId.Unique);
4116 AFSReleaseResource( &pCurrentFcb->NPFcb->Resource);
4119 if( pDirEnumEntry != NULL)
4122 AFSExFreePool( pDirEnumEntry);
4130 AFSInitializeSpecialShareNameList()
4133 NTSTATUS ntStatus = STATUS_SUCCESS;
4134 AFSDirectoryCB *pDirNode = NULL, *pLastDirNode = NULL;
4135 AFSObjectInfoCB *pObjectInfoCB = NULL;
4136 UNICODE_STRING uniShareName;
4137 ULONG ulEntryLength = 0;
4138 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
4143 RtlInitUnicodeString( &uniShareName,
4146 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
4149 if( pObjectInfoCB == NULL)
4152 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4155 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4156 AFS_TRACE_LEVEL_VERBOSE,
4157 "AFSInitializeSpecialShareNameList (srvsvc) Initializing count (1) on object %08lX\n",
4160 pObjectInfoCB->ObjectReferenceCount = 1;
4162 pObjectInfoCB->FileType = AFS_FILE_TYPE_SPECIAL_SHARE_NAME;
4164 ulEntryLength = sizeof( AFSDirectoryCB) +
4165 uniShareName.Length;
4167 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
4171 if( pDirNode == NULL)
4174 AFSDeleteObjectInfo( pObjectInfoCB);
4176 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4179 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
4180 sizeof( AFSNonPagedDirectoryCB),
4181 AFS_DIR_ENTRY_NP_TAG);
4183 if( pNonPagedDirEntry == NULL)
4186 ExFreePool( pDirNode);
4188 AFSDeleteObjectInfo( pObjectInfoCB);
4190 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4193 RtlZeroMemory( pDirNode,
4196 RtlZeroMemory( pNonPagedDirEntry,
4197 sizeof( AFSNonPagedDirectoryCB));
4199 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
4201 pDirNode->NonPaged = pNonPagedDirEntry;
4203 pDirNode->ObjectInformation = pObjectInfoCB;
4209 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_SERVER_SERVICE);
4211 pDirNode->NameInformation.FileName.Length = uniShareName.Length;
4213 pDirNode->NameInformation.FileName.MaximumLength = uniShareName.Length;
4215 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
4217 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
4218 uniShareName.Buffer,
4219 pDirNode->NameInformation.FileName.Length);
4221 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
4224 AFSSpecialShareNames = pDirNode;
4226 pLastDirNode = pDirNode;
4228 RtlInitUnicodeString( &uniShareName,
4231 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
4234 if( pObjectInfoCB == NULL)
4237 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4240 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4241 AFS_TRACE_LEVEL_VERBOSE,
4242 "AFSInitializeSpecialShareNameList (wkssvc) Initializing count (1) on object %08lX\n",
4245 pObjectInfoCB->ObjectReferenceCount = 1;
4247 pObjectInfoCB->FileType = AFS_FILE_TYPE_SPECIAL_SHARE_NAME;
4249 ulEntryLength = sizeof( AFSDirectoryCB) +
4250 uniShareName.Length;
4252 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
4256 if( pDirNode == NULL)
4259 AFSDeleteObjectInfo( pObjectInfoCB);
4261 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4264 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
4265 sizeof( AFSNonPagedDirectoryCB),
4266 AFS_DIR_ENTRY_NP_TAG);
4268 if( pNonPagedDirEntry == NULL)
4271 ExFreePool( pDirNode);
4273 AFSDeleteObjectInfo( pObjectInfoCB);
4275 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4278 RtlZeroMemory( pDirNode,
4281 RtlZeroMemory( pNonPagedDirEntry,
4282 sizeof( AFSNonPagedDirectoryCB));
4284 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
4286 pDirNode->NonPaged = pNonPagedDirEntry;
4288 pDirNode->ObjectInformation = pObjectInfoCB;
4294 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_WORKSTATION_SERVICE);
4296 pDirNode->NameInformation.FileName.Length = uniShareName.Length;
4298 pDirNode->NameInformation.FileName.MaximumLength = uniShareName.Length;
4300 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
4302 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
4303 uniShareName.Buffer,
4304 pDirNode->NameInformation.FileName.Length);
4306 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
4309 pLastDirNode->ListEntry.fLink = pDirNode;
4311 pDirNode->ListEntry.bLink = pLastDirNode;
4313 pLastDirNode = pDirNode;
4315 RtlInitUnicodeString( &uniShareName,
4318 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
4321 if( pObjectInfoCB == NULL)
4324 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4327 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4328 AFS_TRACE_LEVEL_VERBOSE,
4329 "AFSInitializeSpecialShareNameList (ipc$) Initializing count (1) on object %08lX\n",
4332 pObjectInfoCB->ObjectReferenceCount = 1;
4334 pObjectInfoCB->FileType = AFS_FILE_TYPE_SPECIAL_SHARE_NAME;
4336 ulEntryLength = sizeof( AFSDirectoryCB) +
4337 uniShareName.Length;
4339 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
4343 if( pDirNode == NULL)
4346 AFSDeleteObjectInfo( pObjectInfoCB);
4348 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4351 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
4352 sizeof( AFSNonPagedDirectoryCB),
4353 AFS_DIR_ENTRY_NP_TAG);
4355 if( pNonPagedDirEntry == NULL)
4358 ExFreePool( pDirNode);
4360 AFSDeleteObjectInfo( pObjectInfoCB);
4362 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4365 RtlZeroMemory( pDirNode,
4368 RtlZeroMemory( pNonPagedDirEntry,
4369 sizeof( AFSNonPagedDirectoryCB));
4371 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
4373 pDirNode->NonPaged = pNonPagedDirEntry;
4375 pDirNode->ObjectInformation = pObjectInfoCB;
4381 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_IPC);
4383 pDirNode->NameInformation.FileName.Length = uniShareName.Length;
4385 pDirNode->NameInformation.FileName.MaximumLength = uniShareName.Length;
4387 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
4389 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
4390 uniShareName.Buffer,
4391 pDirNode->NameInformation.FileName.Length);
4393 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
4396 pLastDirNode->ListEntry.fLink = pDirNode;
4398 pDirNode->ListEntry.bLink = pLastDirNode;
4402 if( !NT_SUCCESS( ntStatus))
4405 if( AFSSpecialShareNames != NULL)
4408 pDirNode = AFSSpecialShareNames;
4410 while( pDirNode != NULL)
4413 pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
4415 AFSDeleteObjectInfo( pDirNode->ObjectInformation);
4417 ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
4419 ExFreePool( pDirNode->NonPaged);
4421 ExFreePool( pDirNode);
4423 pDirNode = pLastDirNode;
4426 AFSSpecialShareNames = NULL;
4435 AFSGetSpecialShareNameEntry( IN UNICODE_STRING *ShareName,
4436 IN UNICODE_STRING *SecondaryName)
4439 AFSDirectoryCB *pDirectoryCB = NULL;
4440 ULONGLONG ullHash = 0;
4441 UNICODE_STRING uniFullShareName;
4447 // Build up the entire name here. We are guaranteed that if there is a
4448 // secondary name, it is pointing to a portion of the share name buffer
4451 if( SecondaryName->Length > 0 &&
4452 SecondaryName->Buffer != NULL)
4455 uniFullShareName = *SecondaryName;
4458 // The calling routine strips off the leading slash so add it back in
4461 uniFullShareName.Buffer--;
4462 uniFullShareName.Length += sizeof( WCHAR);
4463 uniFullShareName.MaximumLength += sizeof( WCHAR);
4466 // And the share name
4469 uniFullShareName.Buffer -= (ShareName->Length/sizeof( WCHAR));
4470 uniFullShareName.Length += ShareName->Length;
4471 uniFullShareName.MaximumLength += ShareName->Length;
4476 uniFullShareName = *ShareName;
4480 // Generate our hash value
4483 ullHash = AFSGenerateCRC( &uniFullShareName,
4487 // Loop through our special share names to see if this is one of them
4490 pDirectoryCB = AFSSpecialShareNames;
4492 while( pDirectoryCB != NULL)
4495 if( ullHash == pDirectoryCB->CaseInsensitiveTreeEntry.HashIndex)
4501 pDirectoryCB = (AFSDirectoryCB *)pDirectoryCB->ListEntry.fLink;
4505 return pDirectoryCB;
4509 AFSWaitOnQueuedFlushes( IN AFSFcb *Fcb)
4513 // Block on the queue flush event
4516 KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
4526 AFSWaitOnQueuedReleases()
4529 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
4532 // Block on the queue flush event
4535 KeWaitForSingleObject( &pRDRDeviceExt->Specific.RDR.QueuedReleaseExtentEvent,
4545 AFSIsEqualFID( IN AFSFileID *FileId1,
4546 IN AFSFileID *FileId2)
4549 BOOLEAN bIsEqual = FALSE;
4551 if( FileId1->Unique == FileId2->Unique &&
4552 FileId1->Vnode == FileId2->Vnode &&
4553 FileId1->Volume == FileId2->Volume &&
4554 FileId1->Cell == FileId2->Cell)
4564 AFSResetDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB)
4567 NTSTATUS ntStatus = STATUS_SUCCESS;
4568 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
4573 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
4576 // Reset the directory list information
4579 pCurrentDirEntry = ObjectInfoCB->Specific.Directory.DirectoryNodeListHead;
4581 while( pCurrentDirEntry != NULL)
4584 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
4586 if( pCurrentDirEntry->OpenReferenceCount == 0)
4589 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
4590 AFS_TRACE_LEVEL_VERBOSE,
4591 "AFSResetDirectoryContent Deleting dir entry %p for %wZ\n",
4593 &pCurrentDirEntry->NameInformation.FileName);
4595 AFSDeleteDirEntry( ObjectInfoCB,
4601 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
4602 AFS_TRACE_LEVEL_VERBOSE,
4603 "AFSResetDirectoryContent Setting DELETE flag in dir entry %p for %wZ\n",
4605 &pCurrentDirEntry->NameInformation.FileName);
4607 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
4609 AFSRemoveNameEntry( ObjectInfoCB,
4613 pCurrentDirEntry = pNextDirEntry;
4616 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = NULL;
4618 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = NULL;
4620 ObjectInfoCB->Specific.Directory.ShortNameTree = NULL;
4622 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = NULL;
4624 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = NULL;
4626 ObjectInfoCB->Specific.Directory.DirectoryNodeCount = 0;
4628 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
4629 AFS_TRACE_LEVEL_VERBOSE,
4630 "AFSResetDirectoryContent Reset count to 0 on parent FID %08lX-%08lX-%08lX-%08lX\n",
4631 ObjectInfoCB->FileId.Cell,
4632 ObjectInfoCB->FileId.Volume,
4633 ObjectInfoCB->FileId.Vnode,
4634 ObjectInfoCB->FileId.Unique);
4641 AFSEnumerateGlobalRoot( IN GUID *AuthGroup)
4644 NTSTATUS ntStatus = STATUS_SUCCESS;
4645 AFSDirectoryCB *pDirGlobalDirNode = NULL;
4646 UNICODE_STRING uniFullName;
4651 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4652 AFS_TRACE_LEVEL_VERBOSE,
4653 "AFSEnumerateGlobalRoot Acquiring GlobalRoot DirectoryNodeHdr.TreeLock lock %08lX EXCL %08lX\n",
4654 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4655 PsGetCurrentThread());
4657 AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4660 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
4663 try_return( ntStatus);
4667 // Initialize the root information
4670 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.ContentIndex = 1;
4673 // Enumerate the shares in the volume
4676 ntStatus = AFSEnumerateDirectory( AuthGroup,
4677 &AFSGlobalRoot->ObjectInformation,
4680 if( !NT_SUCCESS( ntStatus))
4683 try_return( ntStatus);
4686 pDirGlobalDirNode = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead;
4689 // Indicate the node is initialized
4692 SetFlag( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
4694 uniFullName.MaximumLength = PAGE_SIZE;
4695 uniFullName.Length = 0;
4697 uniFullName.Buffer = (WCHAR *)AFSLibExAllocatePoolWithTag( PagedPool,
4698 uniFullName.MaximumLength,
4699 AFS_GENERIC_MEMORY_12_TAG);
4701 if( uniFullName.Buffer == NULL)
4705 // Reset the directory content
4708 AFSResetDirectoryContent( &AFSGlobalRoot->ObjectInformation);
4710 ClearFlag( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
4712 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4716 // Populate our list of entries in the NP enumeration list
4719 while( pDirGlobalDirNode != NULL)
4722 uniFullName.Buffer[ 0] = L'\\';
4723 uniFullName.Buffer[ 1] = L'\\';
4725 uniFullName.Length = 2 * sizeof( WCHAR);
4727 RtlCopyMemory( &uniFullName.Buffer[ 2],
4728 AFSServerName.Buffer,
4729 AFSServerName.Length);
4731 uniFullName.Length += AFSServerName.Length;
4733 uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)] = L'\\';
4735 uniFullName.Length += sizeof( WCHAR);
4737 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
4738 pDirGlobalDirNode->NameInformation.FileName.Buffer,
4739 pDirGlobalDirNode->NameInformation.FileName.Length);
4741 uniFullName.Length += pDirGlobalDirNode->NameInformation.FileName.Length;
4743 AFSAddConnectionEx( &uniFullName,
4744 RESOURCEDISPLAYTYPE_SHARE,
4747 pDirGlobalDirNode = (AFSDirectoryCB *)pDirGlobalDirNode->ListEntry.fLink;
4750 AFSExFreePool( uniFullName.Buffer);
4754 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4761 AFSIsRelativeName( IN UNICODE_STRING *Name)
4764 BOOLEAN bIsRelative = FALSE;
4766 if( Name->Buffer[ 0] != L'\\')
4776 AFSUpdateName( IN UNICODE_STRING *Name)
4781 while( usIndex < Name->Length/sizeof( WCHAR))
4784 if( Name->Buffer[ usIndex] == L'/')
4787 Name->Buffer[ usIndex] = L'\\';
4797 AFSUpdateTargetName( IN OUT UNICODE_STRING *TargetName,
4798 IN OUT ULONG *Flags,
4799 IN WCHAR *NameBuffer,
4800 IN USHORT NameLength)
4803 NTSTATUS ntStatus = STATUS_SUCCESS;
4804 WCHAR *pTmpBuffer = NULL;
4810 // If we have enough space then just move in the name otherwise
4811 // allocate a new buffer
4814 if( TargetName->Length < NameLength)
4817 pTmpBuffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4819 AFS_NAME_BUFFER_FIVE_TAG);
4821 if( pTmpBuffer == NULL)
4824 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4827 if( BooleanFlagOn( *Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
4830 AFSExFreePool( TargetName->Buffer);
4833 TargetName->MaximumLength = NameLength;
4835 TargetName->Buffer = pTmpBuffer;
4837 SetFlag( *Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER);
4840 TargetName->Length = NameLength;
4842 RtlCopyMemory( TargetName->Buffer,
4844 TargetName->Length);
4847 // Update the name in the buffer
4850 AFSUpdateName( TargetName);
4861 AFSInitNameArray( IN AFSDirectoryCB *DirectoryCB,
4862 IN ULONG InitialElementCount)
4865 AFSNameArrayHdr *pNameArray = NULL;
4866 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4872 if( InitialElementCount == 0)
4875 InitialElementCount = pDevExt->Specific.RDR.NameArrayLength;
4878 pNameArray = (AFSNameArrayHdr *)AFSExAllocatePoolWithTag( PagedPool,
4879 sizeof( AFSNameArrayHdr) +
4880 (InitialElementCount * sizeof( AFSNameArrayCB)),
4881 AFS_NAME_ARRAY_TAG);
4883 if( pNameArray == NULL)
4886 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4887 AFS_TRACE_LEVEL_ERROR,
4888 "AFSInitNameArray Failed to allocate name array\n");
4890 try_return( pNameArray);
4893 RtlZeroMemory( pNameArray,
4894 sizeof( AFSNameArrayHdr) +
4895 (InitialElementCount * sizeof( AFSNameArrayCB)));
4897 pNameArray->MaxElementCount = InitialElementCount;
4899 if( DirectoryCB != NULL)
4902 pNameArray->CurrentEntry = &pNameArray->ElementArray[ 0];
4904 lCount = InterlockedIncrement( &pNameArray->Count);
4906 lCount = InterlockedIncrement( &DirectoryCB->OpenReferenceCount);
4908 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4909 AFS_TRACE_LEVEL_VERBOSE,
4910 "AFSInitNameArray Increment count on %wZ DE %p Cnt %d\n",
4911 &DirectoryCB->NameInformation.FileName,
4915 pNameArray->CurrentEntry->DirectoryCB = DirectoryCB;
4917 pNameArray->CurrentEntry->Component = DirectoryCB->NameInformation.FileName;
4919 pNameArray->CurrentEntry->FileId = DirectoryCB->ObjectInformation->FileId;
4931 AFSPopulateNameArray( IN AFSNameArrayHdr *NameArray,
4932 IN UNICODE_STRING *Path,
4933 IN AFSDirectoryCB *DirectoryCB)
4936 NTSTATUS ntStatus = STATUS_SUCCESS;
4937 AFSNameArrayCB *pCurrentElement = NULL;
4938 UNICODE_STRING uniComponentName, uniRemainingPath;
4939 AFSObjectInfoCB *pCurrentObject = NULL;
4940 ULONG ulTotalCount = 0;
4942 USHORT usLength = 0;
4949 // Init some info in the header
4952 pCurrentElement = &NameArray->ElementArray[ 0];
4954 NameArray->CurrentEntry = pCurrentElement;
4957 // The first entry points at the root
4960 pCurrentElement->DirectoryCB = DirectoryCB->ObjectInformation->VolumeCB->DirectoryCB;
4962 lCount = InterlockedIncrement( &pCurrentElement->DirectoryCB->OpenReferenceCount);
4964 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4965 AFS_TRACE_LEVEL_VERBOSE,
4966 "AFSPopulateNameArray Increment count on volume %wZ DE %p Cnt %d\n",
4967 &pCurrentElement->DirectoryCB->NameInformation.FileName,
4968 pCurrentElement->DirectoryCB,
4971 pCurrentElement->Component = DirectoryCB->ObjectInformation->VolumeCB->DirectoryCB->NameInformation.FileName;
4973 pCurrentElement->FileId = DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
4975 NameArray->Count = 1;
4977 NameArray->LinkCount = 0;
4980 // If the root is the parent then we are done ...
4983 if( &DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation == DirectoryCB->ObjectInformation)
4985 try_return( ntStatus);
4997 AFSPopulateNameArrayFromRelatedArray( IN AFSNameArrayHdr *NameArray,
4998 IN AFSNameArrayHdr *RelatedNameArray,
4999 IN AFSDirectoryCB *DirectoryCB)
5002 NTSTATUS ntStatus = STATUS_SUCCESS;
5003 AFSNameArrayCB *pCurrentElement = NULL, *pCurrentRelatedElement = NULL;
5004 UNICODE_STRING uniComponentName, uniRemainingPath;
5005 AFSObjectInfoCB *pObjectInfo = NULL;
5006 ULONG ulTotalCount = 0;
5008 USHORT usLength = 0;
5015 // Init some info in the header
5018 pCurrentElement = &NameArray->ElementArray[ 0];
5020 pCurrentRelatedElement = &RelatedNameArray->ElementArray[ 0];
5022 NameArray->Count = 0;
5024 NameArray->LinkCount = RelatedNameArray->LinkCount;
5027 // Populate the name array with the data from the related array
5033 pCurrentElement->DirectoryCB = pCurrentRelatedElement->DirectoryCB;
5035 pCurrentElement->Component = pCurrentRelatedElement->DirectoryCB->NameInformation.FileName;
5037 pCurrentElement->FileId = pCurrentElement->DirectoryCB->ObjectInformation->FileId;
5039 lCount = InterlockedIncrement( &pCurrentElement->DirectoryCB->OpenReferenceCount);
5041 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5042 AFS_TRACE_LEVEL_VERBOSE,
5043 "AFSPopulateNameArrayFromRelatedArray Increment count on %wZ DE %p Cnt %d\n",
5044 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5045 pCurrentElement->DirectoryCB,
5048 lCount = InterlockedIncrement( &NameArray->Count);
5050 if( pCurrentElement->DirectoryCB == DirectoryCB ||
5051 NameArray->Count == RelatedNameArray->Count)
5063 pCurrentRelatedElement++;
5066 if( NameArray->Count > 0)
5068 NameArray->CurrentEntry = pCurrentElement;
5076 AFSFreeNameArray( IN AFSNameArrayHdr *NameArray)
5079 NTSTATUS ntStatus = STATUS_SUCCESS;
5080 AFSNameArrayCB *pCurrentElement = NULL;
5086 pCurrentElement = &NameArray->ElementArray[ 0];
5091 if( pCurrentElement->DirectoryCB == NULL)
5097 lCount = InterlockedDecrement( &pCurrentElement->DirectoryCB->OpenReferenceCount);
5099 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5100 AFS_TRACE_LEVEL_VERBOSE,
5101 "AFSFreeNameArray Decrement count on %wZ DE %p Cnt %d\n",
5102 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5103 pCurrentElement->DirectoryCB,
5109 AFSExFreePool( NameArray);
5116 AFSInsertNextElement( IN AFSNameArrayHdr *NameArray,
5117 IN AFSDirectoryCB *DirEntry)
5120 NTSTATUS ntStatus = STATUS_SUCCESS;
5121 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
5127 if( NameArray->Count == NameArray->MaxElementCount)
5130 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5133 if( NameArray->CurrentEntry != NULL &&
5134 NameArray->CurrentEntry->DirectoryCB == DirEntry)
5137 try_return( ntStatus);
5140 if( NameArray->Count > 0)
5143 NameArray->CurrentEntry++;
5147 NameArray->CurrentEntry = &NameArray->ElementArray[ 0];
5150 lCount = InterlockedIncrement( &NameArray->Count);
5152 lCount = InterlockedIncrement( &DirEntry->OpenReferenceCount);
5154 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5155 AFS_TRACE_LEVEL_VERBOSE,
5156 "AFSInsertNextElement Increment count on %wZ DE %p Cnt %d\n",
5157 &DirEntry->NameInformation.FileName,
5161 NameArray->CurrentEntry->DirectoryCB = DirEntry;
5163 NameArray->CurrentEntry->Component = DirEntry->NameInformation.FileName;
5165 NameArray->CurrentEntry->FileId = DirEntry->ObjectInformation->FileId;
5176 AFSReplaceCurrentElement( IN AFSNameArrayHdr *NameArray,
5177 IN AFSDirectoryCB *DirectoryCB)
5181 ASSERT( NameArray->CurrentEntry != NULL);
5183 lCount = InterlockedDecrement( &NameArray->CurrentEntry->DirectoryCB->OpenReferenceCount);
5185 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5186 AFS_TRACE_LEVEL_VERBOSE,
5187 "AFSReplaceCurrentElement Decrement count on %wZ DE %p Cnt %d\n",
5188 &NameArray->CurrentEntry->DirectoryCB->NameInformation.FileName,
5189 NameArray->CurrentEntry->DirectoryCB,
5192 lCount = InterlockedIncrement( &DirectoryCB->OpenReferenceCount);
5194 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5195 AFS_TRACE_LEVEL_VERBOSE,
5196 "AFSReplaceCurrentElement Increment count on %wZ DE %p Cnt %d\n",
5197 &DirectoryCB->NameInformation.FileName,
5201 NameArray->CurrentEntry->DirectoryCB = DirectoryCB;
5203 NameArray->CurrentEntry->Component = DirectoryCB->NameInformation.FileName;
5205 NameArray->CurrentEntry->FileId = DirectoryCB->ObjectInformation->FileId;
5207 if( DirectoryCB->ObjectInformation->ParentObjectInformation == NULL)
5210 SetFlag( NameArray->CurrentEntry->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5217 AFSBackupEntry( IN AFSNameArrayHdr *NameArray)
5220 AFSDirectoryCB *pCurrentDirEntry = NULL;
5226 if( NameArray->Count == 0)
5228 try_return( pCurrentDirEntry);
5231 lCount = InterlockedDecrement( &NameArray->CurrentEntry->DirectoryCB->OpenReferenceCount);
5233 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5234 AFS_TRACE_LEVEL_VERBOSE,
5235 "AFSBackupEntry Decrement count on %wZ DE %p Cnt %d\n",
5236 &NameArray->CurrentEntry->DirectoryCB->NameInformation.FileName,
5237 NameArray->CurrentEntry->DirectoryCB,
5240 NameArray->CurrentEntry->DirectoryCB = NULL;
5242 lCount = InterlockedDecrement( &NameArray->Count);
5246 NameArray->CurrentEntry = NULL;
5250 NameArray->CurrentEntry--;
5251 pCurrentDirEntry = NameArray->CurrentEntry->DirectoryCB;
5259 return pCurrentDirEntry;
5263 AFSGetParentEntry( IN AFSNameArrayHdr *NameArray)
5266 AFSDirectoryCB *pDirEntry = NULL;
5267 AFSNameArrayCB *pElement = NULL;
5272 if( NameArray->Count == 0 ||
5273 NameArray->Count == 1)
5276 try_return( pDirEntry = NULL);
5279 pElement = &NameArray->ElementArray[ NameArray->Count - 2];
5281 pDirEntry = pElement->DirectoryCB;
5292 AFSResetNameArray( IN AFSNameArrayHdr *NameArray,
5293 IN AFSDirectoryCB *DirEntry)
5296 AFSNameArrayCB *pCurrentElement = NULL;
5297 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
5303 pCurrentElement = &NameArray->ElementArray[ 0];
5308 if( pCurrentElement->DirectoryCB == NULL)
5314 lCount = InterlockedDecrement( &pCurrentElement->DirectoryCB->OpenReferenceCount);
5316 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5317 AFS_TRACE_LEVEL_VERBOSE,
5318 "AFSResetNameArray Decrement count on %wZ DE %p Cnt %d\n",
5319 &pCurrentElement->DirectoryCB->NameInformation.FileName,
5320 pCurrentElement->DirectoryCB,
5326 RtlZeroMemory( NameArray,
5327 sizeof( AFSNameArrayHdr) +
5328 ((pDevExt->Specific.RDR.NameArrayLength - 1) * sizeof( AFSNameArrayCB)));
5330 NameArray->MaxElementCount = pDevExt->Specific.RDR.NameArrayLength;
5332 if( DirEntry != NULL)
5335 NameArray->CurrentEntry = &NameArray->ElementArray[ 0];
5337 lCount = InterlockedIncrement( &NameArray->Count);
5339 lCount = InterlockedIncrement( &DirEntry->OpenReferenceCount);
5341 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5342 AFS_TRACE_LEVEL_VERBOSE,
5343 "AFSResetNameArray Increment count on %wZ DE %p Cnt %d\n",
5344 &DirEntry->NameInformation.FileName,
5348 NameArray->CurrentEntry->DirectoryCB = DirEntry;
5350 NameArray->CurrentEntry->Component = DirEntry->NameInformation.FileName;
5352 NameArray->CurrentEntry->FileId = DirEntry->ObjectInformation->FileId;
5360 AFSDumpNameArray( IN AFSNameArrayHdr *NameArray)
5363 AFSNameArrayCB *pCurrentElement = NULL;
5365 pCurrentElement = &NameArray->ElementArray[ 0];
5367 AFSPrint("AFSDumpNameArray Start (%d)\n", NameArray->Count);
5369 while( pCurrentElement->DirectoryCB != NULL)
5372 AFSPrint("FID %08lX-%08lX-%08lX-%08lX %wZ\n",
5373 pCurrentElement->FileId.Cell,
5374 pCurrentElement->FileId.Volume,
5375 pCurrentElement->FileId.Vnode,
5376 pCurrentElement->FileId.Unique,
5377 &pCurrentElement->DirectoryCB->NameInformation.FileName);
5382 AFSPrint("AFSDumpNameArray End\n\n");
5388 AFSSetEnumerationEvent( IN AFSFcb *Fcb)
5393 // Depending on the type of node, set the event
5396 switch( Fcb->Header.NodeTypeCode)
5399 case AFS_DIRECTORY_FCB:
5404 lCount = InterlockedIncrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
5414 AFSClearEnumerationEvent( IN AFSFcb *Fcb)
5420 // Depending on the type of node, set the event
5423 switch( Fcb->Header.NodeTypeCode)
5426 case AFS_DIRECTORY_FCB:
5431 ASSERT( Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0);
5433 lCount = InterlockedDecrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
5443 AFSIsEnumerationInProcess( IN AFSObjectInfoCB *ObjectInfo)
5446 BOOLEAN bIsInProcess = FALSE;
5451 if( ObjectInfo->Fcb == NULL)
5454 try_return( bIsInProcess);
5457 switch( ObjectInfo->Fcb->Header.NodeTypeCode)
5460 case AFS_DIRECTORY_FCB:
5465 if( ObjectInfo->Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0)
5468 bIsInProcess = TRUE;
5480 return bIsInProcess;
5484 AFSVerifyVolume( IN ULONGLONG ProcessId,
5485 IN AFSVolumeCB *VolumeCB)
5488 NTSTATUS ntStatus = STATUS_SUCCESS;
5495 AFSInitPIOCtlDirectoryCB( IN AFSObjectInfoCB *ObjectInfo)
5498 NTSTATUS ntStatus = STATUS_SUCCESS;
5499 AFSObjectInfoCB *pObjectInfoCB = NULL;
5500 AFSDirectoryCB *pDirNode = NULL;
5501 ULONG ulEntryLength = 0;
5502 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
5508 pObjectInfoCB = AFSAllocateObjectInfo( ObjectInfo,
5511 if( pObjectInfoCB == NULL)
5514 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5517 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
5518 AFS_TRACE_LEVEL_VERBOSE,
5519 "AFSInitPIOCtlDirectoryCB Initializing count (1) on object %08lX\n",
5522 pObjectInfoCB->ObjectReferenceCount = 1;
5524 pObjectInfoCB->FileType = AFS_FILE_TYPE_PIOCTL;
5526 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
5528 ulEntryLength = sizeof( AFSDirectoryCB) + AFSPIOCtlName.Length;
5530 pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
5534 if( pDirNode == NULL)
5537 AFSDeleteObjectInfo( pObjectInfoCB);
5539 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5542 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
5543 sizeof( AFSNonPagedDirectoryCB),
5544 AFS_DIR_ENTRY_NP_TAG);
5546 if( pNonPagedDirEntry == NULL)
5549 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5552 RtlZeroMemory( pDirNode,
5555 RtlZeroMemory( pNonPagedDirEntry,
5556 sizeof( AFSNonPagedDirectoryCB));
5558 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
5560 pDirNode->NonPaged = pNonPagedDirEntry;
5562 pDirNode->ObjectInformation = pObjectInfoCB;
5564 pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_PIOCTL_INDEX;
5570 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_FAKE);
5572 pDirNode->NameInformation.FileName.Length = AFSPIOCtlName.Length;
5574 pDirNode->NameInformation.FileName.MaximumLength = AFSPIOCtlName.Length;
5576 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
5578 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
5579 AFSPIOCtlName.Buffer,
5580 pDirNode->NameInformation.FileName.Length);
5582 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
5585 if ( InterlockedCompareExchangePointer( (PVOID *)&ObjectInfo->Specific.Directory.PIOCtlDirectoryCB, pDirNode, NULL) != NULL)
5588 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
5589 AFS_TRACE_LEVEL_WARNING,
5590 "AFSInitPIOCtlDirectoryCB Raced PIOCtlDirectoryCB %08lX pFcb %08lX\n",
5591 ObjectInfo->Specific.Directory.PIOCtlDirectoryCB,
5595 // Increment the open reference and handle on the node
5598 lCount = InterlockedIncrement( &pDirNode->ObjectInformation->ObjectReferenceCount);
5600 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
5601 AFS_TRACE_LEVEL_VERBOSE,
5602 "AFSInitPIOCtlDirectoryCB Increment count on Object %08lX Cnt %d\n",
5603 pDirNode->ObjectInformation,
5606 try_return( ntStatus = STATUS_REPARSE);
5611 if ( ntStatus != STATUS_SUCCESS)
5614 if ( pDirNode != NULL)
5617 AFSExFreePool( pDirNode);
5620 if ( pObjectInfoCB != NULL)
5623 AFSDeleteObjectInfo( pObjectInfoCB);
5632 AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB,
5633 IN AFSDirectoryCB *DirectoryCB,
5634 IN UNICODE_STRING *ParentPathName,
5635 IN AFSNameArrayHdr *RelatedNameArray,
5637 OUT AFSFileInfoCB *FileInfo)
5640 NTSTATUS ntStatus = STATUS_SUCCESS;
5641 AFSDirEnumEntry *pDirEntry = NULL, *pLastDirEntry = NULL;
5642 UNICODE_STRING uniFullPathName;
5643 AFSNameArrayHdr *pNameArray = NULL;
5644 AFSVolumeCB *pVolumeCB = NULL;
5645 AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
5646 WCHAR *pwchBuffer = NULL;
5647 UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
5648 ULONG ulNameDifference = 0;
5655 // Retrieve a target name for the entry
5658 AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
5661 if( DirectoryCB->NameInformation.TargetName.Length == 0)
5664 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5666 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
5671 if( !NT_SUCCESS( ntStatus) ||
5672 pDirEntry->TargetNameLength == 0)
5675 if( pDirEntry != NULL)
5678 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
5681 try_return( ntStatus);
5684 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
5687 if( DirectoryCB->NameInformation.TargetName.Length == 0)
5691 // Update the target name
5694 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
5695 &DirectoryCB->Flags,
5696 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
5697 (USHORT)pDirEntry->TargetNameLength);
5699 if( !NT_SUCCESS( ntStatus))
5702 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5704 try_return( ntStatus);
5708 AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
5712 // Need to pass the full path in for parsing.
5715 if( AFSIsRelativeName( &DirectoryCB->NameInformation.TargetName))
5718 uniFullPathName.Length = 0;
5719 uniFullPathName.MaximumLength = ParentPathName->Length +
5721 DirectoryCB->NameInformation.TargetName.Length;
5723 uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5724 uniFullPathName.MaximumLength,
5725 AFS_NAME_BUFFER_SIX_TAG);
5727 if( uniFullPathName.Buffer == NULL)
5730 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5732 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5735 pwchBuffer = uniFullPathName.Buffer;
5737 RtlZeroMemory( uniFullPathName.Buffer,
5738 uniFullPathName.MaximumLength);
5740 RtlCopyMemory( uniFullPathName.Buffer,
5741 ParentPathName->Buffer,
5742 ParentPathName->Length);
5744 uniFullPathName.Length = ParentPathName->Length;
5746 if( uniFullPathName.Buffer[ (uniFullPathName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
5747 DirectoryCB->NameInformation.TargetName.Buffer[ 0] != L'\\')
5750 uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)] = L'\\';
5752 uniFullPathName.Length += sizeof( WCHAR);
5755 RtlCopyMemory( &uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)],
5756 DirectoryCB->NameInformation.TargetName.Buffer,
5757 DirectoryCB->NameInformation.TargetName.Length);
5759 uniFullPathName.Length += DirectoryCB->NameInformation.TargetName.Length;
5761 uniParsedName.Length = uniFullPathName.Length - ParentPathName->Length;
5762 uniParsedName.MaximumLength = uniParsedName.Length;
5764 uniParsedName.Buffer = &uniFullPathName.Buffer[ ParentPathName->Length/sizeof( WCHAR)];
5766 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5769 // We populate up to the current parent
5772 if( RelatedNameArray != NULL)
5775 pNameArray = AFSInitNameArray( NULL,
5776 RelatedNameArray->MaxElementCount);
5778 if( pNameArray == NULL)
5781 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5784 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
5791 pNameArray = AFSInitNameArray( NULL,
5794 if( pNameArray == NULL)
5797 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5800 ntStatus = AFSPopulateNameArray( pNameArray,
5805 if( !NT_SUCCESS( ntStatus))
5808 try_return( ntStatus);
5811 pVolumeCB = ParentDirectoryCB->ObjectInformation->VolumeCB;
5813 pParentDirEntry = ParentDirectoryCB;
5818 uniFullPathName.Length = 0;
5819 uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
5821 uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5822 uniFullPathName.MaximumLength,
5823 AFS_NAME_BUFFER_SEVEN_TAG);
5825 if( uniFullPathName.Buffer == NULL)
5828 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5830 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5833 pwchBuffer = uniFullPathName.Buffer;
5835 RtlZeroMemory( uniFullPathName.Buffer,
5836 uniFullPathName.MaximumLength);
5838 RtlCopyMemory( uniFullPathName.Buffer,
5839 DirectoryCB->NameInformation.TargetName.Buffer,
5840 DirectoryCB->NameInformation.TargetName.Length);
5842 uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
5845 // This name should begin with the \afs server so parse it off and check it
5848 FsRtlDissectName( uniFullPathName,
5852 if( RtlCompareUnicodeString( &uniComponentName,
5857 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5859 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
5860 AFS_TRACE_LEVEL_ERROR,
5861 "AFSRetrieveFileAttributes Name %wZ contains invalid server name\n",
5864 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
5867 uniFullPathName = uniRemainingPath;
5869 uniParsedName = uniFullPathName;
5871 ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
5873 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5879 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
5882 if( pNameArray == NULL)
5885 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5888 pVolumeCB = AFSGlobalRoot;
5890 pParentDirEntry = AFSGlobalRoot->DirectoryCB;
5894 // Increment the ref count on the volume and dir entry for correct processing below
5897 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
5899 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
5900 AFS_TRACE_LEVEL_VERBOSE,
5901 "AFSRetrieveFileAttributes Increment count on volume %08lX Cnt %d\n",
5905 lCount = InterlockedIncrement( &pParentDirEntry->OpenReferenceCount);
5907 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5908 AFS_TRACE_LEVEL_VERBOSE,
5909 "AFSRetrieveFileAttributes Increment count on %wZ DE %p Ccb %p Cnt %d\n",
5910 &pParentDirEntry->NameInformation.FileName,
5915 ntStatus = AFSLocateNameEntry( NULL,
5920 AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL,
5926 if( !NT_SUCCESS( ntStatus))
5930 // The volume lock was released on failure above
5931 // Except for STATUS_OBJECT_NAME_NOT_FOUND
5934 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
5937 if( pVolumeCB != NULL)
5940 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
5942 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
5943 AFS_TRACE_LEVEL_VERBOSE,
5944 "AFSRetrieveFileAttributes Decrement count on volume %08lX Cnt %d\n",
5949 if( pDirectoryEntry != NULL)
5952 lCount = InterlockedDecrement( &pDirectoryEntry->OpenReferenceCount);
5954 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5955 AFS_TRACE_LEVEL_VERBOSE,
5956 "AFSRetrieveFileAttributes Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
5957 &pDirectoryEntry->NameInformation.FileName,
5965 lCount = InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
5967 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5968 AFS_TRACE_LEVEL_VERBOSE,
5969 "AFSRetrieveFileAttributes Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
5970 &pParentDirEntry->NameInformation.FileName,
5979 try_return( ntStatus);
5983 // Store off the information
5986 FileInfo->FileAttributes = pDirectoryEntry->ObjectInformation->FileAttributes;
5989 // Check for the mount point being returned
5992 if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT)
5995 FileInfo->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
5997 else if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK ||
5998 pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DFSLINK)
6001 if ( FileInfo->FileAttributes == FILE_ATTRIBUTE_NORMAL)
6004 FileInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
6009 FileInfo->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
6013 FileInfo->AllocationSize = pDirectoryEntry->ObjectInformation->AllocationSize;
6015 FileInfo->EndOfFile = pDirectoryEntry->ObjectInformation->EndOfFile;
6017 FileInfo->CreationTime = pDirectoryEntry->ObjectInformation->CreationTime;
6019 FileInfo->LastAccessTime = pDirectoryEntry->ObjectInformation->LastAccessTime;
6021 FileInfo->LastWriteTime = pDirectoryEntry->ObjectInformation->LastWriteTime;
6023 FileInfo->ChangeTime = pDirectoryEntry->ObjectInformation->ChangeTime;
6026 // Remove the reference made above
6029 lCount = InterlockedDecrement( &pDirectoryEntry->OpenReferenceCount);
6031 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6032 AFS_TRACE_LEVEL_VERBOSE,
6033 "AFSRetrieveFileAttributes Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
6034 &pDirectoryEntry->NameInformation.FileName,
6041 if( pDirEntry != NULL)
6044 AFSExFreePool( pDirEntry);
6047 if( pVolumeCB != NULL)
6050 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6052 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6053 AFS_TRACE_LEVEL_VERBOSE,
6054 "AFSRetrieveFileAttributes Decrement2 count on volume %08lX Cnt %d\n",
6059 if( pNameArray != NULL)
6062 AFSFreeNameArray( pNameArray);
6065 if( pwchBuffer != NULL)
6069 // Always free the buffer that we allocated as AFSLocateNameEntry
6070 // will not free it. If uniFullPathName.Buffer was allocated by
6071 // AFSLocateNameEntry, then we must free that as well.
6072 // Check that the uniFullPathName.Buffer in the string is not the same
6073 // offset by the length of the server name
6076 if( uniFullPathName.Length > 0 &&
6077 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
6080 AFSExFreePool( uniFullPathName.Buffer);
6083 AFSExFreePool( pwchBuffer);
6091 AFSAllocateObjectInfo( IN AFSObjectInfoCB *ParentObjectInfo,
6092 IN ULONGLONG HashIndex)
6095 NTSTATUS ntStatus = STATUS_SUCCESS;
6096 AFSObjectInfoCB *pObjectInfo = NULL;
6102 pObjectInfo = (AFSObjectInfoCB *)AFSExAllocatePoolWithTag( PagedPool,
6103 sizeof( AFSObjectInfoCB),
6104 AFS_OBJECT_INFO_TAG);
6106 if( pObjectInfo == NULL)
6109 try_return( pObjectInfo);
6112 RtlZeroMemory( pObjectInfo,
6113 sizeof( AFSObjectInfoCB));
6115 pObjectInfo->NonPagedInfo = (AFSNonPagedObjectInfoCB *)AFSExAllocatePoolWithTag( NonPagedPool,
6116 sizeof( AFSNonPagedObjectInfoCB),
6117 AFS_NP_OBJECT_INFO_TAG);
6119 if( pObjectInfo->NonPagedInfo == NULL)
6122 AFSExFreePool( pObjectInfo);
6124 try_return( pObjectInfo = NULL);
6127 ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6129 pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock = &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock;
6131 pObjectInfo->VolumeCB = ParentObjectInfo->VolumeCB;
6133 pObjectInfo->ParentObjectInformation = ParentObjectInfo;
6135 if( ParentObjectInfo != NULL)
6137 lCount = InterlockedIncrement( &ParentObjectInfo->ObjectReferenceCount);
6141 // Initialize the access time
6144 KeQueryTickCount( &pObjectInfo->LastAccessCount);
6150 // Insert the entry into the object tree and list
6153 pObjectInfo->TreeEntry.HashIndex = HashIndex;
6155 if( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead == NULL)
6158 ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead = &pObjectInfo->TreeEntry;
6163 ntStatus = AFSInsertHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
6164 &pObjectInfo->TreeEntry);
6166 ASSERT( NT_SUCCESS( ntStatus));
6170 // And the object list in the volume
6173 if( ParentObjectInfo->VolumeCB->ObjectInfoListHead == NULL)
6176 ParentObjectInfo->VolumeCB->ObjectInfoListHead = pObjectInfo;
6181 ParentObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = (void *)pObjectInfo;
6183 pObjectInfo->ListEntry.bLink = (void *)ParentObjectInfo->VolumeCB->ObjectInfoListTail;
6186 ParentObjectInfo->VolumeCB->ObjectInfoListTail = pObjectInfo;
6189 // Indicate the object is in the hash tree and linked list in the volume
6192 SetFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE | AFS_OBJECT_INSERTED_VOLUME_LIST);
6204 AFSDeleteObjectInfo( IN AFSObjectInfoCB *ObjectInfo)
6207 BOOLEAN bAcquiredTreeLock = FALSE;
6210 if( !ExIsResourceAcquiredExclusiveLite( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock))
6213 ASSERT( !ExIsResourceAcquiredLite( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock));
6215 AFSAcquireExcl( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
6218 bAcquiredTreeLock = TRUE;
6222 // Remove it from the tree and list if it was inserted
6225 if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
6228 AFSRemoveHashEntry( &ObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
6229 &ObjectInfo->TreeEntry);
6232 if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_INSERTED_VOLUME_LIST))
6235 if( ObjectInfo->ListEntry.fLink == NULL)
6238 ObjectInfo->VolumeCB->ObjectInfoListTail = (AFSObjectInfoCB *)ObjectInfo->ListEntry.bLink;
6240 if( ObjectInfo->VolumeCB->ObjectInfoListTail != NULL)
6243 ObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = NULL;
6249 ((AFSObjectInfoCB *)(ObjectInfo->ListEntry.fLink))->ListEntry.bLink = ObjectInfo->ListEntry.bLink;
6252 if( ObjectInfo->ListEntry.bLink == NULL)
6255 ObjectInfo->VolumeCB->ObjectInfoListHead = (AFSObjectInfoCB *)ObjectInfo->ListEntry.fLink;
6257 if( ObjectInfo->VolumeCB->ObjectInfoListHead != NULL)
6260 ObjectInfo->VolumeCB->ObjectInfoListHead->ListEntry.bLink = NULL;
6266 ((AFSObjectInfoCB *)(ObjectInfo->ListEntry.bLink))->ListEntry.fLink = ObjectInfo->ListEntry.fLink;
6270 if( ObjectInfo->ParentObjectInformation != NULL)
6273 lCount = InterlockedDecrement( &ObjectInfo->ParentObjectInformation->ObjectReferenceCount);
6276 if( bAcquiredTreeLock)
6279 AFSReleaseResource( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
6283 // Release the fid in the service
6286 if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_HELD_IN_SERVICE))
6289 AFSReleaseFid( &ObjectInfo->FileId);
6292 ExDeleteResourceLite( &ObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6294 AFSExFreePool( ObjectInfo->NonPagedInfo);
6296 AFSExFreePool( ObjectInfo);
6302 AFSEvaluateRootEntry( IN AFSDirectoryCB *DirectoryCB,
6303 OUT AFSDirectoryCB **TargetDirEntry)
6306 NTSTATUS ntStatus = STATUS_SUCCESS;
6307 AFSDirEnumEntry *pDirEntry = NULL, *pLastDirEntry = NULL;
6308 UNICODE_STRING uniFullPathName;
6309 AFSNameArrayHdr *pNameArray = NULL;
6310 AFSVolumeCB *pVolumeCB = NULL;
6311 AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
6312 WCHAR *pwchBuffer = NULL;
6313 UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
6314 ULONG ulNameDifference = 0;
6321 ntStatus = AFSRetrieveValidAuthGroup( NULL,
6322 DirectoryCB->ObjectInformation,
6326 if( !NT_SUCCESS( ntStatus))
6328 try_return( ntStatus);
6332 // Retrieve a target name for the entry
6335 AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
6338 if( DirectoryCB->NameInformation.TargetName.Length == 0)
6341 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6343 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
6348 if( !NT_SUCCESS( ntStatus) ||
6349 pDirEntry->TargetNameLength == 0)
6352 if( pDirEntry != NULL)
6355 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
6358 try_return( ntStatus);
6361 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
6364 if( DirectoryCB->NameInformation.TargetName.Length == 0)
6368 // Update the target name
6371 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
6372 &DirectoryCB->Flags,
6373 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
6374 (USHORT)pDirEntry->TargetNameLength);
6376 if( !NT_SUCCESS( ntStatus))
6379 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6381 try_return( ntStatus);
6385 AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
6389 // Need to pass the full path in for parsing.
6392 uniFullPathName.Length = 0;
6393 uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
6395 uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6396 uniFullPathName.MaximumLength,
6397 AFS_NAME_BUFFER_EIGHT_TAG);
6399 if( uniFullPathName.Buffer == NULL)
6402 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6404 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6407 pwchBuffer = uniFullPathName.Buffer;
6409 RtlZeroMemory( uniFullPathName.Buffer,
6410 uniFullPathName.MaximumLength);
6412 RtlCopyMemory( uniFullPathName.Buffer,
6413 DirectoryCB->NameInformation.TargetName.Buffer,
6414 DirectoryCB->NameInformation.TargetName.Length);
6416 uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6419 // This name should begin with the \afs server so parse it off and chech it
6422 FsRtlDissectName( uniFullPathName,
6426 if( RtlCompareUnicodeString( &uniComponentName,
6432 // Try evaluating the full path
6435 uniFullPathName.Buffer = pwchBuffer;
6437 uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6439 uniFullPathName.MaximumLength = uniFullPathName.Length;
6444 uniFullPathName = uniRemainingPath;
6447 uniParsedName = uniFullPathName;
6449 ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
6451 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6457 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
6460 if( pNameArray == NULL)
6463 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6466 pVolumeCB = AFSGlobalRoot;
6468 pParentDirEntry = AFSGlobalRoot->DirectoryCB;
6470 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
6472 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6473 AFS_TRACE_LEVEL_VERBOSE,
6474 "AFSEvaluateRootEntry Increment count on volume %08lX Cnt %d\n",
6478 lCount = InterlockedIncrement( &pParentDirEntry->OpenReferenceCount);
6480 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6481 AFS_TRACE_LEVEL_VERBOSE,
6482 "AFSEvaluateRootEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
6483 &pParentDirEntry->NameInformation.FileName,
6488 ntStatus = AFSLocateNameEntry( NULL,
6499 if( !NT_SUCCESS( ntStatus))
6503 // The volume lock was released on failure above
6504 // Except for STATUS_OBJECT_NAME_NOT_FOUND
6507 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
6510 if( pVolumeCB != NULL)
6513 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6515 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6516 AFS_TRACE_LEVEL_VERBOSE,
6517 "AFSEvaluateRootEntry Decrement count on volume %08lX Cnt %d\n",
6522 if( pDirectoryEntry != NULL)
6525 lCount = InterlockedDecrement( &pDirectoryEntry->OpenReferenceCount);
6527 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6528 AFS_TRACE_LEVEL_VERBOSE,
6529 "AFSEvaluateRootEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6530 &pDirectoryEntry->NameInformation.FileName,
6538 lCount = InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
6540 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6541 AFS_TRACE_LEVEL_VERBOSE,
6542 "AFSEvaluateRootEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6543 &pParentDirEntry->NameInformation.FileName,
6552 try_return( ntStatus);
6556 // Pass back the target dir entry for this request
6559 *TargetDirEntry = pDirectoryEntry;
6563 if( pDirEntry != NULL)
6566 AFSExFreePool( pDirEntry);
6569 if( pVolumeCB != NULL)
6572 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6574 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6575 AFS_TRACE_LEVEL_VERBOSE,
6576 "AFSEvaluateRootEntry2 Decrement count on volume %08lX Cnt %d\n",
6581 if( pNameArray != NULL)
6584 AFSFreeNameArray( pNameArray);
6587 if( pwchBuffer != NULL)
6591 // Always free the buffer that we allocated as AFSLocateNameEntry
6592 // will not free it. If uniFullPathName.Buffer was allocated by
6593 // AFSLocateNameEntry, then we must free that as well.
6594 // Check that the uniFullPathName.Buffer in the string is not the same
6595 // offset by the length of the server name
6598 if( uniFullPathName.Length > 0 &&
6599 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
6602 AFSExFreePool( uniFullPathName.Buffer);
6605 AFSExFreePool( pwchBuffer);
6613 AFSCleanupFcb( IN AFSFcb *Fcb,
6614 IN BOOLEAN ForceFlush)
6617 NTSTATUS ntStatus = STATUS_SUCCESS;
6618 AFSDeviceExt *pRDRDeviceExt = NULL, *pControlDeviceExt = NULL;
6619 LARGE_INTEGER liTime;
6620 IO_STATUS_BLOCK stIoStatus;
6625 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
6627 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
6629 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
6632 if( !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) &&
6633 !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
6636 AFSAcquireExcl( &Fcb->NPFcb->Resource,
6639 if( Fcb->OpenReferenceCount > 0)
6645 CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
6650 if( !NT_SUCCESS( stIoStatus.Status))
6653 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
6654 AFS_TRACE_LEVEL_ERROR,
6655 "AFSCleanupFcb CcFlushCache [1] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
6656 Fcb->ObjectInformation->FileId.Cell,
6657 Fcb->ObjectInformation->FileId.Volume,
6658 Fcb->ObjectInformation->FileId.Vnode,
6659 Fcb->ObjectInformation->FileId.Unique,
6661 stIoStatus.Information);
6663 ntStatus = stIoStatus.Status;
6666 CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
6671 __except( EXCEPTION_EXECUTE_HANDLER)
6673 ntStatus = GetExceptionCode();
6677 AFSReleaseResource( &Fcb->NPFcb->Resource);
6680 // Wait for any currently running flush or release requests to complete
6683 AFSWaitOnQueuedFlushes( Fcb);
6686 // Now perform another flush on the file
6689 if( !NT_SUCCESS( AFSFlushExtents( Fcb,
6693 AFSReleaseExtentsWithFlush( Fcb,
6698 if( Fcb->OpenReferenceCount == 0 ||
6699 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
6700 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
6703 AFSTearDownFcbExtents( Fcb,
6707 try_return( ntStatus);
6710 KeQueryTickCount( &liTime);
6713 // First up are there dirty extents in the cache to flush?
6717 ( !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) &&
6718 !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
6719 ( Fcb->Specific.File.ExtentsDirtyCount ||
6720 Fcb->Specific.File.ExtentCount) &&
6721 (liTime.QuadPart - Fcb->Specific.File.LastServerFlush.QuadPart)
6722 >= pControlDeviceExt->Specific.Control.FcbFlushTimeCount.QuadPart))
6724 if( !NT_SUCCESS( AFSFlushExtents( Fcb,
6726 Fcb->OpenReferenceCount == 0)
6729 AFSReleaseExtentsWithFlush( Fcb,
6733 else if( BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
6734 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
6738 // The file has been marked as invalid. Dump it
6741 AFSTearDownFcbExtents( Fcb,
6746 // If there are extents and they haven't been used recently *and*
6747 // are not being used
6751 ( 0 != Fcb->Specific.File.ExtentCount &&
6752 0 != Fcb->Specific.File.LastExtentAccess.QuadPart &&
6753 (liTime.QuadPart - Fcb->Specific.File.LastExtentAccess.QuadPart) >=
6754 (AFS_SERVER_PURGE_SLEEP * pControlDeviceExt->Specific.Control.FcbPurgeTimeCount.QuadPart))) &&
6755 AFSAcquireExcl( &Fcb->NPFcb->Resource,
6762 CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
6767 if( !NT_SUCCESS( stIoStatus.Status))
6770 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
6771 AFS_TRACE_LEVEL_ERROR,
6772 "AFSCleanupFcb CcFlushCache [2] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
6773 Fcb->ObjectInformation->FileId.Cell,
6774 Fcb->ObjectInformation->FileId.Volume,
6775 Fcb->ObjectInformation->FileId.Vnode,
6776 Fcb->ObjectInformation->FileId.Unique,
6778 stIoStatus.Information);
6780 ntStatus = stIoStatus.Status;
6786 CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
6792 __except( EXCEPTION_EXECUTE_HANDLER)
6794 ntStatus = GetExceptionCode();
6797 AFSReleaseResource( &Fcb->NPFcb->Resource);
6799 if( Fcb->OpenReferenceCount == 0)
6803 // Tear em down we'll not be needing them again
6806 AFSTearDownFcbExtents( Fcb,
6820 AFSUpdateDirEntryName( IN AFSDirectoryCB *DirectoryCB,
6821 IN UNICODE_STRING *NewFileName)
6824 NTSTATUS ntStatus = STATUS_SUCCESS;
6825 WCHAR *pTmpBuffer = NULL;
6830 if( NewFileName->Length > DirectoryCB->NameInformation.FileName.Length)
6833 if( BooleanFlagOn( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
6836 AFSExFreePool( DirectoryCB->NameInformation.FileName.Buffer);
6838 ClearFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
6840 DirectoryCB->NameInformation.FileName.Buffer = NULL;
6844 // OK, we need to allocate a new name buffer
6847 pTmpBuffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6848 NewFileName->Length,
6849 AFS_NAME_BUFFER_NINE_TAG);
6851 if( pTmpBuffer == NULL)
6854 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6857 DirectoryCB->NameInformation.FileName.Buffer = pTmpBuffer;
6859 DirectoryCB->NameInformation.FileName.MaximumLength = NewFileName->Length;
6861 SetFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
6864 DirectoryCB->NameInformation.FileName.Length = NewFileName->Length;
6866 RtlCopyMemory( DirectoryCB->NameInformation.FileName.Buffer,
6867 NewFileName->Buffer,
6868 NewFileName->Length);
6879 AFSReadCacheFile( IN void *ReadBuffer,
6880 IN LARGE_INTEGER *ReadOffset,
6881 IN ULONG RequestedDataLength,
6882 IN OUT PULONG BytesRead)
6885 NTSTATUS ntStatus = STATUS_SUCCESS;
6888 PIO_STACK_LOCATION pIoStackLocation = NULL;
6889 AFSDeviceExt *pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
6890 DEVICE_OBJECT *pTargetDeviceObject = NULL;
6891 FILE_OBJECT *pCacheFileObject = NULL;
6896 pCacheFileObject = AFSReferenceCacheFileObject();
6898 if( pCacheFileObject == NULL)
6900 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
6903 pTargetDeviceObject = IoGetRelatedDeviceObject( pCacheFileObject);
6906 // Initialize the event
6909 KeInitializeEvent( &kEvent,
6910 SynchronizationEvent,
6914 // Allocate an irp for this request. This could also come from a
6915 // private pool, for instance.
6918 pIrp = IoAllocateIrp( pTargetDeviceObject->StackSize,
6924 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6928 // Build the IRP's main body
6931 pIrp->UserBuffer = ReadBuffer;
6933 pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
6934 pIrp->RequestorMode = KernelMode;
6935 pIrp->Flags |= IRP_READ_OPERATION;
6938 // Set up the I/O stack location.
6941 pIoStackLocation = IoGetNextIrpStackLocation( pIrp);
6942 pIoStackLocation->MajorFunction = IRP_MJ_READ;
6943 pIoStackLocation->DeviceObject = pTargetDeviceObject;
6944 pIoStackLocation->FileObject = pCacheFileObject;
6945 pIoStackLocation->Parameters.Read.Length = RequestedDataLength;
6947 pIoStackLocation->Parameters.Read.ByteOffset.QuadPart = ReadOffset->QuadPart;
6950 // Set the completion routine.
6953 IoSetCompletionRoutine( pIrp,
6961 // Send it to the FSD
6964 ntStatus = IoCallDriver( pTargetDeviceObject,
6967 if( NT_SUCCESS( ntStatus))
6974 ntStatus = KeWaitForSingleObject( &kEvent,
6980 if( NT_SUCCESS( ntStatus))
6983 ntStatus = pIrp->IoStatus.Status;
6985 *BytesRead = (ULONG)pIrp->IoStatus.Information;
6991 if( pCacheFileObject != NULL)
6993 AFSReleaseCacheFileObject( pCacheFileObject);
6999 if( pIrp->MdlAddress != NULL)
7002 if( FlagOn( pIrp->MdlAddress->MdlFlags, MDL_PAGES_LOCKED))
7005 MmUnlockPages( pIrp->MdlAddress);
7008 IoFreeMdl( pIrp->MdlAddress);
7011 pIrp->MdlAddress = NULL;
7025 AFSIrpComplete( IN PDEVICE_OBJECT DeviceObject,
7030 KEVENT *pEvent = (KEVENT *)Context;
7036 return STATUS_MORE_PROCESSING_REQUIRED;
7040 AFSIsDirectoryEmptyForDelete( IN AFSFcb *Fcb)
7043 BOOLEAN bIsEmpty = FALSE;
7044 AFSDirectoryCB *pDirEntry = NULL;
7049 AFSAcquireShared( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
7054 if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
7057 pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
7059 while( pDirEntry != NULL)
7062 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
7063 !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
7071 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
7076 AFSReleaseResource( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
7083 AFSRemoveNameEntry( IN AFSObjectInfoCB *ParentObjectInfo,
7084 IN AFSDirectoryCB *DirEntry)
7087 NTSTATUS ntStatus = STATUS_SUCCESS;
7092 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7095 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7096 AFS_TRACE_LEVEL_VERBOSE,
7097 "AFSRemoveNameEntry DE %p for %wZ has NOT_IN flag set\n",
7099 &DirEntry->NameInformation.FileName);
7101 try_return( ntStatus);
7104 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
7107 // Remove the entry from the parent tree
7110 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7111 AFS_TRACE_LEVEL_VERBOSE,
7112 "AFSRemoveNameEntry DE %p for %wZ removing from case sensitive tree\n",
7114 &DirEntry->NameInformation.FileName);
7116 AFSRemoveCaseSensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7119 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7120 AFS_TRACE_LEVEL_VERBOSE,
7121 "AFSRemoveNameEntry DE %p for %wZ removing from case insensitive tree\n",
7123 &DirEntry->NameInformation.FileName);
7125 AFSRemoveCaseInsensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
7128 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
7132 // From the short name tree
7135 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7136 AFS_TRACE_LEVEL_VERBOSE,
7137 "AFSRemoveNameEntry DE %p for %wZ removing from shortname tree\n",
7139 &DirEntry->NameInformation.FileName);
7141 AFSRemoveShortNameDirEntry( &ParentObjectInfo->Specific.Directory.ShortNameTree,
7144 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
7147 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7148 AFS_TRACE_LEVEL_VERBOSE,
7149 "AFSRemoveNameEntry DE %p for %wZ setting NOT_IN flag\n",
7151 &DirEntry->NameInformation.FileName);
7153 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
7155 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
7166 AFSGetAuthenticationId()
7169 LARGE_INTEGER liAuthId = {0,0};
7170 NTSTATUS ntStatus = STATUS_SUCCESS;
7171 PACCESS_TOKEN hToken = NULL;
7172 PTOKEN_STATISTICS pTokenInfo = NULL;
7173 BOOLEAN bCopyOnOpen = FALSE;
7174 BOOLEAN bEffectiveOnly = FALSE;
7175 BOOLEAN bPrimaryToken = FALSE;
7176 SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
7181 hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
7184 &stImpersonationLevel);
7189 hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
7194 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7195 AFS_TRACE_LEVEL_ERROR,
7196 "AFSGetAuthenticationId Failed to retrieve impersonation or primary token\n");
7198 try_return( ntStatus);
7201 bPrimaryToken = TRUE;
7204 ntStatus = SeQueryInformationToken( hToken,
7206 (PVOID *)&pTokenInfo);
7208 if( !NT_SUCCESS( ntStatus))
7211 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7212 AFS_TRACE_LEVEL_ERROR,
7213 "AFSGetAuthenticationId Failed to retrieve information Status %08lX\n", ntStatus);
7215 try_return( ntStatus);
7218 liAuthId.HighPart = pTokenInfo->AuthenticationId.HighPart;
7219 liAuthId.LowPart = pTokenInfo->AuthenticationId.LowPart;
7221 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7222 AFS_TRACE_LEVEL_VERBOSE,
7223 "AFSGetAuthenticationId Successfully retrieved authentication ID %I64X\n",
7234 PsDereferenceImpersonationToken( hToken);
7239 PsDereferencePrimaryToken( hToken);
7243 if( pTokenInfo != NULL)
7246 AFSExFreePool( pTokenInfo);
7254 AFSUnwindFileInfo( IN AFSFcb *Fcb,
7258 if( Ccb->FileUnwindInfo.FileAttributes != (ULONG)-1)
7260 Ccb->DirectoryCB->ObjectInformation->FileAttributes = Ccb->FileUnwindInfo.FileAttributes;
7263 if( Ccb->FileUnwindInfo.CreationTime.QuadPart != (ULONGLONG)-1)
7265 Ccb->DirectoryCB->ObjectInformation->CreationTime.QuadPart = Ccb->FileUnwindInfo.CreationTime.QuadPart;
7268 if( Ccb->FileUnwindInfo.LastAccessTime.QuadPart != (ULONGLONG)-1)
7270 Ccb->DirectoryCB->ObjectInformation->LastAccessTime.QuadPart = Ccb->FileUnwindInfo.LastAccessTime.QuadPart;
7273 if( Ccb->FileUnwindInfo.LastWriteTime.QuadPart != (ULONGLONG)-1)
7275 Ccb->DirectoryCB->ObjectInformation->LastWriteTime.QuadPart = Ccb->FileUnwindInfo.LastWriteTime.QuadPart;
7278 if( Ccb->FileUnwindInfo.ChangeTime.QuadPart != (ULONGLONG)-1)
7280 Ccb->DirectoryCB->ObjectInformation->ChangeTime.QuadPart = Ccb->FileUnwindInfo.ChangeTime.QuadPart;
7287 AFSValidateDirList( IN AFSObjectInfoCB *ObjectInfo)
7290 BOOLEAN bIsValid = TRUE;
7292 AFSDirectoryCB *pCurrentDirEntry = NULL, *pDirEntry = NULL;
7294 pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
7296 while( pCurrentDirEntry != NULL)
7299 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
7303 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7308 AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7309 (ULONG)pCurrentDirEntry->CaseSensitiveTreeEntry.HashIndex,
7312 if( pDirEntry == NULL)
7319 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
7322 if( ulCount != ObjectInfo->Specific.Directory.DirectoryNodeCount)
7325 AFSPrint("AFSValidateDirList Count off Calc: %d Stored: %d\n",
7327 ObjectInfo->Specific.Directory.DirectoryNodeCount);
7329 ObjectInfo->Specific.Directory.DirectoryNodeCount = ulCount;
7338 AFSReferenceCacheFileObject()
7341 AFSDeviceExt *pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
7342 FILE_OBJECT *pCacheFileObject = NULL;
7344 AFSAcquireShared( &pRdrDevExt->Specific.RDR.CacheFileLock,
7347 pCacheFileObject = pRdrDevExt->Specific.RDR.CacheFileObject;
7349 if( pCacheFileObject != NULL)
7351 ObReferenceObject( pCacheFileObject);
7354 AFSReleaseResource( &pRdrDevExt->Specific.RDR.CacheFileLock);
7356 return pCacheFileObject;
7360 AFSReleaseCacheFileObject( IN PFILE_OBJECT CacheFileObject)
7363 ASSERT( CacheFileObject != NULL);
7365 ObDereferenceObject( CacheFileObject);
7371 AFSInitializeLibrary( IN AFSLibraryInitCB *LibraryInit)
7374 NTSTATUS ntStatus = STATUS_SUCCESS;
7375 AFSDeviceExt *pControlDevExt = NULL;
7376 ULONG ulTimeIncrement = 0;
7381 AFSControlDeviceObject = LibraryInit->AFSControlDeviceObject;
7383 AFSRDRDeviceObject = LibraryInit->AFSRDRDeviceObject;
7385 AFSServerName = LibraryInit->AFSServerName;
7387 AFSDebugFlags = LibraryInit->AFSDebugFlags;
7390 // Callbacks in the framework
7393 AFSProcessRequest = LibraryInit->AFSProcessRequest;
7395 AFSDbgLogMsg = LibraryInit->AFSDbgLogMsg;
7397 AFSAddConnectionEx = LibraryInit->AFSAddConnectionEx;
7399 AFSExAllocatePoolWithTag = LibraryInit->AFSExAllocatePoolWithTag;
7401 AFSExFreePool = LibraryInit->AFSExFreePool;
7403 AFSDumpTraceFilesFnc = LibraryInit->AFSDumpTraceFiles;
7405 AFSRetrieveAuthGroupFnc = LibraryInit->AFSRetrieveAuthGroup;
7407 AFSLibCacheManagerCallbacks = LibraryInit->AFSCacheManagerCallbacks;
7409 if( LibraryInit->AFSCacheBaseAddress != NULL)
7412 SetFlag( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE);
7414 AFSLibCacheBaseAddress = LibraryInit->AFSCacheBaseAddress;
7416 AFSLibCacheLength = LibraryInit->AFSCacheLength;
7420 // Initialize some flush parameters
7423 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
7425 ulTimeIncrement = KeQueryTimeIncrement();
7427 pControlDevExt->Specific.Control.ObjectLifeTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_OBJECT_LIFETIME / (ULONGLONG)ulTimeIncrement);
7428 pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart = AFS_SERVER_PURGE_DELAY;
7429 pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart /= ulTimeIncrement;
7430 pControlDevExt->Specific.Control.FcbFlushTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_SERVER_FLUSH_DELAY / (ULONGLONG)ulTimeIncrement);
7431 pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_EXTENT_REQUEST_TIME/(ULONGLONG)ulTimeIncrement);
7434 // Initialize the global root entry
7437 ntStatus = AFSInitVolume( NULL,
7438 &LibraryInit->GlobalRootFid,
7441 if( !NT_SUCCESS( ntStatus))
7444 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
7445 AFS_TRACE_LEVEL_ERROR,
7446 "AFSInitializeLibrary AFSInitVolume failure %08lX\n",
7449 try_return( ntStatus);
7452 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
7455 if( !NT_SUCCESS( ntStatus))
7458 AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
7459 AFS_TRACE_LEVEL_ERROR,
7460 "AFSInitializeLibrary AFSInitRootFcb failure %08lX\n",
7463 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
7465 try_return( ntStatus);
7469 // Update the node type code to AFS_ROOT_ALL
7472 AFSGlobalRoot->ObjectInformation.Fcb->Header.NodeTypeCode = AFS_ROOT_ALL;
7474 SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_ACTIVE_GLOBAL_ROOT);
7477 // Invalidate all known volumes since contact with the service and therefore
7478 // the file server was lost.
7481 AFSInvalidateAllVolumes();
7484 // Drop the locks acquired above
7487 AFSInitVolumeWorker( AFSGlobalRoot);
7489 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
7491 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Fcb->Header.Resource);
7505 NTSTATUS ntStatus = STATUS_SUCCESS;
7506 AFSDirectoryCB *pDirNode = NULL, *pLastDirNode = NULL;
7511 if( AFSGlobalDotDirEntry != NULL)
7514 AFSDeleteObjectInfo( AFSGlobalDotDirEntry->ObjectInformation);
7516 ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
7518 ExFreePool( AFSGlobalDotDirEntry->NonPaged);
7520 ExFreePool( AFSGlobalDotDirEntry);
7522 AFSGlobalDotDirEntry = NULL;
7525 if( AFSGlobalDotDotDirEntry != NULL)
7528 AFSDeleteObjectInfo( AFSGlobalDotDotDirEntry->ObjectInformation);
7530 ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
7532 ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
7534 ExFreePool( AFSGlobalDotDotDirEntry);
7536 AFSGlobalDotDotDirEntry = NULL;
7539 if( AFSSpecialShareNames != NULL)
7542 pDirNode = AFSSpecialShareNames;
7544 while( pDirNode != NULL)
7547 pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
7549 AFSDeleteObjectInfo( pDirNode->ObjectInformation);
7551 ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
7553 ExFreePool( pDirNode->NonPaged);
7555 ExFreePool( pDirNode);
7557 pDirNode = pLastDirNode;
7560 AFSSpecialShareNames = NULL;
7568 AFSDefaultLogMsg( IN ULONG Subsystem,
7574 NTSTATUS ntStatus = STATUS_SUCCESS;
7576 char chDebugBuffer[ 256];
7581 va_start( va_args, Format);
7583 ntStatus = RtlStringCbVPrintfA( chDebugBuffer,
7588 if( NT_SUCCESS( ntStatus))
7590 DbgPrint( chDebugBuffer);
7600 AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
7601 IN ULONG InputBufferLength,
7602 IN AFSStatusInfoCB *StatusInfo,
7603 OUT ULONG *ReturnLength)
7606 NTSTATUS ntStatus = STATUS_SUCCESS;
7607 AFSFcb *pFcb = NULL;
7608 AFSVolumeCB *pVolumeCB = NULL;
7609 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
7610 AFSObjectInfoCB *pObjectInfo = NULL;
7611 ULONGLONG ullIndex = 0;
7612 UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName, uniParsedName;
7613 AFSNameArrayHdr *pNameArray = NULL;
7614 AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
7621 // If we are given a FID then look up the entry by that, otherwise
7625 if( GetStatusInfo->FileID.Cell != 0 &&
7626 GetStatusInfo->FileID.Volume != 0 &&
7627 GetStatusInfo->FileID.Vnode != 0 &&
7628 GetStatusInfo->FileID.Unique != 0)
7631 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
7634 // Locate the volume node
7637 ullIndex = AFSCreateHighIndex( &GetStatusInfo->FileID);
7639 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
7641 (AFSBTreeEntry **)&pVolumeCB);
7643 if( pVolumeCB != NULL)
7646 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
7648 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7649 AFS_TRACE_LEVEL_VERBOSE,
7650 "AFSGetObjectStatus Increment count on volume %08lX Cnt %d\n",
7655 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
7657 if( !NT_SUCCESS( ntStatus) ||
7660 try_return( ntStatus = STATUS_INVALID_PARAMETER);
7663 if( AFSIsVolumeFID( &GetStatusInfo->FileID))
7666 pObjectInfo = &pVolumeCB->ObjectInformation;
7668 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
7670 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
7675 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
7678 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
7680 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7681 AFS_TRACE_LEVEL_VERBOSE,
7682 "AFSGetObjectStatus Decrement count on volume %08lX Cnt %d\n",
7686 ullIndex = AFSCreateLowIndex( &GetStatusInfo->FileID);
7688 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
7690 (AFSBTreeEntry **)&pObjectInfo);
7692 if( pObjectInfo != NULL)
7696 // Reference the node so it won't be torn down
7699 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
7701 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
7702 AFS_TRACE_LEVEL_VERBOSE,
7703 "AFSGetObjectStatus Increment count on object %08lX Cnt %d\n",
7708 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
7710 if( !NT_SUCCESS( ntStatus) ||
7711 pObjectInfo == NULL)
7713 try_return( ntStatus = STATUS_INVALID_PARAMETER);
7720 if( GetStatusInfo->FileNameLength == 0 ||
7721 InputBufferLength < (ULONG)(FIELD_OFFSET( AFSGetStatusInfoCB, FileName) + GetStatusInfo->FileNameLength))
7723 try_return( ntStatus = STATUS_INVALID_PARAMETER);
7726 uniFullPathName.Length = GetStatusInfo->FileNameLength;
7727 uniFullPathName.MaximumLength = uniFullPathName.Length;
7729 uniFullPathName.Buffer = (WCHAR *)GetStatusInfo->FileName;
7732 // This name should begin with the \afs server so parse it off and check it
7735 FsRtlDissectName( uniFullPathName,
7739 if( RtlCompareUnicodeString( &uniComponentName,
7743 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7744 AFS_TRACE_LEVEL_ERROR,
7745 "AFSGetObjectStatus Name %wZ contains invalid server name\n",
7748 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
7751 uniFullPathName = uniRemainingPath;
7753 uniParsedName = uniFullPathName;
7759 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
7762 if( pNameArray == NULL)
7764 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7767 pVolumeCB = AFSGlobalRoot;
7769 pParentDirEntry = AFSGlobalRoot->DirectoryCB;
7772 // Increment the ref count on the volume and dir entry for correct processing below
7775 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
7777 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7778 AFS_TRACE_LEVEL_VERBOSE,
7779 "AFSGetObjectStatus Increment count on volume %08lX Cnt %d\n",
7783 lCount = InterlockedIncrement( &pParentDirEntry->OpenReferenceCount);
7785 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
7786 AFS_TRACE_LEVEL_VERBOSE,
7787 "AFSGetObjectStatus Increment count on %wZ DE %p Ccb %p Cnt %d\n",
7788 &pParentDirEntry->NameInformation.FileName,
7793 ntStatus = AFSLocateNameEntry( NULL,
7798 AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL |
7799 AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL,
7805 if( !NT_SUCCESS( ntStatus))
7809 // The volume lock was released on failure above
7810 // Except for STATUS_OBJECT_NAME_NOT_FOUND
7813 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
7816 if( pVolumeCB != NULL)
7819 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
7821 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7822 AFS_TRACE_LEVEL_VERBOSE,
7823 "AFSGetObjectStatus Decrement count on volume %08lX Cnt %d\n",
7828 if( pDirectoryEntry != NULL)
7831 lCount = InterlockedDecrement( &pDirectoryEntry->OpenReferenceCount);
7833 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
7834 AFS_TRACE_LEVEL_VERBOSE,
7835 "AFSGetObjectStatus Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
7836 &pDirectoryEntry->NameInformation.FileName,
7844 lCount = InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
7846 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
7847 AFS_TRACE_LEVEL_VERBOSE,
7848 "AFSGetObjectStatus Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
7849 &pParentDirEntry->NameInformation.FileName,
7858 try_return( ntStatus);
7862 // Remove the reference made above
7865 lCount = InterlockedDecrement( &pDirectoryEntry->OpenReferenceCount);
7867 pObjectInfo = pDirectoryEntry->ObjectInformation;
7869 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
7871 if( pVolumeCB != NULL)
7874 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
7876 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7877 AFS_TRACE_LEVEL_VERBOSE,
7878 "AFSRetrieveFileAttributes Decrement2 count on volume %08lX Cnt %d\n",
7880 pVolumeCB->VolumeReferenceCount);
7885 // At this point we have an object info block, return the information
7888 StatusInfo->FileId = pObjectInfo->FileId;
7890 StatusInfo->TargetFileId = pObjectInfo->TargetFileId;
7892 StatusInfo->Expiration = pObjectInfo->Expiration;
7894 StatusInfo->DataVersion = pObjectInfo->DataVersion;
7896 StatusInfo->FileType = pObjectInfo->FileType;
7898 StatusInfo->ObjectFlags = pObjectInfo->Flags;
7900 StatusInfo->CreationTime = pObjectInfo->CreationTime;
7902 StatusInfo->LastAccessTime = pObjectInfo->LastAccessTime;
7904 StatusInfo->LastWriteTime = pObjectInfo->LastWriteTime;
7906 StatusInfo->ChangeTime = pObjectInfo->ChangeTime;
7908 StatusInfo->FileAttributes = pObjectInfo->FileAttributes;
7910 StatusInfo->EndOfFile = pObjectInfo->EndOfFile;
7912 StatusInfo->AllocationSize = pObjectInfo->AllocationSize;
7914 StatusInfo->EaSize = pObjectInfo->EaSize;
7916 StatusInfo->Links = pObjectInfo->Links;
7919 // Return the information length
7922 *ReturnLength = sizeof( AFSStatusInfoCB);
7926 if( pObjectInfo != NULL)
7929 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
7932 if( pNameArray != NULL)
7935 AFSFreeNameArray( pNameArray);
7943 AFSCheckSymlinkAccess( IN AFSDirectoryCB *ParentDirectoryCB,
7944 IN UNICODE_STRING *ComponentName)
7947 NTSTATUS ntStatus = STATUS_SUCCESS;
7948 AFSDirectoryCB *pDirEntry = NULL;
7956 // Search for the entry in the parent
7959 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7960 AFS_TRACE_LEVEL_VERBOSE_2,
7961 "AFSCheckSymlinkAccess Searching for entry %wZ case sensitive\n",
7964 ulCRC = AFSGenerateCRC( ComponentName,
7967 AFSAcquireShared( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
7970 AFSLocateCaseSensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7974 if( pDirEntry == NULL)
7978 // Missed so perform a case insensitive lookup
7981 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7982 AFS_TRACE_LEVEL_VERBOSE_2,
7983 "AFSCheckSymlinkAccess Searching for entry %wZ case insensitive\n",
7986 ulCRC = AFSGenerateCRC( ComponentName,
7989 AFSLocateCaseInsensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
7993 if( pDirEntry == NULL)
7997 // OK, if this component is a valid short name then try
7998 // a lookup in the short name tree
8001 if( RtlIsNameLegalDOS8Dot3( ComponentName,
8006 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8007 AFS_TRACE_LEVEL_VERBOSE_2,
8008 "AFSCheckSymlinkAccess Searching for entry %wZ short name\n",
8011 AFSLocateShortNameDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.ShortNameTree,
8018 if( pDirEntry != NULL)
8020 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
8023 AFSReleaseResource( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
8025 if( pDirEntry == NULL)
8028 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8029 AFS_TRACE_LEVEL_VERBOSE_2,
8030 "AFSCheckSymlinkAccess Failed to locate entry %wZ\n",
8033 try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
8037 // We have the symlink object but previously failed to process it so return access
8041 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8042 AFS_TRACE_LEVEL_VERBOSE_2,
8043 "AFSCheckSymlinkAccess Failing symlink access to entry %wZ REPARSE_POINT_NOT_RESOLVED\n",
8046 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
8048 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
8059 AFSRetrieveFinalComponent( IN UNICODE_STRING *FullPathName,
8060 OUT UNICODE_STRING *ComponentName)
8063 NTSTATUS ntStatus = STATUS_SUCCESS;
8064 UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName;
8066 uniFullPathName = *FullPathName;
8071 FsRtlDissectName( uniFullPathName,
8075 if( uniRemainingPath.Length == 0)
8080 uniFullPathName = uniRemainingPath;
8083 if( uniComponentName.Length > 0)
8085 *ComponentName = uniComponentName;
8092 AFSDumpTraceFiles_Default()
8098 AFSValidNameFormat( IN UNICODE_STRING *FileName)
8101 BOOLEAN bIsValidName = TRUE;
8107 while( usIndex < FileName->Length/sizeof( WCHAR))
8110 if( FileName->Buffer[ usIndex] == L':' ||
8111 FileName->Buffer[ usIndex] == L'*' ||
8112 FileName->Buffer[ usIndex] == L'?' ||
8113 FileName->Buffer[ usIndex] == L'"' ||
8114 FileName->Buffer[ usIndex] == L'<' ||
8115 FileName->Buffer[ usIndex] == L'>')
8117 bIsValidName = FALSE;
8125 return bIsValidName;
8129 AFSCreateDefaultSecurityDescriptor()
8132 NTSTATUS ntStatus = STATUS_SUCCESS;
8134 ULONG ulSACLSize = 0;
8135 SYSTEM_MANDATORY_LABEL_ACE* pACE = NULL;
8136 ULONG ulACESize = 0;
8137 SECURITY_DESCRIPTOR *pSecurityDescr = NULL;
8138 ULONG ulSDLength = 0;
8139 SECURITY_DESCRIPTOR *pRelativeSecurityDescr = NULL;
8140 PSID pWorldSID = NULL;
8141 ULONG *pulSubAuthority = NULL;
8142 ULONG ulWorldSIDLEngth = 0;
8147 ulWorldSIDLEngth = RtlLengthRequiredSid( 1);
8149 pWorldSID = (PSID)ExAllocatePoolWithTag( PagedPool,
8151 AFS_GENERIC_MEMORY_29_TAG);
8153 if( pWorldSID == NULL)
8155 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate World SID\n");
8156 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8159 RtlZeroMemory( pWorldSID,
8162 RtlInitializeSid( pWorldSID,
8163 &SeWorldSidAuthority,
8166 pulSubAuthority = RtlSubAuthoritySid(pWorldSID, 0);
8167 *pulSubAuthority = SECURITY_WORLD_RID;
8169 if( AFSRtlSetSaclSecurityDescriptor == NULL)
8172 AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor == NULL\n");
8177 ulACESize = sizeof( SYSTEM_MANDATORY_LABEL_ACE) + 128;
8179 pACE = (SYSTEM_MANDATORY_LABEL_ACE *)ExAllocatePoolWithTag( PagedPool,
8181 AFS_GENERIC_MEMORY_29_TAG);
8186 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8188 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8191 RtlZeroMemory( pACE,
8194 pACE->Header.AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
8195 pACE->Header.AceType = SYSTEM_MANDATORY_LABEL_ACE_TYPE;
8196 pACE->Header.AceSize = FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + (USHORT)RtlLengthSid( SeExports->SeLowMandatorySid);
8197 pACE->Mask = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP;
8199 RtlCopySid( RtlLengthSid( SeExports->SeLowMandatorySid),
8201 SeExports->SeLowMandatorySid);
8203 ulSACLSize = sizeof(ACL) + RtlLengthSid( SeExports->SeLowMandatorySid) +
8204 FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + ulACESize;
8206 pSACL = (PACL)ExAllocatePoolWithTag( PagedPool,
8208 AFS_GENERIC_MEMORY_29_TAG);
8213 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8215 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8218 ntStatus = RtlCreateAcl( pSACL,
8222 if( !NT_SUCCESS( ntStatus))
8225 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateAcl ntStatus %08lX\n",
8228 try_return( ntStatus);
8231 ntStatus = RtlAddAce( pSACL,
8235 pACE->Header.AceSize);
8237 if( !NT_SUCCESS( ntStatus))
8240 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAddAce ntStatus %08lX\n",
8243 try_return( ntStatus);
8247 pSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
8248 sizeof( SECURITY_DESCRIPTOR),
8249 AFS_GENERIC_MEMORY_27_TAG);
8251 if( pSecurityDescr == NULL)
8254 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8256 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8259 ntStatus = RtlCreateSecurityDescriptor( pSecurityDescr,
8260 SECURITY_DESCRIPTOR_REVISION);
8262 if( !NT_SUCCESS( ntStatus))
8265 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateSecurityDescriptor ntStatus %08lX\n",
8268 try_return( ntStatus);
8271 if( AFSRtlSetSaclSecurityDescriptor != NULL)
8273 ntStatus = AFSRtlSetSaclSecurityDescriptor( pSecurityDescr,
8278 if( !NT_SUCCESS( ntStatus))
8281 AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor ntStatus %08lX\n",
8284 try_return( ntStatus);
8289 // Add in the group and owner to the SD
8292 if( AFSRtlSetGroupSecurityDescriptor != NULL)
8294 ntStatus = AFSRtlSetGroupSecurityDescriptor( pSecurityDescr,
8298 if( !NT_SUCCESS( ntStatus))
8301 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetGroupSecurityDescriptor failed ntStatus %08lX\n",
8304 try_return( ntStatus);
8308 ntStatus = RtlSetOwnerSecurityDescriptor( pSecurityDescr,
8312 if( !NT_SUCCESS( ntStatus))
8315 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetOwnerSecurityDescriptor failed ntStatus %08lX\n",
8318 try_return( ntStatus);
8321 if( !RtlValidSecurityDescriptor( pSecurityDescr))
8324 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlValidSecurityDescriptor NOT\n");
8326 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8329 pRelativeSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
8331 AFS_GENERIC_MEMORY_27_TAG);
8333 if( pRelativeSecurityDescr == NULL)
8336 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8338 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8341 ulSDLength = PAGE_SIZE;
8343 ntStatus = RtlAbsoluteToSelfRelativeSD( pSecurityDescr,
8344 pRelativeSecurityDescr,
8347 if( !NT_SUCCESS( ntStatus))
8350 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAbsoluteToSelfRelativeSD ntStatus %08lX\n",
8353 try_return( ntStatus);
8356 AFSDefaultSD = pRelativeSecurityDescr;
8360 if( !NT_SUCCESS( ntStatus))
8363 if( pRelativeSecurityDescr != NULL)
8365 ExFreePool( pRelativeSecurityDescr);
8369 if( pSecurityDescr != NULL)
8371 ExFreePool( pSecurityDescr);
8384 if( pWorldSID != NULL)
8386 ExFreePool( pWorldSID);
8394 AFSRetrieveParentPath( IN UNICODE_STRING *FullFileName,
8395 OUT UNICODE_STRING *ParentPath)
8400 *ParentPath = *FullFileName;
8403 // If the final character is a \, jump over it
8406 if( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] == L'\\')
8408 ParentPath->Length -= sizeof( WCHAR);
8411 while( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] != L'\\')
8413 ParentPath->Length -= sizeof( WCHAR);
8417 // And the separator
8420 ParentPath->Length -= sizeof( WCHAR);
8426 AFSRetrieveValidAuthGroup( IN AFSFcb *Fcb,
8427 IN AFSObjectInfoCB *ObjectInfo,
8428 IN BOOLEAN WriteAccess,
8429 OUT GUID *AuthGroup)
8432 NTSTATUS ntStatus = STATUS_SUCCESS;
8433 GUID stAuthGroup, stZeroAuthGroup;
8434 BOOLEAN bFoundAuthGroup = FALSE;
8435 AFSCcb *pCcb = NULL;
8441 RtlZeroMemory( &stAuthGroup,
8444 RtlZeroMemory( &stZeroAuthGroup,
8450 if( ObjectInfo != NULL &&
8451 ObjectInfo->Fcb != NULL)
8453 pFcb = ObjectInfo->Fcb;
8460 AFSAcquireShared( &Fcb->NPFcb->CcbListLock,
8463 pCcb = Fcb->CcbListHead;
8465 while( pCcb != NULL)
8469 pCcb->GrantedAccess & FILE_WRITE_DATA)
8471 RtlCopyMemory( &stAuthGroup,
8475 bFoundAuthGroup = TRUE;
8479 else if( pCcb->GrantedAccess & FILE_READ_DATA)
8482 // At least get the read-only access
8485 RtlCopyMemory( &stAuthGroup,
8489 bFoundAuthGroup = TRUE;
8492 pCcb = (AFSCcb *)pCcb->ListEntry.fLink;
8495 AFSReleaseResource( &Fcb->NPFcb->CcbListLock);
8498 if( !bFoundAuthGroup)
8501 AFSRetrieveAuthGroupFnc( (ULONGLONG)PsGetCurrentProcessId(),
8502 (ULONGLONG)PsGetCurrentThreadId(),
8505 if( RtlCompareMemory( &stZeroAuthGroup,
8507 sizeof( GUID)) == sizeof( GUID))
8510 DbgPrint("AFSRetrieveValidAuthGroup Failed to locate PAG\n");
8512 try_return( ntStatus = STATUS_ACCESS_DENIED);
8516 RtlCopyMemory( AuthGroup,
8529 AFSPerformObjectInvalidate( IN AFSObjectInfoCB *ObjectInfo,
8530 IN ULONG InvalidateReason)
8533 NTSTATUS ntStatus = STATUS_SUCCESS;
8534 IO_STATUS_BLOCK stIoStatus;
8537 ULONG ulProcessCount = 0;
8543 switch( InvalidateReason)
8546 case AFS_INVALIDATE_DELETED:
8549 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
8550 ObjectInfo->Fcb != NULL)
8555 // Clear out the extents
8556 // And get rid of them (note this involves waiting
8557 // for any writes or reads to the cache to complete)
8560 (VOID) AFSTearDownFcbExtents( ObjectInfo->Fcb,
8567 case AFS_INVALIDATE_DATA_VERSION:
8570 LARGE_INTEGER liCurrentOffset = {0,0};
8571 LARGE_INTEGER liFlushLength = {0,0};
8572 ULONG ulFlushLength = 0;
8573 BOOLEAN bLocked = FALSE;
8574 BOOLEAN bExtentsLocked = FALSE;
8575 BOOLEAN bCleanExtents = FALSE;
8577 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
8578 ObjectInfo->Fcb != NULL)
8581 AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Resource,
8586 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
8587 AFS_TRACE_LEVEL_VERBOSE,
8588 "AFSPerformObjectInvalidate Acquiring Fcb extents lock %08lX SHARED %08lX\n",
8589 &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
8590 PsGetCurrentThread());
8592 AFSAcquireShared( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
8595 bExtentsLocked = TRUE;
8598 // There are several possibilities here:
8600 // 0. If there are no extents or all of the extents are dirty, do nothing.
8602 // 1. There could be nothing dirty and an open reference count of zero
8603 // in which case we can just tear down all of the extents without
8604 // holding any resources.
8606 // 2. There could be nothing dirty and a non-zero open reference count
8607 // in which case we can issue a CcPurge against the entire file
8608 // while holding just the Fcb Resource.
8610 // 3. There can be dirty extents in which case we need to identify
8611 // the non-dirty ranges and then perform a CcPurge on just the
8612 // non-dirty ranges while holding just the Fcb Resource.
8615 if ( ObjectInfo->Fcb->Specific.File.ExtentCount != ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount)
8618 if ( ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount == 0)
8621 if ( ObjectInfo->Fcb->OpenReferenceCount == 0)
8624 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
8626 bExtentsLocked = FALSE;
8628 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
8632 (VOID) AFSTearDownFcbExtents( ObjectInfo->Fcb,
8641 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
8643 bExtentsLocked = FALSE;
8645 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
8650 SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
8655 bCleanExtents = TRUE;
8658 __except( EXCEPTION_EXECUTE_HANDLER)
8661 ntStatus = GetExceptionCode();
8665 "EXCEPTION - AFSPerformObjectInvalidate Status %08lX\n",
8674 // Must build a list of non-dirty ranges from the beginning of the file
8675 // to the end. There can be at most (Fcb->Specific.File.ExtentsDirtyCount + 1)
8676 // ranges. In all but the most extreme random data write scenario there will
8677 // be significantly fewer.
8679 // For each range we need offset and size.
8682 AFSByteRange * ByteRangeList = NULL;
8683 ULONG ulByteRangeCount = 0;
8685 BOOLEAN bPurgeOnClose = FALSE;
8690 ulByteRangeCount = AFSConstructCleanByteRangeList( ObjectInfo->Fcb,
8693 if ( ByteRangeList != NULL ||
8694 ulByteRangeCount == 0)
8697 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
8699 bExtentsLocked = FALSE;
8701 for ( ulIndex = 0; ulIndex < ulByteRangeCount; ulIndex++)
8708 ulSize = ByteRangeList[ulIndex].Length.QuadPart > DWORD_MAX ? DWORD_MAX : ByteRangeList[ulIndex].Length.LowPart;
8710 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
8711 &ByteRangeList[ulIndex].FileOffset,
8716 bPurgeOnClose = TRUE;
8721 bCleanExtents = TRUE;
8724 ByteRangeList[ulIndex].Length.QuadPart -= ulSize;
8726 ByteRangeList[ulIndex].FileOffset.QuadPart += ulSize;
8728 } while ( ByteRangeList[ulIndex].Length.QuadPart > 0);
8735 // We couldn't allocate the memory to build the purge list
8736 // so just walk the extent list while holding the ExtentsList Resource.
8737 // This could deadlock but we do not have much choice.
8740 le = ObjectInfo->Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
8744 ulCount = (ULONG)ObjectInfo->Fcb->Specific.File.ExtentCount;
8748 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
8750 while( ulProcessCount < ulCount)
8752 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
8754 if( !BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
8756 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
8757 &pEntry->FileOffset,
8762 bPurgeOnClose = TRUE;
8767 bCleanExtents = TRUE;
8771 if( liCurrentOffset.QuadPart < pEntry->FileOffset.QuadPart)
8774 liFlushLength.QuadPart = pEntry->FileOffset.QuadPart - liCurrentOffset.QuadPart;
8776 while( liFlushLength.QuadPart > 0)
8779 if( liFlushLength.QuadPart > 512 * 1024000)
8781 ulFlushLength = 512 * 1024000;
8785 ulFlushLength = liFlushLength.LowPart;
8788 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
8794 bPurgeOnClose = TRUE;
8799 bCleanExtents = TRUE;
8802 liFlushLength.QuadPart -= ulFlushLength;
8806 liCurrentOffset.QuadPart = pEntry->FileOffset.QuadPart + pEntry->Size;
8814 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
8820 bPurgeOnClose = TRUE;
8825 bCleanExtents = TRUE;
8832 SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
8836 __except( EXCEPTION_EXECUTE_HANDLER)
8839 ntStatus = GetExceptionCode();
8843 "EXCEPTION - AFSPerformObjectInvalidate Status %08lX\n",
8849 if ( bExtentsLocked)
8852 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
8858 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
8864 AFSReleaseCleanExtents( ObjectInfo->Fcb,
8873 if( ObjectInfo != NULL)
8875 InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);