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,
1636 FILE_ACTION_MODIFIED);
1638 try_return( ntStatus);
1642 // Depending on the reason for invalidation then perform work on the node
1648 case AFS_INVALIDATE_DELETED:
1652 // Mark this node as invalid
1655 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_DELETED);
1657 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1658 AFS_TRACE_LEVEL_VERBOSE,
1659 "AFSInvalidateObject Set DELETE flag on fid %08lX-%08lX-%08lX-%08lX\n",
1660 (*ppObjectInfo)->FileId.Cell,
1661 (*ppObjectInfo)->FileId.Volume,
1662 (*ppObjectInfo)->FileId.Vnode,
1663 (*ppObjectInfo)->FileId.Unique);
1665 if( (*ppObjectInfo)->ParentObjectInformation != NULL)
1668 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1669 AFS_TRACE_LEVEL_VERBOSE,
1670 "AFSInvalidateObject Set VERIFY flag on parent fid %08lX-%08lX-%08lX-%08lX\n",
1671 (*ppObjectInfo)->ParentObjectInformation->FileId.Cell,
1672 (*ppObjectInfo)->ParentObjectInformation->FileId.Volume,
1673 (*ppObjectInfo)->ParentObjectInformation->FileId.Vnode,
1674 (*ppObjectInfo)->ParentObjectInformation->FileId.Unique);
1676 SetFlag( (*ppObjectInfo)->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1678 (*ppObjectInfo)->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1680 (*ppObjectInfo)->ParentObjectInformation->Expiration.QuadPart = 0;
1683 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1685 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1689 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1692 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
1695 FILE_ACTION_REMOVED);
1697 if( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1700 (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1706 case AFS_INVALIDATE_FLUSHED:
1709 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1710 (*ppObjectInfo)->Fcb != NULL)
1713 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1714 AFS_TRACE_LEVEL_VERBOSE,
1715 "AFSInvalidateObject Flush/purge file fid %08lX-%08lX-%08lX-%08lX\n",
1716 (*ppObjectInfo)->FileId.Cell,
1717 (*ppObjectInfo)->FileId.Volume,
1718 (*ppObjectInfo)->FileId.Vnode,
1719 (*ppObjectInfo)->FileId.Unique);
1721 AFSAcquireExcl( &(*ppObjectInfo)->Fcb->NPFcb->Resource,
1727 CcFlushCache( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1732 if( !NT_SUCCESS( stIoStatus.Status))
1735 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1736 AFS_TRACE_LEVEL_ERROR,
1737 "AFSInvalidateObject CcFlushCache failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1738 (*ppObjectInfo)->FileId.Cell,
1739 (*ppObjectInfo)->FileId.Volume,
1740 (*ppObjectInfo)->FileId.Vnode,
1741 (*ppObjectInfo)->FileId.Unique,
1743 stIoStatus.Information);
1745 ntStatus = stIoStatus.Status;
1748 if ( !CcPurgeCacheSection( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1754 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1755 AFS_TRACE_LEVEL_WARNING,
1756 "AFSInvalidateObject CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
1757 (*ppObjectInfo)->FileId.Cell,
1758 (*ppObjectInfo)->FileId.Volume,
1759 (*ppObjectInfo)->FileId.Vnode,
1760 (*ppObjectInfo)->FileId.Unique);
1762 SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1765 __except( EXCEPTION_EXECUTE_HANDLER)
1768 ntStatus = GetExceptionCode();
1772 "EXCEPTION - AFSInvalidateObject Cc FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
1773 (*ppObjectInfo)->FileId.Cell,
1774 (*ppObjectInfo)->FileId.Volume,
1775 (*ppObjectInfo)->FileId.Vnode,
1776 (*ppObjectInfo)->FileId.Unique,
1779 SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1782 AFSReleaseResource( &(*ppObjectInfo)->Fcb->NPFcb->Resource);
1785 // Clear out the extents
1786 // Get rid of them (note this involves waiting
1787 // for any writes or reads to the cache to complete)
1790 (VOID) AFSTearDownFcbExtents( (*ppObjectInfo)->Fcb,
1794 (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1797 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE)
1800 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1801 AFS_TRACE_LEVEL_VERBOSE,
1802 "AFSInvalidateObject Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
1803 (*ppObjectInfo)->FileId.Cell,
1804 (*ppObjectInfo)->FileId.Volume,
1805 (*ppObjectInfo)->FileId.Vnode,
1806 (*ppObjectInfo)->FileId.Unique);
1808 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1811 // Fall through to the default processing
1817 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1819 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1823 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1826 if( Reason == AFS_INVALIDATE_CREDS)
1828 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1831 if( Reason == AFS_INVALIDATE_DATA_VERSION)
1833 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1837 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1840 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
1843 FILE_ACTION_MODIFIED);
1846 // Indicate this node requires re-evaluation for the remaining reasons
1849 (*ppObjectInfo)->Expiration.QuadPart = 0;
1851 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1852 AFS_TRACE_LEVEL_VERBOSE,
1853 "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1854 (*ppObjectInfo)->FileId.Cell,
1855 (*ppObjectInfo)->FileId.Volume,
1856 (*ppObjectInfo)->FileId.Vnode,
1857 (*ppObjectInfo)->FileId.Unique);
1859 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1861 if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1862 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1863 ( Reason == AFS_INVALIDATE_CALLBACK ||
1864 Reason == AFS_INVALIDATE_EXPIRED))
1866 if ( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1867 AFS_INVALIDATE_DATA_VERSION)))
1870 (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1884 AFSInvalidateCache( IN AFSInvalidateCacheCB *InvalidateCB)
1887 NTSTATUS ntStatus = STATUS_SUCCESS;
1888 AFSFcb *pDcb = NULL, *pFcb = NULL, *pNextFcb = NULL;
1889 AFSVolumeCB *pVolumeCB = NULL;
1890 AFSFcb *pTargetDcb = NULL;
1891 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1892 AFSDirectoryCB *pCurrentDirEntry = NULL;
1893 BOOLEAN bIsChild = FALSE;
1894 ULONGLONG ullIndex = 0;
1895 AFSObjectInfoCB *pObjectInfo = NULL;
1901 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1902 AFS_TRACE_LEVEL_VERBOSE,
1903 "AFSInvalidateCache Invalidation FID %08lX-%08lX-%08lX-%08lX Type %d WholeVolume %d Reason %d\n",
1904 InvalidateCB->FileID.Cell,
1905 InvalidateCB->FileID.Volume,
1906 InvalidateCB->FileID.Vnode,
1907 InvalidateCB->FileID.Unique,
1908 InvalidateCB->FileType,
1909 InvalidateCB->WholeVolume,
1910 InvalidateCB->Reason);
1913 // Need to locate the Fcb for the directory to purge
1916 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1917 AFS_TRACE_LEVEL_VERBOSE,
1918 "AFSInvalidateCache Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1919 &pDevExt->Specific.RDR.VolumeTreeLock,
1920 PsGetCurrentThread());
1923 // Starve any exclusive waiters on this paticular call
1926 AFSAcquireSharedStarveExclusive( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1929 // Locate the volume node
1932 ullIndex = AFSCreateHighIndex( &InvalidateCB->FileID);
1934 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1936 (AFSBTreeEntry **)&pVolumeCB);
1938 if( pVolumeCB != NULL)
1941 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1943 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1944 AFS_TRACE_LEVEL_VERBOSE,
1945 "AFSInvalidateCache Increment count on volume %08lX Cnt %d\n",
1950 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1952 if( !NT_SUCCESS( ntStatus) ||
1956 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1957 AFS_TRACE_LEVEL_WARNING,
1958 "AFSInvalidateCache Invalidation FAILURE Unable to locate volume node FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1959 InvalidateCB->FileID.Cell,
1960 InvalidateCB->FileID.Volume,
1961 InvalidateCB->FileID.Vnode,
1962 InvalidateCB->FileID.Unique,
1965 try_return( ntStatus = STATUS_SUCCESS);
1969 // If this is a whole volume invalidation then go do it now
1972 if( InvalidateCB->WholeVolume)
1975 ntStatus = AFSInvalidateVolume( pVolumeCB,
1976 InvalidateCB->Reason);
1978 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1980 try_return( ntStatus);
1983 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1986 if ( AFSIsVolumeFID( &InvalidateCB->FileID))
1989 pObjectInfo = &pVolumeCB->ObjectInformation;
1994 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1996 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1997 AFS_TRACE_LEVEL_VERBOSE,
1998 "AFSInvalidateCache Decrement count on volume %08lX Cnt %d\n",
2000 pVolumeCB->VolumeReferenceCount);
2002 ullIndex = AFSCreateLowIndex( &InvalidateCB->FileID);
2004 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2006 (AFSBTreeEntry **)&pObjectInfo);
2009 if( pObjectInfo != NULL)
2013 // Reference the node so it won't be torn down
2016 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2018 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2019 AFS_TRACE_LEVEL_VERBOSE,
2020 "AFSInvalidateCache Increment count on object %08lX Cnt %d\n",
2025 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2027 if( !NT_SUCCESS( ntStatus) ||
2028 pObjectInfo == NULL)
2031 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2032 AFS_TRACE_LEVEL_VERBOSE,
2033 "AFSInvalidateCache Invalidation FAILURE Unable to locate object FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2034 InvalidateCB->FileID.Cell,
2035 InvalidateCB->FileID.Volume,
2036 InvalidateCB->FileID.Vnode,
2037 InvalidateCB->FileID.Unique,
2040 try_return( ntStatus = STATUS_SUCCESS);
2043 AFSInvalidateObject( &pObjectInfo,
2044 InvalidateCB->Reason);
2048 if( pObjectInfo != NULL)
2051 lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2053 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2054 AFS_TRACE_LEVEL_VERBOSE,
2055 "AFSInvalidateCache Decrement count on object %08lX Cnt %d\n",
2065 AFSIsChildOfParent( IN AFSFcb *Dcb,
2069 BOOLEAN bIsChild = FALSE;
2070 AFSFcb *pCurrentFcb = Fcb;
2072 while( pCurrentFcb != NULL)
2075 if( pCurrentFcb->ObjectInformation->ParentObjectInformation == Dcb->ObjectInformation)
2083 pCurrentFcb = pCurrentFcb->ObjectInformation->ParentObjectInformation->Fcb;
2091 AFSCreateHighIndex( IN AFSFileID *FileID)
2094 ULONGLONG ullIndex = 0;
2096 ullIndex = (((ULONGLONG)FileID->Cell << 32) | FileID->Volume);
2103 AFSCreateLowIndex( IN AFSFileID *FileID)
2106 ULONGLONG ullIndex = 0;
2108 ullIndex = (((ULONGLONG)FileID->Vnode << 32) | FileID->Unique);
2114 AFSCheckAccess( IN ACCESS_MASK DesiredAccess,
2115 IN ACCESS_MASK GrantedAccess,
2116 IN BOOLEAN DirectoryEntry)
2119 BOOLEAN bAccessGranted = TRUE;
2122 // Check if we are asking for read/write and granted only read only
2123 // NOTE: There will be more checks here
2126 if( !AFSCheckForReadOnlyAccess( DesiredAccess,
2128 AFSCheckForReadOnlyAccess( GrantedAccess,
2132 bAccessGranted = FALSE;
2135 return bAccessGranted;
2139 AFSGetDriverStatus( IN AFSDriverStatusRespCB *DriverStatus)
2142 NTSTATUS ntStatus = STATUS_SUCCESS;
2143 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2149 DriverStatus->Status = AFS_DRIVER_STATUS_READY;
2151 if( AFSGlobalRoot == NULL)
2158 DriverStatus->Status = AFS_DRIVER_STATUS_NOT_READY;
2161 if( pControlDevExt->Specific.Control.CommServiceCB.IrpPoolControlFlag != POOL_ACTIVE)
2168 DriverStatus->Status = AFS_DRIVER_STATUS_NO_SERVICE;
2175 AFSSubstituteSysName( IN UNICODE_STRING *ComponentName,
2176 IN UNICODE_STRING *SubstituteName,
2177 IN ULONG StringIndex)
2180 NTSTATUS ntStatus = STATUS_SUCCESS;
2181 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2182 AFSSysNameCB *pSysName = NULL;
2183 ERESOURCE *pSysNameLock = NULL;
2186 UNICODE_STRING uniSysName;
2193 if( IoIs32bitProcess( NULL))
2196 pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2198 pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2203 pSysNameLock = &pControlDevExt->Specific.Control.SysName64ListLock;
2205 pSysName = pControlDevExt->Specific.Control.SysName64ListHead;
2209 pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2211 pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2215 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2216 AFS_TRACE_LEVEL_VERBOSE,
2217 "AFSSubstituteSysName Acquiring SysName lock %08lX SHARED %08lX\n",
2219 PsGetCurrentThread());
2221 AFSAcquireShared( pSysNameLock,
2225 // Find where we are in the list
2228 while( pSysName != NULL &&
2229 ulIndex < StringIndex)
2232 pSysName = pSysName->fLink;
2237 if( pSysName == NULL)
2240 try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
2243 RtlInitUnicodeString( &uniSysName,
2246 // If it is a full component of @SYS then just substitue the
2250 if( RtlCompareUnicodeString( &uniSysName,
2255 SubstituteName->Length = pSysName->SysName.Length;
2256 SubstituteName->MaximumLength = SubstituteName->Length;
2258 SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2259 SubstituteName->Length,
2260 AFS_SUBST_BUFFER_TAG);
2262 if( SubstituteName->Buffer == NULL)
2265 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2268 RtlCopyMemory( SubstituteName->Buffer,
2269 pSysName->SysName.Buffer,
2270 pSysName->SysName.Length);
2277 while( ComponentName->Buffer[ usIndex] != L'@')
2283 SubstituteName->Length = (usIndex * sizeof( WCHAR)) + pSysName->SysName.Length;
2284 SubstituteName->MaximumLength = SubstituteName->Length;
2286 SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2287 SubstituteName->Length,
2288 AFS_SUBST_BUFFER_TAG);
2290 if( SubstituteName->Buffer == NULL)
2293 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2296 RtlCopyMemory( SubstituteName->Buffer,
2297 ComponentName->Buffer,
2298 usIndex * sizeof( WCHAR));
2300 RtlCopyMemory( &SubstituteName->Buffer[ usIndex],
2301 pSysName->SysName.Buffer,
2302 pSysName->SysName.Length);
2307 AFSReleaseResource( pSysNameLock);
2314 AFSSubstituteNameInPath( IN OUT UNICODE_STRING *FullPathName,
2315 IN OUT UNICODE_STRING *ComponentName,
2316 IN UNICODE_STRING *SubstituteName,
2317 IN OUT UNICODE_STRING *RemainingPath,
2318 IN BOOLEAN FreePathName)
2321 NTSTATUS ntStatus = STATUS_SUCCESS;
2322 UNICODE_STRING uniPathName;
2323 USHORT usPrefixNameLen = 0;
2324 SHORT sNameLenDelta = 0;
2330 // If the passed in name can handle the additional length
2331 // then just moves things around
2334 sNameLenDelta = SubstituteName->Length - ComponentName->Length;
2336 usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2338 if( FullPathName->MaximumLength > FullPathName->Length + sNameLenDelta)
2341 if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2344 RtlMoveMemory( &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + SubstituteName->Length)/sizeof( WCHAR))],
2345 &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + ComponentName->Length)/sizeof( WCHAR))],
2346 FullPathName->Length - usPrefixNameLen*sizeof( WCHAR) - ComponentName->Length);
2349 RtlCopyMemory( &FullPathName->Buffer[ usPrefixNameLen],
2350 SubstituteName->Buffer,
2351 SubstituteName->Length);
2353 FullPathName->Length += sNameLenDelta;
2355 ComponentName->Length += sNameLenDelta;
2357 ComponentName->MaximumLength = ComponentName->Length;
2359 if ( RemainingPath->Buffer)
2362 RemainingPath->Buffer += sNameLenDelta/sizeof( WCHAR);
2365 try_return( ntStatus);
2369 // Need to re-allocate the buffer
2372 uniPathName.Length = FullPathName->Length -
2373 ComponentName->Length +
2374 SubstituteName->Length;
2376 uniPathName.MaximumLength = FullPathName->MaximumLength + PAGE_SIZE;
2378 uniPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2379 uniPathName.MaximumLength,
2380 AFS_NAME_BUFFER_FOUR_TAG);
2382 if( uniPathName.Buffer == NULL)
2385 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2388 usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2390 usPrefixNameLen *= sizeof( WCHAR);
2392 RtlZeroMemory( uniPathName.Buffer,
2393 uniPathName.MaximumLength);
2395 RtlCopyMemory( uniPathName.Buffer,
2396 FullPathName->Buffer,
2399 RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen/sizeof( WCHAR))],
2400 SubstituteName->Buffer,
2401 SubstituteName->Length);
2403 if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2406 RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen + SubstituteName->Length)/sizeof( WCHAR)],
2407 &FullPathName->Buffer[ (usPrefixNameLen + ComponentName->Length)/sizeof( WCHAR)],
2408 FullPathName->Length - usPrefixNameLen - ComponentName->Length);
2411 ComponentName->Buffer = uniPathName.Buffer + (ComponentName->Buffer - FullPathName->Buffer);
2413 ComponentName->Length += sNameLenDelta;
2415 ComponentName->MaximumLength = ComponentName->Length;
2417 if ( RemainingPath->Buffer)
2420 RemainingPath->Buffer = uniPathName.Buffer
2421 + (RemainingPath->Buffer - FullPathName->Buffer)
2422 + sNameLenDelta/sizeof( WCHAR);
2427 AFSExFreePool( FullPathName->Buffer);
2430 *FullPathName = uniPathName;
2441 AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
2445 NTSTATUS ntStatus = STATUS_SUCCESS;
2446 AFSObjectInfoCB *pCurrentObject = NULL;
2447 AFSObjectInfoCB *pNextObject = NULL;
2449 AFSFcb *pFcb = NULL;
2455 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2456 AFS_TRACE_LEVEL_VERBOSE,
2457 "AFSInvalidateVolume Invalidate volume fid %08lX-%08lX-%08lX-%08lX Reason %08lX\n",
2458 VolumeCB->ObjectInformation.FileId.Cell,
2459 VolumeCB->ObjectInformation.FileId.Volume,
2460 VolumeCB->ObjectInformation.FileId.Vnode,
2461 VolumeCB->ObjectInformation.FileId.Unique,
2465 // Depending on the reason for invalidation then perform work on the node
2471 case AFS_INVALIDATE_DELETED:
2475 // Mark this volume as invalid
2478 SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
2480 SetFlag( VolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE);
2487 // Invalidate the volume root directory
2490 pCurrentObject = &VolumeCB->ObjectInformation;
2492 if ( pCurrentObject )
2495 lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
2497 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2498 AFS_TRACE_LEVEL_VERBOSE,
2499 "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2503 AFSInvalidateObject( &pCurrentObject,
2506 if ( pCurrentObject)
2509 lCount = InterlockedDecrement( &pCurrentObject->ObjectReferenceCount);
2511 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2512 AFS_TRACE_LEVEL_VERBOSE,
2513 "AFSInvalidateVolumeObjects Decrement count on object %08lX Cnt %d\n",
2520 // Apply invalidation to all other volume objects
2523 AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2526 pCurrentObject = VolumeCB->ObjectInfoListHead;
2528 if ( pCurrentObject)
2532 // Reference the node so it won't be torn down
2535 lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
2537 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2538 AFS_TRACE_LEVEL_VERBOSE,
2539 "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2544 while( pCurrentObject != NULL)
2547 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2553 // Reference the node so it won't be torn down
2556 lCount = InterlockedIncrement( &pNextObject->ObjectReferenceCount);
2558 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2559 AFS_TRACE_LEVEL_VERBOSE,
2560 "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2565 AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2567 AFSInvalidateObject( &pCurrentObject,
2570 if ( pCurrentObject )
2573 lCount = InterlockedDecrement( &pCurrentObject->ObjectReferenceCount);
2575 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2576 AFS_TRACE_LEVEL_VERBOSE,
2577 "AFSInvalidateVolumeObjects Decrement count on object %08lX Cnt %d\n",
2582 AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2585 pCurrentObject = pNextObject;
2588 AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2595 AFSInvalidateAllVolumes( VOID)
2597 AFSVolumeCB *pVolumeCB = NULL;
2598 AFSVolumeCB *pNextVolumeCB = NULL;
2599 AFSDeviceExt *pRDRDeviceExt = NULL;
2602 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2604 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2605 AFS_TRACE_LEVEL_VERBOSE,
2606 "AFSInvalidateAllVolumes Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
2607 &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2608 PsGetCurrentThread());
2610 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2613 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
2618 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2619 AFS_TRACE_LEVEL_VERBOSE,
2620 "AFSInvalidateAllVolumes Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
2621 pVolumeCB->ObjectInfoTree.TreeLock,
2622 PsGetCurrentThread());
2624 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2627 while( pVolumeCB != NULL)
2630 pNextVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2635 lCount = InterlockedIncrement( &pNextVolumeCB->VolumeReferenceCount);
2638 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2640 // do I need to hold the volume lock here?
2642 AFSInvalidateVolume( pVolumeCB, AFS_INVALIDATE_EXPIRED);
2644 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2647 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2649 pVolumeCB = pNextVolumeCB;
2652 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2656 AFSVerifyEntry( IN GUID *AuthGroup,
2657 IN AFSDirectoryCB *DirEntry)
2660 NTSTATUS ntStatus = STATUS_SUCCESS;
2661 AFSDirEnumEntry *pDirEnumEntry = NULL;
2662 AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
2663 IO_STATUS_BLOCK stIoStatus;
2668 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2669 AFS_TRACE_LEVEL_VERBOSE_2,
2670 "AFSVerifyEntry Verifying entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2671 &DirEntry->NameInformation.FileName,
2672 pObjectInfo->FileId.Cell,
2673 pObjectInfo->FileId.Volume,
2674 pObjectInfo->FileId.Vnode,
2675 pObjectInfo->FileId.Unique);
2677 ntStatus = AFSEvaluateTargetByID( pObjectInfo,
2682 if( !NT_SUCCESS( ntStatus))
2685 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2686 AFS_TRACE_LEVEL_ERROR,
2687 "AFSVerifyEntry Evaluate Target failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2688 &DirEntry->NameInformation.FileName,
2689 pObjectInfo->FileId.Cell,
2690 pObjectInfo->FileId.Volume,
2691 pObjectInfo->FileId.Vnode,
2692 pObjectInfo->FileId.Unique,
2695 try_return( ntStatus);
2699 // Check the data version of the file
2702 if( pObjectInfo->DataVersion.QuadPart == pDirEnumEntry->DataVersion.QuadPart)
2704 if ( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2707 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2708 AFS_TRACE_LEVEL_VERBOSE,
2709 "AFSVerifyEntry No DV change %I64X for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2710 pObjectInfo->DataVersion.QuadPart,
2711 &DirEntry->NameInformation.FileName,
2712 pObjectInfo->FileId.Cell,
2713 pObjectInfo->FileId.Volume,
2714 pObjectInfo->FileId.Vnode,
2715 pObjectInfo->FileId.Unique);
2718 // We are ok, just get out
2721 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2723 try_return( ntStatus = STATUS_SUCCESS);
2728 // New data version so we will need to process the node based on the type
2731 switch( pDirEnumEntry->FileType)
2734 case AFS_FILE_TYPE_MOUNTPOINT:
2738 // For a mount point we need to ensure the target is the same
2741 if( !AFSIsEqualFID( &pObjectInfo->TargetFileId,
2742 &pDirEnumEntry->TargetFileId))
2748 // Update the metadata for the entry
2751 ntStatus = AFSUpdateMetaData( DirEntry,
2754 if( NT_SUCCESS( ntStatus))
2757 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2763 case AFS_FILE_TYPE_SYMLINK:
2766 ASSERT( pDirEnumEntry->TargetNameLength > 0);
2769 // Update the metadata for the entry
2772 ntStatus = AFSUpdateMetaData( DirEntry,
2775 if( NT_SUCCESS( ntStatus))
2778 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2784 case AFS_FILE_TYPE_FILE:
2786 FILE_OBJECT * pCCFileObject = NULL;
2787 BOOLEAN bPurgeExtents = FALSE;
2789 if ( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
2792 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2793 AFS_TRACE_LEVEL_VERBOSE,
2794 "AFSVerifyEntry DV Change %wZ FID %08lX-%08lX-%08lX-%08lX (%08lX != %08lX)\n",
2795 &DirEntry->NameInformation.FileName,
2796 pObjectInfo->FileId.Cell,
2797 pObjectInfo->FileId.Volume,
2798 pObjectInfo->FileId.Vnode,
2799 pObjectInfo->FileId.Unique,
2800 pObjectInfo->DataVersion.LowPart,
2801 pDirEnumEntry->DataVersion.LowPart
2804 bPurgeExtents = TRUE;
2807 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2810 bPurgeExtents = TRUE;
2812 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2813 AFS_TRACE_LEVEL_VERBOSE,
2814 "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2815 &DirEntry->NameInformation.FileName,
2816 pObjectInfo->FileId.Cell,
2817 pObjectInfo->FileId.Volume,
2818 pObjectInfo->FileId.Vnode,
2819 pObjectInfo->FileId.Unique);
2821 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
2824 if( pObjectInfo->Fcb != NULL)
2827 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2828 AFS_TRACE_LEVEL_VERBOSE,
2829 "AFSVerifyEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2830 &DirEntry->NameInformation.FileName,
2831 pObjectInfo->FileId.Cell,
2832 pObjectInfo->FileId.Volume,
2833 pObjectInfo->FileId.Vnode,
2834 pObjectInfo->FileId.Unique);
2836 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
2842 CcFlushCache( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2847 if( !NT_SUCCESS( stIoStatus.Status))
2850 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2851 AFS_TRACE_LEVEL_ERROR,
2852 "AFSVerifyEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
2853 &DirEntry->NameInformation.FileName,
2854 pObjectInfo->FileId.Cell,
2855 pObjectInfo->FileId.Volume,
2856 pObjectInfo->FileId.Vnode,
2857 pObjectInfo->FileId.Unique,
2859 stIoStatus.Information);
2861 ntStatus = stIoStatus.Status;
2867 if ( !CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2873 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2874 AFS_TRACE_LEVEL_WARNING,
2875 "AFSVerifyEntry CcPurgeCacheSection failure %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2876 &DirEntry->NameInformation.FileName,
2877 pObjectInfo->FileId.Cell,
2878 pObjectInfo->FileId.Volume,
2879 pObjectInfo->FileId.Vnode,
2880 pObjectInfo->FileId.Unique);
2882 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
2886 __except( EXCEPTION_EXECUTE_HANDLER)
2888 ntStatus = GetExceptionCode();
2892 "EXCEPTION - AFSVerifyEntry CcFlushCache or CcPurgeCacheSection %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2893 &DirEntry->NameInformation.FileName,
2894 pObjectInfo->FileId.Cell,
2895 pObjectInfo->FileId.Volume,
2896 pObjectInfo->FileId.Vnode,
2897 pObjectInfo->FileId.Unique,
2900 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
2903 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
2907 AFSFlushExtents( pObjectInfo->Fcb,
2912 // Reacquire the Fcb to purge the cache
2915 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2916 AFS_TRACE_LEVEL_VERBOSE,
2917 "AFSVerifyEntry Acquiring Fcb lock %08lX EXCL %08lX\n",
2918 &pObjectInfo->Fcb->NPFcb->Resource,
2919 PsGetCurrentThread());
2921 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
2925 // Update the metadata for the entry
2928 ntStatus = AFSUpdateMetaData( DirEntry,
2931 if( !NT_SUCCESS( ntStatus))
2934 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2935 AFS_TRACE_LEVEL_ERROR,
2936 "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
2937 &DirEntry->NameInformation.FileName,
2938 pObjectInfo->FileId.Cell,
2939 pObjectInfo->FileId.Volume,
2940 pObjectInfo->FileId.Vnode,
2941 pObjectInfo->FileId.Unique,
2948 // Update file sizes
2951 pObjectInfo->Fcb->Header.AllocationSize.QuadPart = pObjectInfo->AllocationSize.QuadPart;
2952 pObjectInfo->Fcb->Header.FileSize.QuadPart = pObjectInfo->EndOfFile.QuadPart;
2953 pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
2955 pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
2957 if ( pCCFileObject != NULL)
2959 CcSetFileSizes( pCCFileObject,
2960 (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
2963 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
2969 // Update the metadata for the entry
2972 ntStatus = AFSUpdateMetaData( DirEntry,
2975 if( !NT_SUCCESS( ntStatus))
2978 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2979 AFS_TRACE_LEVEL_ERROR,
2980 "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
2981 &DirEntry->NameInformation.FileName,
2982 pObjectInfo->FileId.Cell,
2983 pObjectInfo->FileId.Volume,
2984 pObjectInfo->FileId.Vnode,
2985 pObjectInfo->FileId.Unique,
2991 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2992 AFS_TRACE_LEVEL_WARNING,
2993 "AFSVerifyEntry Fcb NULL %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2994 &DirEntry->NameInformation.FileName,
2995 pObjectInfo->FileId.Cell,
2996 pObjectInfo->FileId.Volume,
2997 pObjectInfo->FileId.Vnode,
2998 pObjectInfo->FileId.Unique);
3001 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3006 case AFS_FILE_TYPE_DIRECTORY:
3009 AFSFcb *pCurrentFcb = NULL;
3010 AFSDirectoryCB *pCurrentDirEntry = NULL;
3013 // For a directory or root entry flush the content of
3014 // the directory enumeration.
3017 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3020 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3021 AFS_TRACE_LEVEL_VERBOSE_2,
3022 "AFSVerifyEntry Validating directory content for entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3023 &DirEntry->NameInformation.FileName,
3024 pObjectInfo->FileId.Cell,
3025 pObjectInfo->FileId.Volume,
3026 pObjectInfo->FileId.Vnode,
3027 pObjectInfo->FileId.Unique);
3029 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3032 ntStatus = AFSValidateDirectoryCache( pObjectInfo,
3035 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3037 if ( !NT_SUCCESS( ntStatus))
3040 try_return( ntStatus);
3045 // Update the metadata for the entry
3048 ntStatus = AFSUpdateMetaData( DirEntry,
3051 if( NT_SUCCESS( ntStatus))
3054 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3060 case AFS_FILE_TYPE_DFSLINK:
3063 UNICODE_STRING uniTargetName;
3066 // For a DFS link need to check the target name has not changed
3069 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
3071 uniTargetName.MaximumLength = uniTargetName.Length;
3073 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
3075 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3078 if( DirEntry->NameInformation.TargetName.Length == 0 ||
3079 RtlCompareUnicodeString( &uniTargetName,
3080 &DirEntry->NameInformation.TargetName,
3085 // Update the target name
3088 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3090 uniTargetName.Buffer,
3091 uniTargetName.Length);
3093 if( !NT_SUCCESS( ntStatus))
3096 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3102 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3105 // Update the metadata for the entry
3108 ntStatus = AFSUpdateMetaData( DirEntry,
3111 if( NT_SUCCESS( ntStatus))
3114 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3122 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3123 AFS_TRACE_LEVEL_WARNING,
3124 "AFSVerifyEntry Attempt to verify node of type %d %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3125 pObjectInfo->FileType,
3126 &DirEntry->NameInformation.FileName,
3127 pObjectInfo->FileId.Cell,
3128 pObjectInfo->FileId.Volume,
3129 pObjectInfo->FileId.Vnode,
3130 pObjectInfo->FileId.Unique);
3137 if( pDirEnumEntry != NULL)
3140 AFSExFreePool( pDirEnumEntry);
3148 AFSSetVolumeState( IN AFSVolumeStatusCB *VolumeStatus)
3151 NTSTATUS ntStatus = STATUS_SUCCESS;
3152 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
3153 ULONGLONG ullIndex = 0;
3154 AFSVolumeCB *pVolumeCB = NULL;
3155 AFSFcb *pFcb = NULL;
3156 AFSObjectInfoCB *pCurrentObject = NULL;
3162 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3163 AFS_TRACE_LEVEL_VERBOSE,
3164 "AFSSetVolumeState Marking volume state %d Volume Cell %08lX Volume %08lX\n",
3165 VolumeStatus->Online,
3166 VolumeStatus->FileID.Cell,
3167 VolumeStatus->FileID.Volume);
3170 // Need to locate the Fcb for the directory to purge
3173 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3174 AFS_TRACE_LEVEL_VERBOSE,
3175 "AFSSetVolumeState Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
3176 &pDevExt->Specific.RDR.VolumeTreeLock,
3177 PsGetCurrentThread());
3179 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
3182 // Locate the volume node
3185 ullIndex = AFSCreateHighIndex( &VolumeStatus->FileID);
3187 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
3189 (AFSBTreeEntry **)&pVolumeCB);
3191 if( pVolumeCB != NULL)
3194 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
3196 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3199 // Set the volume state accordingly
3202 if( VolumeStatus->Online)
3205 InterlockedAnd( (LONG *)&(pVolumeCB->Flags), ~AFS_VOLUME_FLAGS_OFFLINE);
3210 InterlockedOr( (LONG *)&(pVolumeCB->Flags), AFS_VOLUME_FLAGS_OFFLINE);
3213 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
3216 pCurrentObject = pVolumeCB->ObjectInfoListHead;;
3218 while( pCurrentObject != NULL)
3221 if( VolumeStatus->Online)
3224 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
3226 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
3228 pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
3233 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
3236 pFcb = pCurrentObject->Fcb;
3239 !(VolumeStatus->Online) &&
3240 pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
3243 AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3244 AFS_TRACE_LEVEL_ERROR,
3245 "AFSSetVolumeState Marking volume offline and canceling extents Volume Cell %08lX Volume %08lX\n",
3246 VolumeStatus->FileID.Cell,
3247 VolumeStatus->FileID.Volume);
3250 // Clear out the extents
3253 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3254 AFS_TRACE_LEVEL_VERBOSE,
3255 "AFSSetVolumeState Acquiring Fcb extents lock %08lX EXCL %08lX\n",
3256 &pFcb->NPFcb->Specific.File.ExtentsResource,
3257 PsGetCurrentThread());