2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011, 2012, 2013 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
16 * nor the names of their contributors may be used to endorse or promote
17 * products derived from this software without specific prior written
18 * permission from Kernel Drivers, LLC and Your File System, Inc.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
24 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 // File: AFSGeneric.cpp
37 #include "AFSCommon.h"
40 // Function: AFSExceptionFilter
44 // This function is the exception handler
48 // A status is returned for the function
52 AFSExceptionFilter( IN CHAR *FunctionString,
54 IN PEXCEPTION_POINTERS ExceptPtrs)
57 UNREFERENCED_PARAMETER(Code);
58 PEXCEPTION_RECORD ExceptRec;
64 ExceptRec = ExceptPtrs->ExceptionRecord;
66 Context = ExceptPtrs->ContextRecord;
70 "AFSExceptionFilter (Library) - EXR %p CXR %p Function %s Code %08lX Address %p Routine %p\n",
74 ExceptRec->ExceptionCode,
75 ExceptRec->ExceptionAddress,
76 (void *)AFSExceptionFilter));
78 DbgPrint("**** Exception Caught in AFS Redirector Library ****\n");
80 DbgPrint("\n\nPerform the following WnDbg Cmds:\n");
81 DbgPrint("\n\t.exr %p ; .cxr %p\n\n", ExceptRec, Context);
83 DbgPrint("**** Exception Complete from AFS Redirector Library ****\n");
85 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION))
88 KeBugCheck( (ULONG)-2);
96 __except( EXCEPTION_EXECUTE_HANDLER)
102 return EXCEPTION_EXECUTE_HANDLER;
106 // Function: AFSLibExAllocatePoolWithTag()
108 // Purpose: Allocate Pool Memory. If BugCheck Exception flag
109 // is configured on, then bugcheck the system if
110 // a memory allocation fails. The routine should be
111 // used for all memory allocations that are to be freed
112 // when the library is unloaded. Memory allocations that
113 // are to survive library unload and reload should be
114 // performed using AFSExAllocatePoolWithTag() which is
115 // provided by the AFS Framework.
118 // POOL_TYPE PoolType - Paged or NonPaged
119 // SIZE_T NumberOfBytes - requested allocation size
120 // ULONG Tag - Pool Allocation Tag to be applied for tracking
123 // void * - the memory allocation
127 AFSLibExAllocatePoolWithTag( IN POOL_TYPE PoolType,
128 IN SIZE_T NumberOfBytes,
132 void *pBuffer = NULL;
134 pBuffer = ExAllocatePoolWithTag( PoolType,
141 if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION))
144 KeBugCheck( (ULONG)-2);
151 "AFSLibExAllocatePoolWithTag failure Type %08lX Size %08lX Tag %08lX %08lX\n",
155 PsGetCurrentThread()));
165 // Function: AFSAcquireExcl()
167 // Purpose: Called to acquire a resource exclusive with optional wait
170 // PERESOURCE Resource - Resource to acquire
171 // BOOLEAN Wait - Whether to block
174 // BOOLEAN - Whether the mask was acquired
178 AFSAcquireExcl( IN PERESOURCE Resource,
182 BOOLEAN bStatus = FALSE;
185 // Normal kernel APCs must be disabled before calling
186 // ExAcquireResourceExclusiveLite. Otherwise a bugcheck occurs.
189 KeEnterCriticalRegion();
191 bStatus = ExAcquireResourceExclusiveLite( Resource,
197 KeLeaveCriticalRegion();
204 AFSAcquireSharedStarveExclusive( IN PERESOURCE Resource,
208 BOOLEAN bStatus = FALSE;
210 KeEnterCriticalRegion();
212 bStatus = ExAcquireSharedStarveExclusive( Resource,
218 KeLeaveCriticalRegion();
225 // Function: AFSAcquireShared()
227 // Purpose: Called to acquire a resource shared with optional wait
230 // PERESOURCE Resource - Resource to acquire
231 // BOOLEAN Wait - Whether to block
234 // BOOLEAN - Whether the mask was acquired
238 AFSAcquireShared( IN PERESOURCE Resource,
242 BOOLEAN bStatus = FALSE;
244 KeEnterCriticalRegion();
246 bStatus = ExAcquireResourceSharedLite( Resource,
252 KeLeaveCriticalRegion();
259 // Function: AFSReleaseResource()
261 // Purpose: Called to release a resource
264 // PERESOURCE Resource - Resource to release
271 AFSReleaseResource( IN PERESOURCE Resource)
274 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
275 AFS_TRACE_LEVEL_VERBOSE,
276 "AFSReleaseResource Releasing lock %p Thread %08lX\n",
278 PsGetCurrentThread()));
280 ExReleaseResourceLite( Resource);
282 KeLeaveCriticalRegion();
288 AFSConvertToShared( IN PERESOURCE Resource)
291 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
292 AFS_TRACE_LEVEL_VERBOSE,
293 "AFSConvertToShared Converting lock %p Thread %08lX\n",
295 PsGetCurrentThread()));
297 ExConvertExclusiveToSharedLite( Resource);
303 // Function: AFSCompleteRequest
307 // This function completes irps
311 // A status is returned for the function
315 AFSCompleteRequest( IN PIRP Irp,
319 Irp->IoStatus.Status = Status;
321 IoCompleteRequest( Irp,
328 // Function: AFSGenerateCRC
332 // Given a device and filename this function generates a CRC
336 // A status is returned for the function
340 AFSGenerateCRC( IN PUNICODE_STRING FileName,
341 IN BOOLEAN UpperCaseName)
345 NTSTATUS ntStatus = STATUS_SUCCESS;
347 ntStatus = RtlHashUnicodeString( FileName,
349 HASH_STRING_ALGORITHM_DEFAULT,
352 if( !NT_SUCCESS( ntStatus))
361 AFSLockSystemBuffer( IN PIRP Irp,
365 void *pAddress = NULL;
367 if( Irp->MdlAddress != NULL)
370 pAddress = MmGetSystemAddressForMdlSafe( Irp->MdlAddress,
373 else if( Irp->AssociatedIrp.SystemBuffer != NULL)
376 pAddress = Irp->AssociatedIrp.SystemBuffer;
378 else if( Irp->UserBuffer != NULL)
381 Irp->MdlAddress = IoAllocateMdl( Irp->UserBuffer,
387 if( Irp->MdlAddress != NULL)
391 // Lock the new Mdl in memory.
396 PIO_STACK_LOCATION pIoStack;
397 pIoStack = IoGetCurrentIrpStackLocation( Irp);
400 MmProbeAndLockPages( Irp->MdlAddress, KernelMode,
401 (pIoStack->MajorFunction == IRP_MJ_READ) ? IoWriteAccess : IoReadAccess);
403 pAddress = MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority );
406 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
409 AFSDumpTraceFilesFnc();
411 IoFreeMdl( Irp->MdlAddress );
412 Irp->MdlAddress = NULL;
422 AFSLockUserBuffer( IN void *UserBuffer,
423 IN ULONG BufferLength,
427 NTSTATUS ntStatus = STATUS_SUCCESS;
428 void *pAddress = NULL;
434 pMdl = IoAllocateMdl( UserBuffer,
443 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
447 // Lock the new Mdl in memory.
453 MmProbeAndLockPages( pMdl,
457 pAddress = MmGetSystemAddressForMdlSafe( pMdl,
460 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
463 AFSDumpTraceFilesFnc();
485 AFSMapToService( IN PIRP Irp,
489 NTSTATUS ntStatus = STATUS_SUCCESS;
490 void *pMappedBuffer = NULL;
491 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
497 if( pDevExt->Specific.Control.ServiceProcess == NULL)
500 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
503 if( Irp->MdlAddress == NULL)
506 if( AFSLockSystemBuffer( Irp,
510 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
515 // Attach to the service process for mapping
518 KeStackAttachProcess( pDevExt->Specific.Control.ServiceProcess,
519 (PRKAPC_STATE)&stApcState);
521 pMappedBuffer = MmMapLockedPagesSpecifyCache( Irp->MdlAddress,
528 KeUnstackDetachProcess( (PRKAPC_STATE)&stApcState);
535 return pMappedBuffer;
539 AFSUnmapServiceMappedBuffer( IN void *MappedBuffer,
543 NTSTATUS ntStatus = STATUS_SUCCESS;
544 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
550 if( pDevExt->Specific.Control.ServiceProcess == NULL)
553 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
560 // Attach to the service process for mapping
563 KeStackAttachProcess( pDevExt->Specific.Control.ServiceProcess,
564 (PRKAPC_STATE)&stApcState);
566 MmUnmapLockedPages( MappedBuffer,
569 KeUnstackDetachProcess( (PRKAPC_STATE)&stApcState);
581 AFSInitializeLibraryDevice()
584 NTSTATUS ntStatus = STATUS_SUCCESS;
585 AFSDeviceExt *pDeviceExt = NULL;
590 pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
593 // The PIOCtl file name
596 RtlInitUnicodeString( &AFSPIOCtlName,
597 AFS_PIOCTL_FILE_INTERFACE_NAME);
600 // And the global root share name
603 RtlInitUnicodeString( &AFSGlobalRootName,
604 AFS_GLOBAL_ROOT_SHARE_NAME);
612 AFSRemoveLibraryDevice()
615 NTSTATUS ntStatus = STATUS_SUCCESS;
626 AFSDefaultDispatch( IN PDEVICE_OBJECT DeviceObject,
630 UNREFERENCED_PARAMETER(DeviceObject);
631 NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
633 AFSCompleteRequest( Irp,
640 AFSInitializeGlobalDirectoryEntries()
643 NTSTATUS ntStatus = STATUS_SUCCESS;
644 AFSDirectoryCB *pDirNode = NULL;
645 ULONG ulEntryLength = 0;
646 AFSObjectInfoCB *pObjectInfoCB = NULL;
647 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
654 // Initialize the global . entry
657 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
660 if( pObjectInfoCB == NULL)
663 AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
664 AFS_TRACE_LEVEL_ERROR,
665 "AFSInitializeGlobalDirectory AFSAllocateObjectInfo failure %08lX\n",
668 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
671 lCount = AFSObjectInfoIncrement( pObjectInfoCB,
672 AFS_OBJECT_REFERENCE_GLOBAL);
674 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
675 AFS_TRACE_LEVEL_VERBOSE,
676 "AFSInitializeGlobalDirectoryEntries Increment count on object %p Cnt %d\n",
680 ntStatus = STATUS_SUCCESS;
682 ulEntryLength = sizeof( AFSDirectoryCB) +
685 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
689 if( pDirNode == NULL)
692 AFSDeleteObjectInfo( &pObjectInfoCB);
694 AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
695 AFS_TRACE_LEVEL_ERROR,
696 "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_TAG allocation failure\n"));
698 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
701 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
702 AFS_TRACE_LEVEL_VERBOSE,
703 "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_TAG allocated %p\n",
706 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
707 sizeof( AFSNonPagedDirectoryCB),
708 AFS_DIR_ENTRY_NP_TAG);
710 if( pNonPagedDirEntry == NULL)
713 ExFreePool( pDirNode);
715 AFSDeleteObjectInfo( &pObjectInfoCB);
717 AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
718 AFS_TRACE_LEVEL_ERROR,
719 "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_NP_TAG allocation failure\n"));
721 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
724 RtlZeroMemory( pDirNode,
727 RtlZeroMemory( pNonPagedDirEntry,
728 sizeof( AFSNonPagedDirectoryCB));
730 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
732 pDirNode->NonPaged = pNonPagedDirEntry;
734 pDirNode->ObjectInformation = pObjectInfoCB;
740 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE | AFS_DIR_ENTRY_FAKE | AFS_DIR_ENTRY_VALID);
742 pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_DOT_INDEX;
745 // Setup the names in the entry
748 pDirNode->NameInformation.FileName.Length = sizeof( WCHAR);
750 pDirNode->NameInformation.FileName.MaximumLength = sizeof( WCHAR);
752 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
754 pDirNode->NameInformation.FileName.Buffer[ 0] = L'.';
757 // Populate the rest of the data
760 pObjectInfoCB->FileType = AFS_FILE_TYPE_DIRECTORY;
762 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
764 AFSGlobalDotDirEntry = pDirNode;
770 pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
773 if( pObjectInfoCB == NULL)
776 AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
777 AFS_TRACE_LEVEL_ERROR,
778 "AFSInitializeGlobalDirectory AFSAllocateObjectInfo (2) failure %08lX\n",
781 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
784 lCount = AFSObjectInfoIncrement( pObjectInfoCB,
785 AFS_OBJECT_REFERENCE_GLOBAL);
787 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
788 AFS_TRACE_LEVEL_VERBOSE,
789 "AFSInitializeGlobalDirectoryEntries Increment count on object %p Cnt %d\n",
793 ntStatus = STATUS_SUCCESS;
795 ulEntryLength = sizeof( AFSDirectoryCB) +
796 ( 2 * sizeof( WCHAR));
798 pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
802 if( pDirNode == NULL)
805 AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
806 AFS_TRACE_LEVEL_ERROR,
807 "AFSInitializeGlobalDirectoryEntries AFS_DIR_ENTRY_TAG allocation failure\n"));
809 AFSDeleteObjectInfo( &pObjectInfoCB);
811 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
814 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
815 AFS_TRACE_LEVEL_VERBOSE,
816 "AFSInitializeGlobalDirectoryEntries AFS_DIR_ENTRY_TAG allocated %p\n",
819 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
820 sizeof( AFSNonPagedDirectoryCB),
821 AFS_DIR_ENTRY_NP_TAG);
823 if( pNonPagedDirEntry == NULL)
826 ExFreePool( pDirNode);
828 AFSDeleteObjectInfo( &pObjectInfoCB);
830 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
833 RtlZeroMemory( pDirNode,
836 RtlZeroMemory( pNonPagedDirEntry,
837 sizeof( AFSNonPagedDirectoryCB));
839 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
841 pDirNode->NonPaged = pNonPagedDirEntry;
843 pDirNode->ObjectInformation = pObjectInfoCB;
849 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE | AFS_DIR_ENTRY_FAKE | AFS_DIR_ENTRY_VALID);
851 pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX;
854 // Setup the names in the entry
857 pDirNode->NameInformation.FileName.Length = 2 * sizeof( WCHAR);
859 pDirNode->NameInformation.FileName.MaximumLength = 2 * sizeof( WCHAR);
861 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
863 pDirNode->NameInformation.FileName.Buffer[ 0] = L'.';
865 pDirNode->NameInformation.FileName.Buffer[ 1] = L'.';
868 // Populate the rest of the data
871 pObjectInfoCB->FileType = AFS_FILE_TYPE_DIRECTORY;
873 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
875 AFSGlobalDotDotDirEntry = pDirNode;
879 if( !NT_SUCCESS( ntStatus))
882 if( AFSGlobalDotDirEntry != NULL)
885 AFSDeleteObjectInfo( &AFSGlobalDotDirEntry->ObjectInformation);
887 ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
889 ExFreePool( AFSGlobalDotDirEntry->NonPaged);
891 ExFreePool( AFSGlobalDotDirEntry);
893 AFSGlobalDotDirEntry = NULL;
896 if( AFSGlobalDotDotDirEntry != NULL)
899 AFSDeleteObjectInfo( &AFSGlobalDotDotDirEntry->ObjectInformation);
901 ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
903 ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
905 ExFreePool( AFSGlobalDotDotDirEntry);
907 AFSGlobalDotDotDirEntry = NULL;
916 AFSInitDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
917 IN PUNICODE_STRING FileName,
918 IN PUNICODE_STRING TargetName,
919 IN AFSDirEnumEntry *DirEnumEntry,
923 AFSDirectoryCB *pDirNode = NULL;
924 NTSTATUS ntStatus = STATUS_SUCCESS;
925 ULONG ulEntryLength = 0;
926 AFSObjectInfoCB *pObjectInfoCB = NULL;
927 BOOLEAN bAllocatedObjectCB = FALSE;
928 ULONGLONG ullIndex = 0;
929 AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
935 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
936 AFS_TRACE_LEVEL_VERBOSE,
937 "AFSInitDirEntry Initializing entry %wZ parent FID %08lX-%08lX-%08lX-%08lX\n",
939 ParentObjectInfo->FileId.Cell,
940 ParentObjectInfo->FileId.Volume,
941 ParentObjectInfo->FileId.Vnode,
942 ParentObjectInfo->FileId.Unique));
945 // First thing is to locate/create our object information block
949 AFSAcquireExcl( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
952 ullIndex = AFSCreateLowIndex( &DirEnumEntry->FileId);
954 ntStatus = AFSLocateHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
956 (AFSBTreeEntry **)&pObjectInfoCB);
958 if( !NT_SUCCESS( ntStatus) ||
959 pObjectInfoCB == NULL)
963 // Allocate our object info cb
966 pObjectInfoCB = AFSAllocateObjectInfo( ParentObjectInfo,
969 if( pObjectInfoCB == NULL)
972 AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
974 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
977 bAllocatedObjectCB = TRUE;
979 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
980 AFS_TRACE_LEVEL_VERBOSE,
981 "AFSInitDirEntry initialized object %p Parent Object %p for %wZ\n",
987 lCount = AFSObjectInfoIncrement( pObjectInfoCB,
988 AFS_OBJECT_REFERENCE_DIRENTRY);
990 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
991 AFS_TRACE_LEVEL_VERBOSE,
992 "AFSInitDirEntry Increment count on object %p Cnt %d\n",
996 AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
998 ntStatus = STATUS_SUCCESS;
1000 ulEntryLength = sizeof( AFSDirectoryCB) +
1003 if( TargetName != NULL)
1006 ulEntryLength += TargetName->Length;
1009 pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
1013 if( pDirNode == NULL)
1016 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1019 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1020 AFS_TRACE_LEVEL_VERBOSE,
1021 "AFSInitDirEntry AFS_DIR_ENTRY_TAG allocated %p\n",
1024 pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
1025 sizeof( AFSNonPagedDirectoryCB),
1026 AFS_DIR_ENTRY_NP_TAG);
1028 if( pNonPagedDirEntry == NULL)
1031 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1034 RtlZeroMemory( pDirNode,
1037 RtlZeroMemory( pNonPagedDirEntry,
1038 sizeof( AFSNonPagedDirectoryCB));
1040 ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
1042 pDirNode->NonPaged = pNonPagedDirEntry;
1044 pDirNode->ObjectInformation = pObjectInfoCB;
1047 // Set valid entry and NOT_IN_PARENT flag
1050 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1052 pDirNode->FileIndex = FileIndex;
1055 // Setup the names in the entry
1058 if( FileName->Length > 0)
1061 pDirNode->NameInformation.FileName.Length = FileName->Length;
1063 pDirNode->NameInformation.FileName.MaximumLength = FileName->Length;
1065 pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
1067 RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
1069 pDirNode->NameInformation.FileName.Length);
1072 // Create a CRC for the file
1075 pDirNode->CaseSensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1078 pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1082 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1083 AFS_TRACE_LEVEL_VERBOSE,
1084 "AFSInitDirEntry Initialized DE %p for %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1087 ParentObjectInfo->FileId.Cell,
1088 ParentObjectInfo->FileId.Volume,
1089 ParentObjectInfo->FileId.Vnode,
1090 ParentObjectInfo->FileId.Unique));
1092 if( TargetName != NULL &&
1093 TargetName->Length > 0)
1096 pDirNode->NameInformation.TargetName.Length = TargetName->Length;
1098 pDirNode->NameInformation.TargetName.MaximumLength = pDirNode->NameInformation.TargetName.Length;
1100 pDirNode->NameInformation.TargetName.Buffer = (WCHAR *)((char *)pDirNode +
1101 sizeof( AFSDirectoryCB) +
1102 pDirNode->NameInformation.FileName.Length);
1104 RtlCopyMemory( pDirNode->NameInformation.TargetName.Buffer,
1106 pDirNode->NameInformation.TargetName.Length);
1110 // If we allocated the object information cb then update the information
1113 if( bAllocatedObjectCB)
1117 // Populate the rest of the data
1120 pObjectInfoCB->FileId = DirEnumEntry->FileId;
1122 pObjectInfoCB->TargetFileId = DirEnumEntry->TargetFileId;
1124 pObjectInfoCB->FileType = DirEnumEntry->FileType;
1126 pObjectInfoCB->CreationTime = DirEnumEntry->CreationTime;
1128 pObjectInfoCB->LastAccessTime = DirEnumEntry->LastAccessTime;
1130 pObjectInfoCB->LastWriteTime = DirEnumEntry->LastWriteTime;
1132 pObjectInfoCB->ChangeTime = DirEnumEntry->ChangeTime;
1134 pObjectInfoCB->EndOfFile = DirEnumEntry->EndOfFile;
1136 pObjectInfoCB->AllocationSize = DirEnumEntry->AllocationSize;
1138 pObjectInfoCB->FileAttributes = DirEnumEntry->FileAttributes;
1140 if( pObjectInfoCB->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1141 pObjectInfoCB->FileType == AFS_FILE_TYPE_DFSLINK)
1144 pObjectInfoCB->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1147 if (pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK)
1150 if ( pObjectInfoCB->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1153 pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1158 pObjectInfoCB->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1162 pObjectInfoCB->EaSize = DirEnumEntry->EaSize;
1165 // Check for the case where we have a filetype of SymLink but both the TargetFid and the
1166 // TargetName are empty. In this case set the filetype to zero so we evaluate it later in
1170 if( pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK &&
1171 pObjectInfoCB->TargetFileId.Vnode == 0 &&
1172 pObjectInfoCB->TargetFileId.Unique == 0 &&
1173 pDirNode->NameInformation.TargetName.Length == 0)
1177 // This will ensure we perform a validation on the node
1180 pObjectInfoCB->FileType = AFS_FILE_TYPE_UNKNOWN;
1183 if( pObjectInfoCB->FileType == AFS_FILE_TYPE_UNKNOWN)
1186 SetFlag( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
1191 // Object specific information
1194 pObjectInfoCB->Links = DirEnumEntry->Links;
1196 pObjectInfoCB->Expiration = DirEnumEntry->Expiration;
1198 pObjectInfoCB->DataVersion = DirEnumEntry->DataVersion;
1202 if( !NT_SUCCESS( ntStatus))
1205 if( pNonPagedDirEntry != NULL)
1208 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
1210 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
1213 if( pDirNode != NULL)
1216 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1217 AFS_TRACE_LEVEL_VERBOSE,
1218 "AFSInitDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
1221 AFSExFreePoolWithTag( pDirNode, AFS_DIR_ENTRY_TAG);
1227 // Dereference our object info block if we have one
1230 if( pObjectInfoCB != NULL)
1233 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
1234 AFS_OBJECT_REFERENCE_DIRENTRY);
1236 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1237 AFS_TRACE_LEVEL_VERBOSE,
1238 "AFSInitDirEntry Decrement count on object %p Cnt %d\n",
1242 if( bAllocatedObjectCB)
1245 ASSERT( pObjectInfoCB->ObjectReferenceCount == 0);
1247 AFSDeleteObjectInfo( &pObjectInfoCB);
1257 AFSCheckForReadOnlyAccess( IN ACCESS_MASK DesiredAccess,
1258 IN BOOLEAN DirectoryEntry)
1261 BOOLEAN bReturn = TRUE;
1262 ACCESS_MASK stAccessMask = 0;
1265 // Get rid of anything we don't know about
1268 DesiredAccess = (DesiredAccess &
1274 ACCESS_SYSTEM_SECURITY |
1278 FILE_READ_ATTRIBUTES |
1279 FILE_WRITE_ATTRIBUTES |
1280 FILE_LIST_DIRECTORY |
1286 // Our 'read only' access mask. These are the accesses we will
1287 // allow for a read only file
1290 stAccessMask = DELETE |
1295 ACCESS_SYSTEM_SECURITY |
1299 FILE_READ_ATTRIBUTES |
1300 FILE_WRITE_ATTRIBUTES |
1302 FILE_LIST_DIRECTORY |
1306 // For a directory, add in the directory specific accesses
1312 stAccessMask |= FILE_ADD_SUBDIRECTORY |
1317 if( FlagOn( DesiredAccess, ~stAccessMask))
1321 // A write access is set ...
1331 AFSEvaluateNode( IN GUID *AuthGroup,
1332 IN AFSDirectoryCB *DirEntry)
1335 NTSTATUS ntStatus = STATUS_SUCCESS;
1336 AFSDirEnumEntry *pDirEntry = NULL;
1337 UNICODE_STRING uniTargetName;
1342 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1347 if( !NT_SUCCESS( ntStatus))
1350 try_return( ntStatus);
1353 DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1355 DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1357 DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1359 DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1361 DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1363 DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1365 DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1367 DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1369 DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1371 DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1373 DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1375 if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1376 pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1379 DirEntry->ObjectInformation->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1382 if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK)
1385 if ( DirEntry->ObjectInformation->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1388 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1393 DirEntry->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1397 DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1399 DirEntry->ObjectInformation->Links = pDirEntry->Links;
1402 // If we have a target name then see if it needs updating ...
1405 if( pDirEntry->TargetNameLength > 0)
1409 // Update the target name information if needed
1412 uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1414 uniTargetName.MaximumLength = uniTargetName.Length;
1416 uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1418 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1421 if( DirEntry->NameInformation.TargetName.Length == 0 ||
1422 RtlCompareUnicodeString( &uniTargetName,
1423 &DirEntry->NameInformation.TargetName,
1428 // Update the target name
1431 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1433 uniTargetName.Buffer,
1434 uniTargetName.Length);
1436 if( !NT_SUCCESS( ntStatus))
1439 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1441 try_return( ntStatus);
1445 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1450 if( pDirEntry != NULL)
1453 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
1461 AFSValidateSymLink( IN GUID *AuthGroup,
1462 IN AFSDirectoryCB *DirEntry)
1465 NTSTATUS ntStatus = STATUS_SUCCESS;
1466 AFSDirEnumEntry *pDirEntry = NULL;
1467 UNICODE_STRING uniTargetName;
1472 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1477 if( !NT_SUCCESS( ntStatus))
1480 try_return( ntStatus);
1483 if( pDirEntry->FileType == AFS_FILE_TYPE_UNKNOWN ||
1484 pDirEntry->FileType == AFS_FILE_TYPE_INVALID)
1487 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1488 AFS_TRACE_LEVEL_VERBOSE_2,
1489 "AFSValidateSymLink Invalid type Status %08lX\n",
1490 STATUS_OBJECT_NAME_NOT_FOUND));
1492 try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
1495 DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1497 DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1499 DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1502 // Update the target name information if needed
1505 uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1507 uniTargetName.MaximumLength = uniTargetName.Length;
1509 uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1511 if( uniTargetName.Length > 0)
1514 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1517 if( DirEntry->NameInformation.TargetName.Length == 0 ||
1518 RtlCompareUnicodeString( &uniTargetName,
1519 &DirEntry->NameInformation.TargetName,
1524 // Update the target name
1527 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1529 uniTargetName.Buffer,
1530 uniTargetName.Length);
1532 if( !NT_SUCCESS( ntStatus))
1535 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1537 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1541 AFSReleaseResource( &DirEntry->NonPaged->Lock);
1545 // If the FileType is the same then nothing to do since it IS
1549 if( pDirEntry->FileType == DirEntry->ObjectInformation->FileType)
1552 ASSERT( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK);
1554 try_return( ntStatus = STATUS_SUCCESS);
1557 DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1559 DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1561 DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1563 DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1565 DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1567 DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1569 DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1571 DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1573 if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1574 pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1577 DirEntry->ObjectInformation->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1580 if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK)
1583 if ( DirEntry->ObjectInformation->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1586 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1591 DirEntry->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1595 DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1597 DirEntry->ObjectInformation->Links = pDirEntry->Links;
1601 if( pDirEntry != NULL)
1604 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
1612 AFSInvalidateObject( IN OUT AFSObjectInfoCB **ppObjectInfo,
1616 NTSTATUS ntStatus = STATUS_SUCCESS;
1617 IO_STATUS_BLOCK stIoStatus;
1619 AFSObjectInfoCB * pParentObjectInfo = NULL;
1621 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1622 AFS_TRACE_LEVEL_VERBOSE,
1623 "AFSInvalidateObject Invalidation on node type %d for fid %08lX-%08lX-%08lX-%08lX Reason %d\n",
1624 (*ppObjectInfo)->FileType,
1625 (*ppObjectInfo)->FileId.Cell,
1626 (*ppObjectInfo)->FileId.Volume,
1627 (*ppObjectInfo)->FileId.Vnode,
1628 (*ppObjectInfo)->FileId.Unique,
1631 if ( BooleanFlagOn( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1634 pParentObjectInfo = AFSFindObjectInfo( (*ppObjectInfo)->VolumeCB,
1635 &(*ppObjectInfo)->ParentFileId);
1638 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_SYMLINK ||
1639 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DFSLINK ||
1640 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1643 // We only act on the mount point itself, not the target. If the
1644 // node has been deleted then mark it as such otherwise indicate
1645 // it requires verification
1648 if( Reason == AFS_INVALIDATE_DELETED)
1650 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
1655 if( Reason == AFS_INVALIDATE_FLUSHED)
1658 (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1660 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1663 (*ppObjectInfo)->Expiration.QuadPart = 0;
1665 (*ppObjectInfo)->TargetFileId.Vnode = 0;
1667 (*ppObjectInfo)->TargetFileId.Unique = 0;
1669 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1670 AFS_TRACE_LEVEL_VERBOSE,
1671 "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1672 (*ppObjectInfo)->FileId.Cell,
1673 (*ppObjectInfo)->FileId.Volume,
1674 (*ppObjectInfo)->FileId.Vnode,
1675 (*ppObjectInfo)->FileId.Unique));
1677 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1680 if ( pParentObjectInfo != NULL)
1683 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1685 if( Reason == AFS_INVALIDATE_CREDS)
1687 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1690 if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1691 Reason == AFS_INVALIDATE_FLUSHED)
1693 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1697 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1700 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1703 FILE_ACTION_MODIFIED);
1706 try_return( ntStatus);
1710 // Depending on the reason for invalidation then perform work on the node
1716 case AFS_INVALIDATE_DELETED:
1720 // Mark this node as invalid
1723 (*ppObjectInfo)->Links = 0;
1725 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_DELETED);
1727 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1728 AFS_TRACE_LEVEL_VERBOSE,
1729 "AFSInvalidateObject Set DELETE flag on fid %08lX-%08lX-%08lX-%08lX\n",
1730 (*ppObjectInfo)->FileId.Cell,
1731 (*ppObjectInfo)->FileId.Volume,
1732 (*ppObjectInfo)->FileId.Vnode,
1733 (*ppObjectInfo)->FileId.Unique));
1735 if( pParentObjectInfo != NULL)
1738 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1739 AFS_TRACE_LEVEL_VERBOSE,
1740 "AFSInvalidateObject Set VERIFY flag on parent fid %08lX-%08lX-%08lX-%08lX\n",
1741 pParentObjectInfo->FileId.Cell,
1742 pParentObjectInfo->FileId.Volume,
1743 pParentObjectInfo->FileId.Vnode,
1744 pParentObjectInfo->FileId.Unique));
1746 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1748 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1750 pParentObjectInfo->Expiration.QuadPart = 0;
1752 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1754 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1758 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1761 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1764 FILE_ACTION_REMOVED);
1767 if( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1770 (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1776 case AFS_INVALIDATE_FLUSHED:
1779 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1780 (*ppObjectInfo)->Fcb != NULL)
1783 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1784 AFS_TRACE_LEVEL_VERBOSE,
1785 "AFSInvalidateObject Flush/purge file fid %08lX-%08lX-%08lX-%08lX\n",
1786 (*ppObjectInfo)->FileId.Cell,
1787 (*ppObjectInfo)->FileId.Volume,
1788 (*ppObjectInfo)->FileId.Vnode,
1789 (*ppObjectInfo)->FileId.Unique));
1791 AFSAcquireExcl( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectResource,
1797 CcFlushCache( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1802 if( !NT_SUCCESS( stIoStatus.Status))
1805 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1806 AFS_TRACE_LEVEL_ERROR,
1807 "AFSInvalidateObject CcFlushCache failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1808 (*ppObjectInfo)->FileId.Cell,
1809 (*ppObjectInfo)->FileId.Volume,
1810 (*ppObjectInfo)->FileId.Vnode,
1811 (*ppObjectInfo)->FileId.Unique,
1813 stIoStatus.Information));
1815 ntStatus = stIoStatus.Status;
1819 if ( (*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
1822 if ( !CcPurgeCacheSection( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1828 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1829 AFS_TRACE_LEVEL_WARNING,
1830 "AFSInvalidateObject CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
1831 (*ppObjectInfo)->FileId.Cell,
1832 (*ppObjectInfo)->FileId.Volume,
1833 (*ppObjectInfo)->FileId.Vnode,
1834 (*ppObjectInfo)->FileId.Unique));
1836 SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1840 __except( EXCEPTION_EXECUTE_HANDLER)
1843 ntStatus = GetExceptionCode();
1847 "EXCEPTION - AFSInvalidateObject Cc FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
1848 (*ppObjectInfo)->FileId.Cell,
1849 (*ppObjectInfo)->FileId.Volume,
1850 (*ppObjectInfo)->FileId.Vnode,
1851 (*ppObjectInfo)->FileId.Unique,
1854 SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1857 AFSReleaseResource( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectResource);
1860 // Clear out the extents
1861 // Get rid of them (note this involves waiting
1862 // for any writes or reads to the cache to complete)
1865 AFSTearDownFcbExtents( (*ppObjectInfo)->Fcb,
1869 (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1872 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE)
1875 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1876 AFS_TRACE_LEVEL_VERBOSE,
1877 "AFSInvalidateObject Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
1878 (*ppObjectInfo)->FileId.Cell,
1879 (*ppObjectInfo)->FileId.Volume,
1880 (*ppObjectInfo)->FileId.Vnode,
1881 (*ppObjectInfo)->FileId.Unique));
1883 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1886 // Fall through to the default processing
1892 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1894 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1898 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1901 if( Reason == AFS_INVALIDATE_CREDS)
1903 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1906 if( Reason == AFS_INVALIDATE_DATA_VERSION)
1908 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1912 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1915 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1918 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo),
1921 FILE_ACTION_MODIFIED);
1923 else if ( pParentObjectInfo != NULL)
1926 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1929 FILE_ACTION_MODIFIED);
1933 // Indicate this node requires re-evaluation for the remaining reasons
1936 (*ppObjectInfo)->Expiration.QuadPart = 0;
1938 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1939 AFS_TRACE_LEVEL_VERBOSE,
1940 "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1941 (*ppObjectInfo)->FileId.Cell,
1942 (*ppObjectInfo)->FileId.Volume,
1943 (*ppObjectInfo)->FileId.Vnode,
1944 (*ppObjectInfo)->FileId.Unique));
1946 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1948 if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1949 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1950 ( Reason == AFS_INVALIDATE_CALLBACK ||
1951 Reason == AFS_INVALIDATE_EXPIRED))
1953 if ( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1954 AFS_INVALIDATE_DATA_VERSION)))
1957 (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1967 if ( pParentObjectInfo != NULL)
1970 AFSReleaseObjectInfo( &pParentObjectInfo);
1977 AFSInvalidateCache( IN AFSInvalidateCacheCB *InvalidateCB)
1980 NTSTATUS ntStatus = STATUS_SUCCESS;
1981 AFSVolumeCB *pVolumeCB = NULL;
1982 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1983 ULONGLONG ullIndex = 0;
1984 AFSObjectInfoCB *pObjectInfo = NULL;
1990 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1991 AFS_TRACE_LEVEL_VERBOSE,
1992 "AFSInvalidateCache Invalidation FID %08lX-%08lX-%08lX-%08lX Type %d WholeVolume %d Reason %d\n",
1993 InvalidateCB->FileID.Cell,
1994 InvalidateCB->FileID.Volume,
1995 InvalidateCB->FileID.Vnode,
1996 InvalidateCB->FileID.Unique,
1997 InvalidateCB->FileType,
1998 InvalidateCB->WholeVolume,
1999 InvalidateCB->Reason));
2002 // Need to locate the Fcb for the directory to purge
2005 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2006 AFS_TRACE_LEVEL_VERBOSE,
2007 "AFSInvalidateCache Acquiring RDR VolumeTreeLock lock %p SHARED %08lX\n",
2008 &pDevExt->Specific.RDR.VolumeTreeLock,
2009 PsGetCurrentThread()));
2012 // Starve any exclusive waiters on this paticular call
2015 AFSAcquireSharedStarveExclusive( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2018 // Locate the volume node
2021 ullIndex = AFSCreateHighIndex( &InvalidateCB->FileID);
2023 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2025 (AFSBTreeEntry **)&pVolumeCB);
2027 if( pVolumeCB != NULL)
2030 lCount = AFSVolumeIncrement( pVolumeCB,
2031 AFS_VOLUME_REFERENCE_INVALIDATE);
2033 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2034 AFS_TRACE_LEVEL_VERBOSE,
2035 "AFSInvalidateCache Increment count on volume %p Cnt %d\n",
2040 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2042 if( !NT_SUCCESS( ntStatus) ||
2046 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2047 AFS_TRACE_LEVEL_WARNING,
2048 "AFSInvalidateCache Invalidation FAILURE Unable to locate volume node FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2049 InvalidateCB->FileID.Cell,
2050 InvalidateCB->FileID.Volume,
2051 InvalidateCB->FileID.Vnode,
2052 InvalidateCB->FileID.Unique,
2055 try_return( ntStatus = STATUS_SUCCESS);
2059 // If this is a whole volume invalidation then go do it now
2062 if( InvalidateCB->WholeVolume)
2065 ntStatus = AFSInvalidateVolume( pVolumeCB,
2066 InvalidateCB->Reason);
2068 try_return( ntStatus);
2071 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2074 if ( AFSIsVolumeFID( &InvalidateCB->FileID))
2077 pObjectInfo = &pVolumeCB->ObjectInformation;
2082 ullIndex = AFSCreateLowIndex( &InvalidateCB->FileID);
2084 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2086 (AFSBTreeEntry **)&pObjectInfo);
2089 if( pObjectInfo != NULL)
2093 // Reference the node so it won't be torn down
2096 lCount = AFSObjectInfoIncrement( pObjectInfo,
2097 AFS_OBJECT_REFERENCE_INVALIDATION);
2099 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2100 AFS_TRACE_LEVEL_VERBOSE,
2101 "AFSInvalidateCache Increment count on object %p Cnt %d\n",
2106 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2108 if( !NT_SUCCESS( ntStatus) ||
2109 pObjectInfo == NULL)
2112 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2113 AFS_TRACE_LEVEL_VERBOSE,
2114 "AFSInvalidateCache Invalidation FAILURE Unable to locate object FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2115 InvalidateCB->FileID.Cell,
2116 InvalidateCB->FileID.Volume,
2117 InvalidateCB->FileID.Vnode,
2118 InvalidateCB->FileID.Unique,
2121 try_return( ntStatus = STATUS_SUCCESS);
2124 AFSInvalidateObject( &pObjectInfo,
2125 InvalidateCB->Reason);
2129 if( pObjectInfo != NULL)
2132 lCount = AFSObjectInfoDecrement( pObjectInfo,
2133 AFS_OBJECT_REFERENCE_INVALIDATION);
2135 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2136 AFS_TRACE_LEVEL_VERBOSE,
2137 "AFSInvalidateCache Decrement count on object %p Cnt %d\n",
2142 if ( pVolumeCB != NULL)
2145 lCount = AFSVolumeDecrement( pVolumeCB,
2146 AFS_VOLUME_REFERENCE_INVALIDATE);
2148 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2149 AFS_TRACE_LEVEL_VERBOSE,
2150 "AFSInvalidateCache Decrement count on volume %p Cnt %d\n",
2160 AFSIsChildOfParent( IN AFSFcb *Dcb,
2164 BOOLEAN bIsChild = FALSE;
2165 AFSFcb *pCurrentFcb = Fcb;
2166 AFSObjectInfoCB * pParentObjectInfo = NULL;
2168 while( pCurrentFcb != NULL)
2171 if( BooleanFlagOn( pCurrentFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
2172 AFSIsEqualFID( &pCurrentFcb->ObjectInformation->ParentFileId, &Dcb->ObjectInformation->FileId))
2180 pParentObjectInfo = AFSFindObjectInfo( pCurrentFcb->ObjectInformation->VolumeCB,
2181 &pCurrentFcb->ObjectInformation->ParentFileId);
2183 if ( pParentObjectInfo != NULL)
2186 pCurrentFcb = pParentObjectInfo->Fcb;
2188 AFSReleaseObjectInfo( &pParentObjectInfo);
2202 AFSCreateHighIndex( IN AFSFileID *FileID)
2205 ULONGLONG ullIndex = 0;
2207 ullIndex = (((ULONGLONG)FileID->Cell << 32) | FileID->Volume);
2214 AFSCreateLowIndex( IN AFSFileID *FileID)
2217 ULONGLONG ullIndex = 0;
2219 ullIndex = (((ULONGLONG)FileID->Vnode << 32) | FileID->Unique);
2225 AFSCheckAccess( IN ACCESS_MASK DesiredAccess,
2226 IN ACCESS_MASK GrantedAccess,
2227 IN BOOLEAN DirectoryEntry)
2230 BOOLEAN bAccessGranted = TRUE;
2233 // Check if we are asking for read/write and granted only read only
2234 // NOTE: There will be more checks here
2237 if( !AFSCheckForReadOnlyAccess( DesiredAccess,
2239 AFSCheckForReadOnlyAccess( GrantedAccess,
2243 bAccessGranted = FALSE;
2246 return bAccessGranted;
2250 AFSGetDriverStatus( IN AFSDriverStatusRespCB *DriverStatus)
2253 NTSTATUS ntStatus = STATUS_SUCCESS;
2254 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2260 DriverStatus->Status = AFS_DRIVER_STATUS_READY;
2262 if( AFSGlobalRoot == NULL)
2269 DriverStatus->Status = AFS_DRIVER_STATUS_NOT_READY;
2272 if( pControlDevExt->Specific.Control.CommServiceCB.IrpPoolControlFlag != POOL_ACTIVE)
2279 DriverStatus->Status = AFS_DRIVER_STATUS_NO_SERVICE;
2286 AFSSubstituteSysName( IN UNICODE_STRING *ComponentName,
2287 IN UNICODE_STRING *SubstituteName,
2288 IN ULONG StringIndex)
2291 NTSTATUS ntStatus = STATUS_SUCCESS;
2292 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2293 AFSSysNameCB *pSysName = NULL;
2294 ERESOURCE *pSysNameLock = NULL;
2297 UNICODE_STRING uniSysName;
2304 if( IoIs32bitProcess( NULL))
2307 pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2309 pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2314 pSysNameLock = &pControlDevExt->Specific.Control.SysName64ListLock;
2316 pSysName = pControlDevExt->Specific.Control.SysName64ListHead;
2320 pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2322 pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2326 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2327 AFS_TRACE_LEVEL_VERBOSE,
2328 "AFSSubstituteSysName Acquiring SysName lock %p SHARED %08lX\n",
2330 PsGetCurrentThread()));
2332 AFSAcquireShared( pSysNameLock,
2336 // Find where we are in the list
2339 while( pSysName != NULL &&
2340 ulIndex < StringIndex)
2343 pSysName = pSysName->fLink;
2348 if( pSysName == NULL)
2351 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2352 AFS_TRACE_LEVEL_VERBOSE_2,
2353 "AFSSubstituteSysName No sysname %wZ Status %08lX\n",
2355 STATUS_OBJECT_NAME_NOT_FOUND));
2357 try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
2360 RtlInitUnicodeString( &uniSysName,
2363 // If it is a full component of @SYS then just substitue the
2367 if( RtlCompareUnicodeString( &uniSysName,
2372 SubstituteName->Length = pSysName->SysName.Length;
2373 SubstituteName->MaximumLength = SubstituteName->Length;
2375 SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2376 SubstituteName->Length,
2377 AFS_SUBST_BUFFER_TAG);
2379 if( SubstituteName->Buffer == NULL)
2382 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2385 RtlCopyMemory( SubstituteName->Buffer,
2386 pSysName->SysName.Buffer,
2387 pSysName->SysName.Length);
2394 while( ComponentName->Buffer[ usIndex] != L'@')
2400 SubstituteName->Length = (usIndex * sizeof( WCHAR)) + pSysName->SysName.Length;
2401 SubstituteName->MaximumLength = SubstituteName->Length;
2403 SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2404 SubstituteName->Length,
2405 AFS_SUBST_BUFFER_TAG);
2407 if( SubstituteName->Buffer == NULL)
2410 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2413 RtlCopyMemory( SubstituteName->Buffer,
2414 ComponentName->Buffer,
2415 usIndex * sizeof( WCHAR));
2417 RtlCopyMemory( &SubstituteName->Buffer[ usIndex],
2418 pSysName->SysName.Buffer,
2419 pSysName->SysName.Length);
2424 AFSReleaseResource( pSysNameLock);
2431 AFSSubstituteNameInPath( IN OUT UNICODE_STRING *FullPathName,
2432 IN OUT UNICODE_STRING *ComponentName,
2433 IN UNICODE_STRING *SubstituteName,
2434 IN OUT UNICODE_STRING *RemainingPath,
2435 IN BOOLEAN FreePathName)
2438 NTSTATUS ntStatus = STATUS_SUCCESS;
2439 UNICODE_STRING uniPathName;
2440 USHORT usPrefixNameLen = 0;
2441 SHORT sNameLenDelta = 0;
2447 // If the passed in name can handle the additional length
2448 // then just moves things around
2451 sNameLenDelta = SubstituteName->Length - ComponentName->Length;
2453 usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2455 if( FullPathName->MaximumLength > FullPathName->Length + sNameLenDelta)
2458 if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2461 RtlMoveMemory( &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + SubstituteName->Length)/sizeof( WCHAR))],
2462 &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + ComponentName->Length)/sizeof( WCHAR))],
2463 FullPathName->Length - usPrefixNameLen*sizeof( WCHAR) - ComponentName->Length);
2466 RtlCopyMemory( &FullPathName->Buffer[ usPrefixNameLen],
2467 SubstituteName->Buffer,
2468 SubstituteName->Length);
2470 FullPathName->Length += sNameLenDelta;
2472 ComponentName->Length += sNameLenDelta;
2474 ComponentName->MaximumLength = ComponentName->Length;
2476 if ( RemainingPath->Buffer)
2479 RemainingPath->Buffer += sNameLenDelta/sizeof( WCHAR);
2482 try_return( ntStatus);
2486 // Need to re-allocate the buffer
2489 uniPathName.Length = FullPathName->Length -
2490 ComponentName->Length +
2491 SubstituteName->Length;
2493 uniPathName.MaximumLength = FullPathName->MaximumLength + PAGE_SIZE;
2495 uniPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2496 uniPathName.MaximumLength,
2497 AFS_NAME_BUFFER_FOUR_TAG);
2499 if( uniPathName.Buffer == NULL)
2502 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2505 usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2507 usPrefixNameLen *= sizeof( WCHAR);
2509 RtlZeroMemory( uniPathName.Buffer,
2510 uniPathName.MaximumLength);
2512 RtlCopyMemory( uniPathName.Buffer,
2513 FullPathName->Buffer,
2516 RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen/sizeof( WCHAR))],
2517 SubstituteName->Buffer,
2518 SubstituteName->Length);
2520 if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2523 RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen + SubstituteName->Length)/sizeof( WCHAR)],
2524 &FullPathName->Buffer[ (usPrefixNameLen + ComponentName->Length)/sizeof( WCHAR)],
2525 FullPathName->Length - usPrefixNameLen - ComponentName->Length);
2528 ComponentName->Buffer = uniPathName.Buffer + (ComponentName->Buffer - FullPathName->Buffer);
2530 ComponentName->Length += sNameLenDelta;
2532 ComponentName->MaximumLength = ComponentName->Length;
2534 if ( RemainingPath->Buffer)
2537 RemainingPath->Buffer = uniPathName.Buffer
2538 + (RemainingPath->Buffer - FullPathName->Buffer)
2539 + sNameLenDelta/sizeof( WCHAR);
2544 AFSExFreePoolWithTag( FullPathName->Buffer, 0);
2547 *FullPathName = uniPathName;
2558 AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
2562 NTSTATUS ntStatus = STATUS_SUCCESS;
2563 AFSObjectInfoCB *pCurrentObject = NULL;
2564 AFSObjectInfoCB *pNextObject = NULL;
2570 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2571 AFS_TRACE_LEVEL_VERBOSE,
2572 "AFSInvalidateVolume Invalidate volume fid %08lX-%08lX-%08lX-%08lX Reason %08lX\n",
2573 VolumeCB->ObjectInformation.FileId.Cell,
2574 VolumeCB->ObjectInformation.FileId.Volume,
2575 VolumeCB->ObjectInformation.FileId.Vnode,
2576 VolumeCB->ObjectInformation.FileId.Unique,
2580 // Depending on the reason for invalidation then perform work on the node
2586 case AFS_INVALIDATE_DELETED:
2590 // Mark this volume as invalid
2593 SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
2595 SetFlag( VolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE);
2602 // Invalidate the volume root directory
2605 pCurrentObject = &VolumeCB->ObjectInformation;
2607 if ( pCurrentObject )
2610 lCount = AFSObjectInfoIncrement( pCurrentObject,
2611 AFS_OBJECT_REFERENCE_INVALIDATION);
2613 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2614 AFS_TRACE_LEVEL_VERBOSE,
2615 "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2619 AFSInvalidateObject( &pCurrentObject,
2622 if ( pCurrentObject)
2625 lCount = AFSObjectInfoDecrement( pCurrentObject,
2626 AFS_OBJECT_REFERENCE_INVALIDATION);
2628 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2629 AFS_TRACE_LEVEL_VERBOSE,
2630 "AFSInvalidateVolumeObjects Decrement count on object %p Cnt %d\n",
2637 // Apply invalidation to all other volume objects
2640 AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2643 pCurrentObject = VolumeCB->ObjectInfoListHead;
2645 if ( pCurrentObject)
2649 // Reference the node so it won't be torn down
2652 lCount = AFSObjectInfoIncrement( pCurrentObject,
2653 AFS_OBJECT_REFERENCE_INVALIDATION);
2655 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2656 AFS_TRACE_LEVEL_VERBOSE,
2657 "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2662 while( pCurrentObject != NULL)
2665 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2671 // Reference the node so it won't be torn down
2674 lCount = AFSObjectInfoIncrement( pNextObject,
2675 AFS_OBJECT_REFERENCE_INVALIDATION);
2677 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2678 AFS_TRACE_LEVEL_VERBOSE,
2679 "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2684 AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2686 AFSInvalidateObject( &pCurrentObject,
2689 if ( pCurrentObject )
2692 lCount = AFSObjectInfoDecrement( pCurrentObject,
2693 AFS_OBJECT_REFERENCE_INVALIDATION);
2695 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2696 AFS_TRACE_LEVEL_VERBOSE,
2697 "AFSInvalidateVolumeObjects Decrement count on object %p Cnt %d\n",
2702 AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2705 pCurrentObject = pNextObject;
2708 AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2715 AFSInvalidateAllVolumes( VOID)
2717 AFSVolumeCB *pVolumeCB = NULL;
2718 AFSVolumeCB *pNextVolumeCB = NULL;
2719 AFSDeviceExt *pRDRDeviceExt = NULL;
2722 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2724 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2725 AFS_TRACE_LEVEL_VERBOSE,
2726 "AFSInvalidateAllVolumes Acquiring RDR VolumeListLock lock %p SHARED %08lX\n",
2727 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2728 PsGetCurrentThread()));
2730 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2733 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
2738 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2739 AFS_TRACE_LEVEL_VERBOSE,
2740 "AFSInvalidateAllVolumes Acquiring VolumeRoot ObjectInfoTree lock %p SHARED %08lX\n",
2741 pVolumeCB->ObjectInfoTree.TreeLock,
2742 PsGetCurrentThread()));
2744 lCount = AFSVolumeIncrement( pVolumeCB,
2745 AFS_VOLUME_REFERENCE_INVALIDATE);
2747 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2748 AFS_TRACE_LEVEL_VERBOSE,
2749 "AFSInvalidateAllVolumes Increment count on volume %p Cnt %d\n",
2754 while( pVolumeCB != NULL)
2757 pNextVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2762 lCount = AFSVolumeIncrement( pNextVolumeCB,
2763 AFS_VOLUME_REFERENCE_INVALIDATE);
2765 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2766 AFS_TRACE_LEVEL_VERBOSE,
2767 "AFSInvalidateAllVolumes Increment count on volume %p Cnt %d\n",
2772 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2774 // do I need to hold the volume lock here?
2776 AFSInvalidateVolume( pVolumeCB, AFS_INVALIDATE_EXPIRED);
2778 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2781 lCount = AFSVolumeDecrement( pVolumeCB,
2782 AFS_VOLUME_REFERENCE_INVALIDATE);
2784 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2785 AFS_TRACE_LEVEL_VERBOSE,
2786 "AFSInvalidateAllVolumes Decrement count on volume %p Cnt %d\n",
2790 pVolumeCB = pNextVolumeCB;
2793 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2797 AFSVerifyEntry( IN GUID *AuthGroup,
2798 IN AFSDirectoryCB *DirEntry)
2801 NTSTATUS ntStatus = STATUS_SUCCESS;
2802 AFSDirEnumEntry *pDirEnumEntry = NULL;
2803 AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
2804 IO_STATUS_BLOCK stIoStatus;
2809 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2810 AFS_TRACE_LEVEL_VERBOSE_2,
2811 "AFSVerifyEntry Verifying entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2812 &DirEntry->NameInformation.FileName,
2813 pObjectInfo->FileId.Cell,
2814 pObjectInfo->FileId.Volume,
2815 pObjectInfo->FileId.Vnode,
2816 pObjectInfo->FileId.Unique));
2818 ntStatus = AFSEvaluateTargetByID( pObjectInfo,
2823 if( !NT_SUCCESS( ntStatus))
2826 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2827 AFS_TRACE_LEVEL_ERROR,
2828 "AFSVerifyEntry Evaluate Target failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2829 &DirEntry->NameInformation.FileName,
2830 pObjectInfo->FileId.Cell,
2831 pObjectInfo->FileId.Volume,
2832 pObjectInfo->FileId.Vnode,
2833 pObjectInfo->FileId.Unique,
2836 try_return( ntStatus);
2840 // Check the data version of the file
2843 if( pObjectInfo->DataVersion.QuadPart == pDirEnumEntry->DataVersion.QuadPart)
2845 if ( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2848 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2849 AFS_TRACE_LEVEL_VERBOSE,
2850 "AFSVerifyEntry No DV change %I64X for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2851 pObjectInfo->DataVersion.QuadPart,
2852 &DirEntry->NameInformation.FileName,
2853 pObjectInfo->FileId.Cell,
2854 pObjectInfo->FileId.Volume,
2855 pObjectInfo->FileId.Vnode,
2856 pObjectInfo->FileId.Unique));
2859 // We are ok, just get out
2862 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2864 try_return( ntStatus = STATUS_SUCCESS);
2869 // New data version so we will need to process the node based on the type
2872 switch( pDirEnumEntry->FileType)
2875 case AFS_FILE_TYPE_MOUNTPOINT:
2879 // For a mount point we need to ensure the target is the same
2882 if( !AFSIsEqualFID( &pObjectInfo->TargetFileId,
2883 &pDirEnumEntry->TargetFileId))
2889 // Update the metadata for the entry
2892 ntStatus = AFSUpdateMetaData( DirEntry,
2895 if( NT_SUCCESS( ntStatus))
2898 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2904 case AFS_FILE_TYPE_SYMLINK:
2908 // Update the metadata for the entry
2911 ntStatus = AFSUpdateMetaData( DirEntry,
2914 if( NT_SUCCESS( ntStatus))
2917 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2923 case AFS_FILE_TYPE_FILE:
2925 FILE_OBJECT * pCCFileObject = NULL;
2926 BOOLEAN bPurgeExtents = FALSE;
2928 if ( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
2931 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2932 AFS_TRACE_LEVEL_VERBOSE,
2933 "AFSVerifyEntry DV Change %wZ FID %08lX-%08lX-%08lX-%08lX (%08lX != %08lX)\n",
2934 &DirEntry->NameInformation.FileName,
2935 pObjectInfo->FileId.Cell,
2936 pObjectInfo->FileId.Volume,
2937 pObjectInfo->FileId.Vnode,
2938 pObjectInfo->FileId.Unique,
2939 pObjectInfo->DataVersion.LowPart,
2940 pDirEnumEntry->DataVersion.LowPart));
2942 bPurgeExtents = TRUE;
2945 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2948 bPurgeExtents = TRUE;
2950 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2951 AFS_TRACE_LEVEL_VERBOSE,
2952 "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2953 &DirEntry->NameInformation.FileName,
2954 pObjectInfo->FileId.Cell,
2955 pObjectInfo->FileId.Volume,
2956 pObjectInfo->FileId.Vnode,
2957 pObjectInfo->FileId.Unique));
2959 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
2962 if( pObjectInfo->Fcb != NULL)
2965 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2966 AFS_TRACE_LEVEL_VERBOSE,
2967 "AFSVerifyEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2968 &DirEntry->NameInformation.FileName,
2969 pObjectInfo->FileId.Cell,
2970 pObjectInfo->FileId.Volume,
2971 pObjectInfo->FileId.Vnode,
2972 pObjectInfo->FileId.Unique));
2974 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
2980 CcFlushCache( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2985 if( !NT_SUCCESS( stIoStatus.Status))
2988 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2989 AFS_TRACE_LEVEL_ERROR,
2990 "AFSVerifyEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
2991 &DirEntry->NameInformation.FileName,
2992 pObjectInfo->FileId.Cell,
2993 pObjectInfo->FileId.Volume,
2994 pObjectInfo->FileId.Vnode,
2995 pObjectInfo->FileId.Unique,
2997 stIoStatus.Information));
2999 ntStatus = stIoStatus.Status;
3002 if ( bPurgeExtents &&
3003 pObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
3006 if ( !CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
3012 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
3013 AFS_TRACE_LEVEL_WARNING,
3014 "AFSVerifyEntry CcPurgeCacheSection failure %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3015 &DirEntry->NameInformation.FileName,
3016 pObjectInfo->FileId.Cell,
3017 pObjectInfo->FileId.Volume,
3018 pObjectInfo->FileId.Vnode,
3019 pObjectInfo->FileId.Unique));
3021 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
3025 __except( EXCEPTION_EXECUTE_HANDLER)
3027 ntStatus = GetExceptionCode();
3031 "EXCEPTION - AFSVerifyEntry CcFlushCache or CcPurgeCacheSection %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
3032 &DirEntry->NameInformation.FileName,
3033 pObjectInfo->FileId.Cell,
3034 pObjectInfo->FileId.Volume,
3035 pObjectInfo->FileId.Vnode,
3036 pObjectInfo->FileId.Unique,
3039 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
3042 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
3046 AFSFlushExtents( pObjectInfo->Fcb,
3051 // Reacquire the Fcb to purge the cache
3054 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3055 AFS_TRACE_LEVEL_VERBOSE,
3056 "AFSVerifyEntry Acquiring Fcb lock %p EXCL %08lX\n",
3057 &pObjectInfo->Fcb->NPFcb->Resource,
3058 PsGetCurrentThread()));
3060 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
3064 // Update the metadata for the entry
3067 ntStatus = AFSUpdateMetaData( DirEntry,
3070 if( !NT_SUCCESS( ntStatus))
3073 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3074 AFS_TRACE_LEVEL_ERROR,
3075 "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
3076 &DirEntry->NameInformation.FileName,
3077 pObjectInfo->FileId.Cell,
3078 pObjectInfo->FileId.Volume,
3079 pObjectInfo->FileId.Vnode,
3080 pObjectInfo->FileId.Unique,
3087 // Update file sizes
3090 pObjectInfo->Fcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart;
3091 pObjectInfo->Fcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart;
3092 pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
3094 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3095 AFS_TRACE_LEVEL_VERBOSE,
3096 "AFSVerifyEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
3097 &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3098 PsGetCurrentThread()));
3100 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3103 pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
3105 if ( pCCFileObject != NULL)
3107 CcSetFileSizes( pCCFileObject,
3108 (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
3111 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3112 AFS_TRACE_LEVEL_VERBOSE,
3113 "AFSVerifyEntry Releasing Fcb SectionObject lock %p EXCL %08lX\n",
3114 &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3115 PsGetCurrentThread()));
3117 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
3119 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
3125 // Update the metadata for the entry
3128 ntStatus = AFSUpdateMetaData( DirEntry,
3131 if( !NT_SUCCESS( ntStatus))
3134 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3135 AFS_TRACE_LEVEL_ERROR,
3136 "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
3137 &DirEntry->NameInformation.FileName,
3138 pObjectInfo->FileId.Cell,
3139 pObjectInfo->FileId.Volume,
3140 pObjectInfo->FileId.Vnode,
3141 pObjectInfo->FileId.Unique,
3147 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3148 AFS_TRACE_LEVEL_WARNING,
3149 "AFSVerifyEntry Fcb NULL %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3150 &DirEntry->NameInformation.FileName,
3151 pObjectInfo->FileId.Cell,
3152 pObjectInfo->FileId.Volume,
3153 pObjectInfo->FileId.Vnode,
3154 pObjectInfo->FileId.Unique));
3157 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3162 case AFS_FILE_TYPE_DIRECTORY:
3166 // For a directory or root entry flush the content of
3167 // the directory enumeration.
3170 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3173 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3174 AFS_TRACE_LEVEL_VERBOSE_2,
3175 "AFSVerifyEntry Validating directory content for entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3176 &DirEntry->NameInformation.FileName,
3177 pObjectInfo->FileId.Cell,
3178 pObjectInfo->FileId.Volume,
3179 pObjectInfo->FileId.Vnode,
3180 pObjectInfo->FileId.Unique));
3182 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3185 ntStatus = AFSValidateDirectoryCache( pObjectInfo,
3188 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3190 if ( !NT_SUCCESS( ntStatus))
3193 try_return( ntStatus);
3198 // Update the metadata for the entry
3201 ntStatus = AFSUpdateMetaData( DirEntry,
3204 if( NT_SUCCESS( ntStatus))
3207 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3213 case AFS_FILE_TYPE_DFSLINK:
3216 UNICODE_STRING uniTargetName;
3219 // For a DFS link need to check the target name has not changed
3222 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
3224 uniTargetName.MaximumLength = uniTargetName.Length;
3226 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
3228 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3231 if( DirEntry->NameInformation.TargetName.Length == 0 ||
3232 RtlCompareUnicodeString( &uniTargetName,
3233 &DirEntry->NameInformation.TargetName,
3238 // Update the target name