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: AFSCommSupport.cpp
39 #include "AFSCommon.h"
42 AFSEnumerateDirectory( IN GUID *AuthGroup,
43 IN AFSObjectInfoCB *ObjectInfoCB,
47 NTSTATUS ntStatus = STATUS_SUCCESS;
49 ULONG ulResultLen = 0;
50 AFSDirQueryCB *pDirQueryCB;
51 AFSDirEnumEntry *pCurrentDirEntry = NULL;
52 AFSDirectoryCB *pDirNode = NULL;
53 ULONG ulEntryLength = 0;
54 AFSDirEnumResp *pDirEnumResponse = NULL;
55 UNICODE_STRING uniDirName, uniTargetName;
56 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
58 UNICODE_STRING uniGUID;
59 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
64 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
67 uniGUID.MaximumLength = 0;
68 uniGUID.Buffer = NULL;
70 if( AuthGroup != NULL)
72 RtlStringFromGUID( *AuthGroup,
76 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
77 AFS_TRACE_LEVEL_VERBOSE,
78 "AFSEnumerateDirectory Enumerating FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
79 ObjectInfoCB->FileId.Cell,
80 ObjectInfoCB->FileId.Volume,
81 ObjectInfoCB->FileId.Vnode,
82 ObjectInfoCB->FileId.Unique,
85 if( AuthGroup != NULL)
87 RtlFreeUnicodeString( &uniGUID);
91 // Initialize the directory enumeration buffer for the directory
94 pBuffer = AFSExAllocatePoolWithTag( PagedPool,
95 AFS_DIR_ENUM_BUFFER_LEN,
101 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
104 RtlZeroMemory( pBuffer,
105 AFS_DIR_ENUM_BUFFER_LEN);
107 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
110 // Use the payload buffer for information we will pass to the service
113 pDirQueryCB = (AFSDirQueryCB *)pBuffer;
115 pDirQueryCB->EnumHandle = 0;
120 ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
124 // Loop on the information
131 // If the enumeration handle is -1 then we are done
134 if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
137 ntStatus = STATUS_NO_MORE_ENTRIES;
143 // Go and retrieve the directory contents
146 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
150 &ObjectInfoCB->FileId,
152 sizeof( AFSDirQueryCB),
157 if( ntStatus != STATUS_SUCCESS ||
161 if( ntStatus == STATUS_NO_MORE_FILES ||
162 ntStatus == STATUS_NO_MORE_ENTRIES)
165 ntStatus = STATUS_SUCCESS;
167 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
169 AFSAcquireExcl( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock,
172 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
173 AFS_TRACE_LEVEL_VERBOSE,
174 "AFSEnumerateDirectory Directory Complete FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX Status %08lX\n",
175 ObjectInfoCB->FileId.Cell,
176 ObjectInfoCB->FileId.Volume,
177 ObjectInfoCB->FileId.Vnode,
178 ObjectInfoCB->FileId.Unique,
179 pDirEnumResponse->SnapshotDataVersion.HighPart,
180 pDirEnumResponse->SnapshotDataVersion.LowPart,
181 pDirEnumResponse->CurrentDataVersion.HighPart,
182 pDirEnumResponse->CurrentDataVersion.LowPart,
185 ObjectInfoCB->DataVersion = pDirEnumResponse->SnapshotDataVersion;
187 if ( pDirEnumResponse->SnapshotDataVersion.QuadPart != pDirEnumResponse->CurrentDataVersion.QuadPart )
190 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
192 ObjectInfoCB->DataVersion.QuadPart = (ULONGLONG)-1;
194 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
195 AFS_TRACE_LEVEL_VERBOSE,
196 "AFSEnumerateDirectory Force Verify due to DV change during enumeration FID %08lX-%08lX-%08lX-%08lX\n",
197 ObjectInfoCB->FileId.Cell,
198 ObjectInfoCB->FileId.Volume,
199 ObjectInfoCB->FileId.Vnode,
200 ObjectInfoCB->FileId.Unique);
203 AFSReleaseResource( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock);
208 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
209 AFS_TRACE_LEVEL_VERBOSE,
210 "AFSEnumerateDirectory Failed to enumerate directory FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ Status %08lX\n",
211 ObjectInfoCB->FileId.Cell,
212 ObjectInfoCB->FileId.Volume,
213 ObjectInfoCB->FileId.Vnode,
214 ObjectInfoCB->FileId.Unique,
222 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
224 pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
226 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
227 AFS_TRACE_LEVEL_VERBOSE,
228 "AFSEnumerateDirectory Enumerating FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX\n",
229 ObjectInfoCB->FileId.Cell,
230 ObjectInfoCB->FileId.Volume,
231 ObjectInfoCB->FileId.Vnode,
232 ObjectInfoCB->FileId.Unique,
233 pDirEnumResponse->SnapshotDataVersion.HighPart,
234 pDirEnumResponse->SnapshotDataVersion.LowPart,
235 pDirEnumResponse->CurrentDataVersion.HighPart,
236 pDirEnumResponse->CurrentDataVersion.LowPart);
239 // Remove the leading header from the processed length
242 ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
244 while( ulResultLen > 0)
247 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
249 uniDirName.MaximumLength = uniDirName.Length;
251 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
253 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
255 uniTargetName.MaximumLength = uniTargetName.Length;
257 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
260 // Be sure we don't have this entry in the case sensitive tree
263 ulCRC = AFSGenerateCRC( &uniDirName,
266 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
270 if( pDirNode != NULL)
274 // Check that the FIDs are the same
277 if( AFSIsEqualFID( &pCurrentDirEntry->FileId,
278 &pDirNode->ObjectInformation->FileId))
282 // Duplicate entry, skip it
285 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
287 uniTargetName.Length);
289 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
291 if( ulResultLen >= ulEntryLength)
293 ulResultLen -= ulEntryLength;
301 // Update the metadata for the entry
304 if( pDirNode->ObjectInformation->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
308 AFSObjectInfoCB *pObjectInfo = pDirNode->ObjectInformation;
311 // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
314 lCount = AFSObjectInfoIncrement( pObjectInfo,
315 AFS_OBJECT_REFERENCE_INVALIDATION);
317 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
318 AFS_TRACE_LEVEL_VERBOSE,
319 "AFSEnumerateDirectory calling AFSPerformObjectInvalidate Increment count on object %p Cnt %d\n",
323 AFSPerformObjectInvalidate( pObjectInfo,
324 AFS_INVALIDATE_DATA_VERSION);
329 AFSUpdateMetaData( pDirNode,
339 // Need to tear down this entry and rebuild it below
342 if( pDirNode->DirOpenReferenceCount <= 0)
345 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
346 AFS_TRACE_LEVEL_VERBOSE,
347 "AFSEnumerateDirectory Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
349 &pDirNode->NameInformation.FileName,
350 pDirNode->ObjectInformation->FileId.Cell,
351 pDirNode->ObjectInformation->FileId.Volume,
352 pDirNode->ObjectInformation->FileId.Vnode,
353 pDirNode->ObjectInformation->FileId.Unique,
354 pCurrentDirEntry->FileId.Cell,
355 pCurrentDirEntry->FileId.Volume,
356 pCurrentDirEntry->FileId.Vnode,
357 pCurrentDirEntry->FileId.Unique);
359 AFSDeleteDirEntry( ObjectInfoCB,
365 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
367 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
368 AFS_TRACE_LEVEL_VERBOSE,
369 "AFSEnumerateDirectory Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
371 &pDirNode->NameInformation.FileName,
372 pDirNode->ObjectInformation->FileId.Cell,
373 pDirNode->ObjectInformation->FileId.Volume,
374 pDirNode->ObjectInformation->FileId.Vnode,
375 pDirNode->ObjectInformation->FileId.Unique,
376 pCurrentDirEntry->FileId.Cell,
377 pCurrentDirEntry->FileId.Volume,
378 pCurrentDirEntry->FileId.Vnode,
379 pCurrentDirEntry->FileId.Unique);
381 AFSRemoveNameEntry( ObjectInfoCB,
389 pDirNode = AFSInitDirEntry( ObjectInfoCB,
393 (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
395 if( pDirNode == NULL)
398 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
403 AFSUpdateMetaData( pDirNode,
406 if( pDirNode->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
409 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
410 AFS_TRACE_LEVEL_VERBOSE,
411 "AFSEnumerateDirectory Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
413 pDirNode->ObjectInformation->FileId.Cell,
414 pDirNode->ObjectInformation->FileId.Volume,
415 pDirNode->ObjectInformation->FileId.Vnode,
416 pDirNode->ObjectInformation->FileId.Unique);
418 AFSAcquireExcl( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
421 SetFlag( pDirNode->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
423 pDirNode->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
425 AFSReleaseResource( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
429 // Set up the entry length
432 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
433 pCurrentDirEntry->FileNameLength +
434 pCurrentDirEntry->TargetNameLength);
437 // Init the short name if we have one
440 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
441 pCurrentDirEntry->ShortNameLength > 0)
444 UNICODE_STRING uniShortName;
446 pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
448 RtlCopyMemory( pDirNode->NameInformation.ShortName,
449 pCurrentDirEntry->ShortName,
450 pDirNode->NameInformation.ShortNameLength);
453 // Generate the short name index
456 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
457 uniShortName.MaximumLength = uniShortName.Length;
458 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
460 if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
465 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
468 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
469 AFS_TRACE_LEVEL_VERBOSE,
470 "AFSEnumerateDirectory Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
473 &pDirNode->NameInformation.FileName,
474 pCurrentDirEntry->FileId.Cell,
475 pCurrentDirEntry->FileId.Volume,
476 pCurrentDirEntry->FileId.Vnode,
477 pCurrentDirEntry->FileId.Unique);
481 pDirNode->NameInformation.ShortNameLength = 0;
483 RtlZeroMemory( pDirNode->NameInformation.ShortName,
484 (12 * sizeof( WCHAR)));
491 // No short name or short names are disabled
494 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
498 // Insert the node into the name tree
501 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
504 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
506 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
507 AFS_TRACE_LEVEL_VERBOSE,
508 "AFSEnumerateDirectory Insert DE %p to head of case sensitive tree for %wZ\n",
510 &pDirNode->NameInformation.FileName);
515 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
516 AFS_TRACE_LEVEL_VERBOSE,
517 "AFSEnumerateDirectory Insert DE %p to case sensitive tree for %wZ\n",
519 &pDirNode->NameInformation.FileName);
521 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
526 // Delete this dir entry and continue on
529 AFSDeleteDirEntry( ObjectInfoCB,
532 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
534 if( ulResultLen >= ulEntryLength)
536 ulResultLen -= ulEntryLength;
547 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
549 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
552 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
553 AFS_TRACE_LEVEL_VERBOSE,
554 "AFSEnumerateDirectory Insert DE %p to head of case insensitive tree for %wZ\n",
556 &pDirNode->NameInformation.FileName);
558 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
560 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
565 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
566 AFS_TRACE_LEVEL_VERBOSE,
567 "AFSEnumerateDirectory Insert DE %p to case insensitive tree for %wZ\n",
569 &pDirNode->NameInformation.FileName);
571 AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
575 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
578 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
583 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
585 pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
588 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
590 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
592 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
594 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
595 AFS_TRACE_LEVEL_VERBOSE,
596 "AFSEnumerateDirectory Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
597 &pDirNode->NameInformation.FileName,
598 ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
599 ObjectInfoCB->FileId.Cell,
600 ObjectInfoCB->FileId.Volume,
601 ObjectInfoCB->FileId.Vnode,
602 ObjectInfoCB->FileId.Unique);
604 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
608 // Insert the short name entry if we have a valid short name
611 if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
614 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
615 AFS_TRACE_LEVEL_VERBOSE,
616 "AFSEnumerateDirectory Insert DE %p to head of shortname tree for %wZ\n",
618 &pDirNode->NameInformation.FileName);
620 ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
622 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
627 if( NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
630 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
632 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
633 AFS_TRACE_LEVEL_VERBOSE,
634 "AFSEnumerateDirectory Insert DE %p to shortname tree for %wZ\n",
636 &pDirNode->NameInformation.FileName);
645 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
647 if( ulResultLen >= ulEntryLength)
649 ulResultLen -= ulEntryLength;
657 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
660 // Reset the information in the request buffer since it got trampled
664 pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
666 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
667 AFS_TRACE_LEVEL_VERBOSE,
668 "AFSEnumerateDirectory EnumHandle %08lX\n",
669 pDirQueryCB->EnumHandle);
681 AFSExFreePoolWithTag( pBuffer, AFS_DIR_BUFFER_TAG);
685 // If the processing failed then we should reset the directory content in the event
686 // it is re-enumerated
689 if( !NT_SUCCESS( ntStatus))
692 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
693 AFS_TRACE_LEVEL_ERROR,
694 "AFSEnumerateDirectory Resetting content for FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
695 ObjectInfoCB->FileId.Cell,
696 ObjectInfoCB->FileId.Volume,
697 ObjectInfoCB->FileId.Vnode,
698 ObjectInfoCB->FileId.Unique,
701 AFSResetDirectoryContent( ObjectInfoCB);
709 AFSEnumerateDirectoryNoResponse( IN GUID *AuthGroup,
710 IN AFSFileID *FileId)
713 NTSTATUS ntStatus = STATUS_SUCCESS;
714 AFSDirQueryCB stDirQueryCB;
715 ULONG ulRequestFlags = 0;
721 // Use the payload buffer for information we will pass to the service
724 stDirQueryCB.EnumHandle = 0;
726 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
731 (void *)&stDirQueryCB,
732 sizeof( AFSDirQueryCB),
736 if( ntStatus != STATUS_SUCCESS)
739 if( ntStatus == STATUS_NO_MORE_FILES ||
740 ntStatus == STATUS_NO_MORE_ENTRIES)
743 ntStatus = STATUS_SUCCESS;
748 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
749 AFS_TRACE_LEVEL_ERROR,
750 "AFSEnumerateDirectoryNoResponse Failed to enumerate directory Status %08lX\n",
760 AFSVerifyDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB,
764 NTSTATUS ntStatus = STATUS_SUCCESS;
765 void *pBuffer = NULL;
766 ULONG ulResultLen = 0;
767 AFSDirQueryCB *pDirQueryCB;
768 AFSDirEnumEntry *pCurrentDirEntry = NULL;
769 AFSDirectoryCB *pDirNode = NULL;
770 ULONG ulEntryLength = 0;
771 AFSDirEnumResp *pDirEnumResponse = NULL;
772 UNICODE_STRING uniDirName, uniTargetName;
773 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_FAST_REQUEST;
775 AFSObjectInfoCB *pObjectInfo = NULL;
776 ULONGLONG ullIndex = 0;
777 UNICODE_STRING uniGUID;
779 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
784 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
787 uniGUID.MaximumLength = 0;
788 uniGUID.Buffer = NULL;
790 if( AuthGroup != NULL)
792 RtlStringFromGUID( *AuthGroup,
796 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
797 AFS_TRACE_LEVEL_VERBOSE,
798 "AFSVerifyDirectoryContent Verifying content for FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
799 ObjectInfoCB->FileId.Cell,
800 ObjectInfoCB->FileId.Volume,
801 ObjectInfoCB->FileId.Vnode,
802 ObjectInfoCB->FileId.Unique,
805 if( AuthGroup != NULL)
807 RtlFreeUnicodeString( &uniGUID);
811 // Initialize the directory enumeration buffer for the directory
814 pBuffer = AFSExAllocatePoolWithTag( PagedPool,
815 AFS_DIR_ENUM_BUFFER_LEN,
821 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
824 RtlZeroMemory( pBuffer,
825 AFS_DIR_ENUM_BUFFER_LEN);
827 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
830 // Use the payload buffer for information we will pass to the service
833 pDirQueryCB = (AFSDirQueryCB *)pBuffer;
835 pDirQueryCB->EnumHandle = 0;
838 // Loop on the information
845 // If the enumeration handle is -1 then we are done
848 if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
851 ntStatus = STATUS_NO_MORE_ENTRIES;
857 // Go and retrieve the directory contents
860 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
864 &ObjectInfoCB->FileId,
866 sizeof( AFSDirQueryCB),
871 if( ntStatus != STATUS_SUCCESS ||
875 if( ntStatus == STATUS_NO_MORE_FILES ||
876 ntStatus == STATUS_NO_MORE_ENTRIES)
879 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
881 AFSAcquireExcl( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock,
884 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
885 AFS_TRACE_LEVEL_VERBOSE,
886 "AFSVerifyDirectoryContent Directory Complete FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX Status %08lX\n",
887 ObjectInfoCB->FileId.Cell,
888 ObjectInfoCB->FileId.Volume,
889 ObjectInfoCB->FileId.Vnode,
890 ObjectInfoCB->FileId.Unique,
891 pDirEnumResponse->SnapshotDataVersion.HighPart,
892 pDirEnumResponse->SnapshotDataVersion.LowPart,
893 pDirEnumResponse->CurrentDataVersion.HighPart,
894 pDirEnumResponse->CurrentDataVersion.LowPart,
897 ntStatus = STATUS_SUCCESS;
899 if ( pDirEnumResponse->SnapshotDataVersion.QuadPart != pDirEnumResponse->CurrentDataVersion.QuadPart )
902 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
904 ObjectInfoCB->DataVersion.QuadPart = (ULONGLONG)-1;
906 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
907 AFS_TRACE_LEVEL_VERBOSE,
908 "AFSVerifyDirectoryContent Force Verify due to DV change during enumeration FID %08lX-%08lX-%08lX-%08lX\n",
909 ObjectInfoCB->FileId.Cell,
910 ObjectInfoCB->FileId.Volume,
911 ObjectInfoCB->FileId.Vnode,
912 ObjectInfoCB->FileId.Unique);
917 ObjectInfoCB->DataVersion = pDirEnumResponse->SnapshotDataVersion;
920 AFSReleaseResource( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock);
925 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
926 AFS_TRACE_LEVEL_ERROR,
927 "AFSVerifyDirectoryContent Failed to enumerate directory FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ Status %08lX\n",
928 ObjectInfoCB->FileId.Cell,
929 ObjectInfoCB->FileId.Volume,
930 ObjectInfoCB->FileId.Vnode,
931 ObjectInfoCB->FileId.Unique,
939 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
941 pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
943 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
944 AFS_TRACE_LEVEL_VERBOSE,
945 "AFSVerifyDirectoryContent EnumResponse FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX\n",
946 ObjectInfoCB->FileId.Cell,
947 ObjectInfoCB->FileId.Volume,
948 ObjectInfoCB->FileId.Vnode,
949 ObjectInfoCB->FileId.Unique,
950 pDirEnumResponse->SnapshotDataVersion.HighPart,
951 pDirEnumResponse->SnapshotDataVersion.LowPart,
952 pDirEnumResponse->CurrentDataVersion.HighPart,
953 pDirEnumResponse->CurrentDataVersion.LowPart);
956 // Remove the leading header from the processed length
959 ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
961 while( ulResultLen > 0)
964 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
966 uniDirName.MaximumLength = uniDirName.Length;
968 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
970 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
972 uniTargetName.MaximumLength = uniTargetName.Length;
974 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
977 // Does this entry already exist in the directory?
980 ulCRC = AFSGenerateCRC( &uniDirName,
983 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
989 // Set up the entry length
992 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
993 pCurrentDirEntry->FileNameLength +
994 pCurrentDirEntry->TargetNameLength);
997 AFSIsEqualFID( &pCurrentDirEntry->FileId,
998 &pDirNode->ObjectInformation->FileId))
1002 // Found matching directory entry by name and FileID
1005 AFSAcquireShared( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock,
1008 ullIndex = AFSCreateLowIndex( &pCurrentDirEntry->FileId);
1010 ntStatus = AFSLocateHashEntry( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeHead,
1012 (AFSBTreeEntry **)&pObjectInfo);
1014 AFSReleaseResource( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock);
1016 if( NT_SUCCESS( ntStatus) &&
1017 pObjectInfo != NULL)
1021 // Indicate this is a valid entry
1024 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
1026 if( pCurrentDirEntry->ShortNameLength > 0 &&
1027 pDirNode->NameInformation.ShortNameLength > 0)
1029 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1030 AFS_TRACE_LEVEL_VERBOSE,
1031 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name %S New short name %S\n",
1033 &pDirNode->NameInformation.FileName,
1034 ObjectInfoCB->FileId.Cell,
1035 ObjectInfoCB->FileId.Volume,
1036 ObjectInfoCB->FileId.Vnode,
1037 ObjectInfoCB->FileId.Unique,
1038 pDirNode->NameInformation.ShortName,
1039 pCurrentDirEntry->ShortName);
1041 else if( pCurrentDirEntry->ShortNameLength == 0 &&
1042 pDirNode->NameInformation.ShortNameLength > 0)
1045 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1046 AFS_TRACE_LEVEL_VERBOSE,
1047 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name %S New short name NULL\n",
1049 &pDirNode->NameInformation.FileName,
1050 ObjectInfoCB->FileId.Cell,
1051 ObjectInfoCB->FileId.Volume,
1052 ObjectInfoCB->FileId.Vnode,
1053 ObjectInfoCB->FileId.Unique,
1054 pDirNode->NameInformation.ShortName);
1056 else if( pCurrentDirEntry->ShortNameLength > 0 &&
1057 pDirNode->NameInformation.ShortNameLength == 0)
1059 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1060 AFS_TRACE_LEVEL_VERBOSE,
1061 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name %S\n",
1063 &pDirNode->NameInformation.FileName,
1064 ObjectInfoCB->FileId.Cell,
1065 ObjectInfoCB->FileId.Volume,
1066 ObjectInfoCB->FileId.Vnode,
1067 ObjectInfoCB->FileId.Unique,
1068 pCurrentDirEntry->ShortName);
1072 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1073 AFS_TRACE_LEVEL_VERBOSE,
1074 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name NULL\n",
1076 &pDirNode->NameInformation.FileName,
1077 ObjectInfoCB->FileId.Cell,
1078 ObjectInfoCB->FileId.Volume,
1079 ObjectInfoCB->FileId.Vnode,
1080 ObjectInfoCB->FileId.Unique);
1084 // Update the metadata for the entry
1087 if( pObjectInfo->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
1091 // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
1092 // if successfully queued. Cannot call AFSPerformObjectInvalidate directly
1093 // because ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock is
1094 // held during the sequence AFSVerifyEntry->AFSValidateDirectoryCache->
1095 // AFSVerifyDirectoryContent and AFSPerformObjectInvalidate requires the
1096 // Fcb->NPFcb->Resource which must be held prior to the TreeLock in the
1100 lCount = AFSObjectInfoIncrement( pObjectInfo,
1101 AFS_OBJECT_REFERENCE_INVALIDATION);
1103 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1104 AFS_TRACE_LEVEL_VERBOSE,
1105 "AFSVerifyDirectoryContent calling AFSQueueInvalidateObject Increment count on object %p Cnt %d\n",
1109 if ( !NT_SUCCESS( AFSQueueInvalidateObject( pObjectInfo,
1110 AFS_INVALIDATE_DATA_VERSION)))
1113 lCount = AFSObjectInfoDecrement( pObjectInfo,
1114 AFS_OBJECT_REFERENCE_INVALIDATION);
1116 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1117 AFS_TRACE_LEVEL_VERBOSE,
1118 "AFSVerifyDirectoryContent AFSQueueInvalidateObject failed Decrement count on object %p Cnt %d\n",
1126 AFSUpdateMetaData( pDirNode,
1134 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1136 if( ulResultLen >= ulEntryLength)
1138 ulResultLen -= ulEntryLength;
1152 // File name matches but FileID does not.
1155 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1156 AFS_TRACE_LEVEL_VERBOSE,
1157 "AFSVerifyDirectoryContent Processing dir entry %p %wZ with different FID, same name in parent FID %08lX-%08lX-%08lX-%08lX\n",
1159 &pDirNode->NameInformation.FileName,
1160 ObjectInfoCB->FileId.Cell,
1161 ObjectInfoCB->FileId.Volume,
1162 ObjectInfoCB->FileId.Vnode,
1163 ObjectInfoCB->FileId.Unique);
1166 // Need to tear down this entry and rebuild it below
1169 if( pDirNode->DirOpenReferenceCount <= 0)
1172 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1173 AFS_TRACE_LEVEL_VERBOSE,
1174 "AFSVerifyDirectoryContent Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1176 &pDirNode->NameInformation.FileName,
1177 pDirNode->ObjectInformation->FileId.Cell,
1178 pDirNode->ObjectInformation->FileId.Volume,
1179 pDirNode->ObjectInformation->FileId.Vnode,
1180 pDirNode->ObjectInformation->FileId.Unique,
1181 pCurrentDirEntry->FileId.Cell,
1182 pCurrentDirEntry->FileId.Volume,
1183 pCurrentDirEntry->FileId.Vnode,
1184 pCurrentDirEntry->FileId.Unique);
1186 AFSDeleteDirEntry( ObjectInfoCB,
1192 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1194 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1195 AFS_TRACE_LEVEL_WARNING,
1196 "AFSVerifyDirectoryContent Different FIDs - removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1198 &pDirNode->NameInformation.FileName,
1199 pDirNode->ObjectInformation->FileId.Cell,
1200 pDirNode->ObjectInformation->FileId.Volume,
1201 pDirNode->ObjectInformation->FileId.Vnode,
1202 pDirNode->ObjectInformation->FileId.Unique,
1203 pCurrentDirEntry->FileId.Cell,
1204 pCurrentDirEntry->FileId.Volume,
1205 pCurrentDirEntry->FileId.Vnode,
1206 pCurrentDirEntry->FileId.Unique);
1208 AFSRemoveNameEntry( ObjectInfoCB,
1215 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1216 AFS_TRACE_LEVEL_VERBOSE,
1217 "AFSVerifyDirectoryContent New entry %wZ for parent FID %08lX-%08lX-%08lX-%08lX\n",
1219 ObjectInfoCB->FileId.Cell,
1220 ObjectInfoCB->FileId.Volume,
1221 ObjectInfoCB->FileId.Vnode,
1222 ObjectInfoCB->FileId.Unique);
1225 pDirNode = AFSInitDirEntry( ObjectInfoCB,
1229 (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1231 if( pDirNode == NULL)
1234 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
1239 AFSUpdateMetaData( pDirNode,
1242 if( pDirNode->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1245 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1246 AFS_TRACE_LEVEL_VERBOSE,
1247 "AFSVerifyDirectoryContent Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
1249 pDirNode->ObjectInformation->FileId.Cell,
1250 pDirNode->ObjectInformation->FileId.Volume,
1251 pDirNode->ObjectInformation->FileId.Vnode,
1252 pDirNode->ObjectInformation->FileId.Unique);
1254 AFSAcquireExcl( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1257 SetFlag( pDirNode->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1259 pDirNode->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1261 AFSReleaseResource( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1265 // Init the short name if we have one
1268 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1269 pCurrentDirEntry->ShortNameLength > 0)
1272 UNICODE_STRING uniShortName;
1274 pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
1276 RtlCopyMemory( pDirNode->NameInformation.ShortName,
1277 pCurrentDirEntry->ShortName,
1278 pDirNode->NameInformation.ShortNameLength);
1281 // Generate the short name index
1284 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1285 uniShortName.MaximumLength = uniShortName.Length;
1286 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1288 if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
1293 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1296 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1297 AFS_TRACE_LEVEL_VERBOSE,
1298 "AFSVerifyDirectoryContent Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1301 &pDirNode->NameInformation.FileName,
1302 pCurrentDirEntry->FileId.Cell,
1303 pCurrentDirEntry->FileId.Volume,
1304 pCurrentDirEntry->FileId.Vnode,
1305 pCurrentDirEntry->FileId.Unique);
1309 pDirNode->NameInformation.ShortNameLength = 0;
1311 RtlZeroMemory( pDirNode->NameInformation.ShortName,
1312 (12 * sizeof( WCHAR)));
1319 // No short name or short names have been disabled
1322 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
1326 // Insert the node into the name tree
1329 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
1331 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
1334 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
1336 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1337 AFS_TRACE_LEVEL_VERBOSE,
1338 "AFSVerifyDirectoryContent Insert DE %p to head of case sensitive tree for %wZ\n",
1340 &pDirNode->NameInformation.FileName);
1345 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1348 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1349 AFS_TRACE_LEVEL_VERBOSE,
1350 "AFSVerifyDirectoryContent Failed to insert DE %p to case sensitive tree for %wZ\n",
1352 &pDirNode->NameInformation.FileName);
1355 // Delete this dir entry and continue on
1358 AFSDeleteDirEntry( ObjectInfoCB,
1361 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1363 if( ulResultLen >= ulEntryLength)
1365 ulResultLen -= ulEntryLength;
1376 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1377 AFS_TRACE_LEVEL_VERBOSE,
1378 "AFSVerifyDirectoryContent Insert DE %p to case sensitive tree for %wZ\n",
1380 &pDirNode->NameInformation.FileName);
1384 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1386 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
1389 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
1391 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
1393 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1394 AFS_TRACE_LEVEL_VERBOSE,
1395 "AFSVerifyDirectoryContent Insert DE %p to head of case insensitive tree for %wZ\n",
1397 &pDirNode->NameInformation.FileName);
1402 AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1405 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1406 AFS_TRACE_LEVEL_VERBOSE,
1407 "AFSVerifyDirectoryContent Insert DE %p to case insensitive tree for %wZ\n",
1409 &pDirNode->NameInformation.FileName);
1412 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
1415 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
1420 (ObjectInfoCB->Specific.Directory.DirectoryNodeListTail)->ListEntry.fLink = pDirNode;
1422 pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
1425 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
1427 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
1429 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
1431 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1432 AFS_TRACE_LEVEL_VERBOSE,
1433 "AFSVerifyDirectoryContent Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
1434 &pDirNode->NameInformation.FileName,
1435 ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
1436 ObjectInfoCB->FileId.Cell,
1437 ObjectInfoCB->FileId.Volume,
1438 ObjectInfoCB->FileId.Vnode,
1439 ObjectInfoCB->FileId.Unique);
1441 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
1445 // Insert the short name entry if we have a valid short name
1448 if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
1451 ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
1453 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1454 AFS_TRACE_LEVEL_VERBOSE,
1455 "AFSVerifyDirectoryContent Insert DE %p to head of shortname tree for %wZ\n",
1457 &pDirNode->NameInformation.FileName);
1459 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1464 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
1467 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1468 AFS_TRACE_LEVEL_VERBOSE,
1469 "AFSVerifyDirectoryContent Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
1471 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex,
1472 &pDirNode->NameInformation.FileName);
1476 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1478 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1479 AFS_TRACE_LEVEL_VERBOSE,
1480 "AFSVerifyDirectoryContent Insert DE %p to shortname tree for %wZ\n",
1482 &pDirNode->NameInformation.FileName);
1487 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
1493 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1495 if( ulResultLen >= ulEntryLength)
1497 ulResultLen -= ulEntryLength;
1505 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
1508 // Reset the information in the request buffer since it got trampled
1512 pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
1521 if( pBuffer != NULL)
1524 AFSExFreePoolWithTag( pBuffer, AFS_DIR_BUFFER_TAG);
1532 AFSNotifyFileCreate( IN GUID *AuthGroup,
1533 IN AFSObjectInfoCB *ParentObjectInfo,
1534 IN PLARGE_INTEGER FileSize,
1535 IN ULONG FileAttributes,
1536 IN UNICODE_STRING *FileName,
1537 OUT AFSDirectoryCB **DirNode)
1540 NTSTATUS ntStatus = STATUS_SUCCESS;
1541 AFSFileCreateCB stCreateCB;
1542 AFSFileCreateResultCB *pResultCB = NULL;
1543 ULONG ulResultLen = 0;
1544 UNICODE_STRING uniTargetName;
1545 AFSDirectoryCB *pDirNode = NULL;
1548 LARGE_INTEGER liOldDataVersion;
1549 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1550 BOOLEAN bReleaseParentTreeLock = FALSE;
1558 // Init the control block for the request
1561 RtlZeroMemory( &stCreateCB,
1562 sizeof( AFSFileCreateCB));
1564 stCreateCB.ParentId = ParentObjectInfo->FileId;
1566 stCreateCB.AllocationSize = *FileSize;
1568 stCreateCB.FileAttributes = FileAttributes;
1570 stCreateCB.EaSize = 0;
1572 liOldDataVersion = ParentObjectInfo->DataVersion;
1575 // Allocate our return buffer
1578 pResultCB = (AFSFileCreateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1580 AFS_GENERIC_MEMORY_1_TAG);
1582 if( pResultCB == NULL)
1585 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1588 RtlZeroMemory( pResultCB,
1591 ulResultLen = PAGE_SIZE;
1594 // Send the call to the service
1597 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_FILE,
1598 AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_HOLD_FID,
1603 sizeof( AFSFileCreateCB),
1607 if( ntStatus != STATUS_SUCCESS)
1610 if( NT_SUCCESS( ntStatus))
1613 ntStatus = STATUS_DEVICE_NOT_READY;
1616 try_return( ntStatus);
1620 // We may have raced with an invalidation call and a subsequent re-enumeration of this parent
1621 // and though we created the node, it is already in our list. If this is the case then
1622 // look up the entry rather than create a new entry
1623 // The check is to ensure the DV has been modified
1626 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1629 bReleaseParentTreeLock = TRUE;
1631 if( ParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
1634 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1635 AFS_TRACE_LEVEL_WARNING,
1636 "AFSNotifyFileCreate Raced with an invalidate call and a re-enumeration for entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version (%08lX:%08lX != %08lX:%08lX - 1)\n",
1638 ParentObjectInfo->FileId.Cell,
1639 ParentObjectInfo->FileId.Volume,
1640 ParentObjectInfo->FileId.Vnode,
1641 ParentObjectInfo->FileId.Unique,
1642 ParentObjectInfo->DataVersion.HighPart,
1643 ParentObjectInfo->DataVersion.LowPart,
1644 pResultCB->ParentDataVersion.HighPart,
1645 pResultCB->ParentDataVersion.LowPart);
1648 // We raced so go and lookup the directory entry in the parent
1651 ulCRC = AFSGenerateCRC( FileName,
1654 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1658 if( pDirNode != NULL)
1661 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1662 AFS_TRACE_LEVEL_VERBOSE,
1663 "AFSNotifyFileCreate Located dir entry %p for file %wZ\n",
1667 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
1668 &pResultCB->DirEnum.FileId))
1671 *DirNode = pDirNode;
1673 try_return( ntStatus = STATUS_REPARSE);
1679 // We found an entry that matches the desired name but it is not the
1680 // same as the one that was created for us by the file server.
1683 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1684 AFS_TRACE_LEVEL_ERROR,
1685 "AFSNotifyFileCreate Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
1688 pDirNode->ObjectInformation->FileId.Cell,
1689 pDirNode->ObjectInformation->FileId.Volume,
1690 pDirNode->ObjectInformation->FileId.Vnode,
1691 pDirNode->ObjectInformation->FileId.Unique,
1692 pResultCB->DirEnum.FileId.Cell,
1693 pResultCB->DirEnum.FileId.Volume,
1694 pResultCB->DirEnum.FileId.Vnode,
1695 pResultCB->DirEnum.FileId.Unique);
1697 if( pDirNode->DirOpenReferenceCount <= 0)
1700 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1701 AFS_TRACE_LEVEL_VERBOSE,
1702 "AFSNotifyFileCreate Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1704 &pDirNode->NameInformation.FileName,
1705 pDirNode->ObjectInformation->FileId.Cell,
1706 pDirNode->ObjectInformation->FileId.Volume,
1707 pDirNode->ObjectInformation->FileId.Vnode,
1708 pDirNode->ObjectInformation->FileId.Unique,
1709 pResultCB->DirEnum.FileId.Cell,
1710 pResultCB->DirEnum.FileId.Volume,
1711 pResultCB->DirEnum.FileId.Vnode,
1712 pResultCB->DirEnum.FileId.Unique);
1714 AFSDeleteDirEntry( ParentObjectInfo,
1720 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1722 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1723 AFS_TRACE_LEVEL_VERBOSE,
1724 "AFSNotifyFileCreate Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1726 &pDirNode->NameInformation.FileName,
1727 pDirNode->ObjectInformation->FileId.Cell,
1728 pDirNode->ObjectInformation->FileId.Volume,
1729 pDirNode->ObjectInformation->FileId.Vnode,
1730 pDirNode->ObjectInformation->FileId.Unique,
1731 pResultCB->DirEnum.FileId.Cell,
1732 pResultCB->DirEnum.FileId.Volume,
1733 pResultCB->DirEnum.FileId.Vnode,
1734 pResultCB->DirEnum.FileId.Unique);
1736 AFSRemoveNameEntry( ParentObjectInfo,
1745 // We are unsure of our current data so set the verify flag. It may already be set
1746 // but no big deal to reset it
1749 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1751 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1754 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1755 AFS_TRACE_LEVEL_VERBOSE,
1756 "AFSNotifyFileCreate Creating new entry %wZ\n",
1760 // Initialize the directory entry
1763 uniTargetName.Length = (USHORT)pResultCB->DirEnum.TargetNameLength;
1765 uniTargetName.MaximumLength = uniTargetName.Length;
1767 uniTargetName.Buffer = (WCHAR *)((char *)&pResultCB->DirEnum + pResultCB->DirEnum.TargetNameOffset);
1769 pDirNode = AFSInitDirEntry( ParentObjectInfo,
1772 &pResultCB->DirEnum,
1773 (ULONG)InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1775 if( pDirNode == NULL)
1778 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1780 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1782 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1786 // Init the short name if we have one
1789 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1790 pResultCB->DirEnum.ShortNameLength > 0)
1793 UNICODE_STRING uniShortName;
1795 pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
1797 RtlCopyMemory( pDirNode->NameInformation.ShortName,
1798 pResultCB->DirEnum.ShortName,
1799 pDirNode->NameInformation.ShortNameLength);
1802 // Generate the short name index
1805 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1806 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1808 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1811 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1812 AFS_TRACE_LEVEL_VERBOSE,
1813 "AFSNotifyFileCreate Initialized short name %wZ for DE %p for %wZ\n",
1816 &pDirNode->NameInformation.FileName);
1821 // No short name or short names are disabled
1824 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
1827 if ( !BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1831 // Update the parent data version
1834 ParentObjectInfo->DataVersion = pResultCB->ParentDataVersion;
1836 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1837 AFS_TRACE_LEVEL_VERBOSE,
1838 "AFSNotifyFileCreate entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
1840 ParentObjectInfo->FileId.Cell,
1841 ParentObjectInfo->FileId.Volume,
1842 ParentObjectInfo->FileId.Vnode,
1843 ParentObjectInfo->FileId.Unique,
1844 ParentObjectInfo->DataVersion.QuadPart);
1848 // Return the directory node
1851 *DirNode = pDirNode;
1855 if ( *DirNode != NULL)
1858 lCount = InterlockedIncrement( &(*DirNode)->DirOpenReferenceCount);
1860 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1861 AFS_TRACE_LEVEL_VERBOSE,
1862 "AFSNotifyFileCreate Increment count on %wZ DE %p Cnt %d\n",
1863 &(*DirNode)->NameInformation.FileName,
1867 ASSERT( lCount >= 0);
1870 if ( bReleaseParentTreeLock)
1873 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1876 if( pResultCB != NULL)
1879 AFSExFreePoolWithTag( pResultCB, AFS_GENERIC_MEMORY_1_TAG);
1887 AFSUpdateFileInformation( IN AFSFileID *ParentFid,
1888 IN AFSObjectInfoCB *ObjectInfo,
1892 NTSTATUS ntStatus = STATUS_SUCCESS;
1893 AFSFileUpdateCB stUpdateCB;
1894 ULONG ulResultLen = 0;
1895 AFSFileUpdateResultCB *pUpdateResultCB = NULL;
1901 // Init the control block for the request
1904 RtlZeroMemory( &stUpdateCB,
1905 sizeof( AFSFileUpdateCB));
1907 stUpdateCB.AllocationSize = ObjectInfo->EndOfFile;
1909 stUpdateCB.FileAttributes = ObjectInfo->FileAttributes;
1911 stUpdateCB.EaSize = ObjectInfo->EaSize;
1913 stUpdateCB.ParentId = *ParentFid;
1915 stUpdateCB.LastAccessTime = ObjectInfo->LastAccessTime;
1917 stUpdateCB.CreateTime = ObjectInfo->CreationTime;
1919 stUpdateCB.ChangeTime = ObjectInfo->ChangeTime;
1921 stUpdateCB.LastWriteTime = ObjectInfo->LastWriteTime;
1923 pUpdateResultCB = (AFSFileUpdateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1925 AFS_UPDATE_RESULT_TAG);
1927 if( pUpdateResultCB == NULL)
1930 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1933 ulResultLen = PAGE_SIZE;
1935 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_UPDATE_FILE,
1936 AFS_REQUEST_FLAG_SYNCHRONOUS,
1939 &ObjectInfo->FileId,
1941 sizeof( AFSFileUpdateCB),
1945 if( ntStatus != STATUS_SUCCESS)
1948 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1949 AFS_TRACE_LEVEL_ERROR,
1950 "AFSUpdateFileInformation failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1951 ObjectInfo->FileId.Cell,
1952 ObjectInfo->FileId.Volume,
1953 ObjectInfo->FileId.Vnode,
1954 ObjectInfo->FileId.Unique,
1957 try_return( ntStatus);
1961 // Update the data version
1964 AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1967 if ( !BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1970 ObjectInfo->DataVersion = pUpdateResultCB->DirEnum.DataVersion;
1973 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1977 if( pUpdateResultCB != NULL)
1980 AFSExFreePoolWithTag( pUpdateResultCB, AFS_UPDATE_RESULT_TAG);
1988 AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
1990 IN BOOLEAN CheckOnly)
1992 NTSTATUS ntStatus = STATUS_SUCCESS;
1993 ULONG ulResultLen = 0;
1994 AFSFileDeleteCB stDelete;
1995 AFSFileDeleteResultCB stDeleteResult;
1996 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
2001 stDelete.ParentId = DirectoryCB->ObjectInformation->ParentObjectInformation->FileId;
2003 stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
2005 ulResultLen = sizeof( AFSFileDeleteResultCB);
2009 ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
2012 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
2015 &DirectoryCB->NameInformation.FileName,
2016 &DirectoryCB->ObjectInformation->FileId,
2018 sizeof( AFSFileDeleteCB),
2022 if( ntStatus != STATUS_SUCCESS)
2025 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2026 AFS_TRACE_LEVEL_ERROR,
2027 "AFSNotifyDelete failed ParentFID %08lX-%08lX-%08lX-%08lX %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2028 stDelete.ParentId.Cell,
2029 stDelete.ParentId.Volume,
2030 stDelete.ParentId.Vnode,
2031 stDelete.ParentId.Unique,
2032 &DirectoryCB->NameInformation.FileName,
2033 DirectoryCB->ObjectInformation->FileId.Cell,
2034 DirectoryCB->ObjectInformation->FileId.Volume,
2035 DirectoryCB->ObjectInformation->FileId.Vnode,
2036 DirectoryCB->ObjectInformation->FileId.Unique,
2039 try_return( ntStatus);
2042 AFSAcquireExcl( DirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
2049 // Validate the parent data version
2052 if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
2055 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
2057 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
2064 // Update the parent data version
2067 if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart - 1)
2070 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
2072 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
2078 // TODO -- The entry must be removed from the directory at which point the
2079 // Directory data version number can be updated. Until then we must force
2082 // DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = stDeleteResult.ParentDataVersion.QuadPart;
2085 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
2087 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
2091 AFSReleaseResource( DirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2103 AFSNotifyHardLink( IN AFSObjectInfoCB *ObjectInfo,
2105 IN AFSObjectInfoCB *ParentObjectInfo,
2106 IN AFSObjectInfoCB *TargetParentObjectInfo,
2107 IN AFSDirectoryCB *SourceDirectoryCB,
2108 IN UNICODE_STRING *TargetName,
2109 IN BOOLEAN bReplaceIfExists,
2110 OUT AFSDirectoryCB **TargetDirectoryCB)
2113 NTSTATUS ntStatus = STATUS_SUCCESS;
2114 AFSFileHardLinkCB *pHardLinkCB = NULL;
2115 AFSFileHardLinkResultCB *pResultCB = NULL;
2116 ULONG ulResultLen = 0;
2117 AFSDirectoryCB *pDirNode = NULL;
2119 BOOLEAN bReleaseParentLock = FALSE, bReleaseTargetParentLock = FALSE;
2120 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2127 // Init the control block for the request
2130 pHardLinkCB = (AFSFileHardLinkCB *)AFSExAllocatePoolWithTag( PagedPool,
2132 AFS_HARDLINK_REQUEST_TAG);
2134 if( pHardLinkCB == NULL)
2137 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2140 RtlZeroMemory( pHardLinkCB,
2143 pHardLinkCB->SourceParentId = ParentObjectInfo->FileId;
2145 pHardLinkCB->TargetParentId = TargetParentObjectInfo->FileId;
2147 pHardLinkCB->TargetNameLength = TargetName->Length;
2149 RtlCopyMemory( pHardLinkCB->TargetName,
2151 TargetName->Length);
2153 pHardLinkCB->bReplaceIfExists = bReplaceIfExists;
2156 // Use the same buffer for the result control block
2159 pResultCB = (AFSFileHardLinkResultCB *)pHardLinkCB;
2161 ulResultLen = PAGE_SIZE;
2163 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_HARDLINK_FILE,
2164 AFS_REQUEST_FLAG_SYNCHRONOUS,
2166 &SourceDirectoryCB->NameInformation.FileName,
2167 &ObjectInfo->FileId,
2169 sizeof( AFSFileHardLinkCB) + TargetName->Length,
2173 if( ntStatus != STATUS_SUCCESS)
2176 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2177 AFS_TRACE_LEVEL_ERROR,
2178 "AFSNotifyHardLink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2179 ObjectInfo->FileId.Cell,
2180 ObjectInfo->FileId.Volume,
2181 ObjectInfo->FileId.Vnode,
2182 ObjectInfo->FileId.Unique,
2185 try_return( ntStatus);
2189 // Update the information from the returned data
2192 if ( ParentObjectInfo != TargetParentObjectInfo)
2195 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2198 bReleaseParentLock = TRUE;
2200 if ( ParentObjectInfo->DataVersion.QuadPart == pResultCB->SourceParentDataVersion.QuadPart - 1)
2203 ParentObjectInfo->DataVersion = pResultCB->SourceParentDataVersion;
2208 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2210 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2214 AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2217 bReleaseTargetParentLock = TRUE;
2219 if ( TargetParentObjectInfo->DataVersion.QuadPart == pResultCB->TargetParentDataVersion.QuadPart - 1)
2222 TargetParentObjectInfo->DataVersion = pResultCB->TargetParentDataVersion;
2227 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2228 AFS_TRACE_LEVEL_WARNING,
2229 "AFSNotifyHardLink Raced with an invalidate call and a re-enumeration for entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version (%08lX:%08lX != %08lX:%08lX - 1)\n",
2231 TargetParentObjectInfo->FileId.Cell,
2232 TargetParentObjectInfo->FileId.Volume,
2233 TargetParentObjectInfo->FileId.Vnode,
2234 TargetParentObjectInfo->FileId.Unique,
2235 TargetParentObjectInfo->DataVersion.HighPart,
2236 TargetParentObjectInfo->DataVersion.LowPart,
2237 pResultCB->TargetParentDataVersion.HighPart,
2238 pResultCB->TargetParentDataVersion.LowPart);
2241 // We raced so go and lookup the directory entry in the parent
2244 ulCRC = AFSGenerateCRC( TargetName,
2247 AFSLocateCaseSensitiveDirEntry( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2251 if( pDirNode != NULL)
2254 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2255 AFS_TRACE_LEVEL_VERBOSE,
2256 "AFSNotifyHardLink Located dir entry %p for file %wZ\n",
2260 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2261 &pResultCB->DirEnum.FileId))
2264 try_return( ntStatus = STATUS_REPARSE);
2270 // We found an entry that matches the desired name but it is not the
2271 // same as the one that was created for us by the file server.
2274 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2275 AFS_TRACE_LEVEL_ERROR,
2276 "AFSNotifyHardLink Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
2279 pDirNode->ObjectInformation->FileId.Cell,
2280 pDirNode->ObjectInformation->FileId.Volume,
2281 pDirNode->ObjectInformation->FileId.Vnode,
2282 pDirNode->ObjectInformation->FileId.Unique,
2283 pResultCB->DirEnum.FileId.Cell,
2284 pResultCB->DirEnum.FileId.Volume,
2285 pResultCB->DirEnum.FileId.Vnode,
2286 pResultCB->DirEnum.FileId.Unique);
2288 if( pDirNode->DirOpenReferenceCount <= 0)
2291 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2292 AFS_TRACE_LEVEL_VERBOSE,
2293 "AFSNotifyHardLink Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2295 &pDirNode->NameInformation.FileName,
2296 pDirNode->ObjectInformation->FileId.Cell,
2297 pDirNode->ObjectInformation->FileId.Volume,
2298 pDirNode->ObjectInformation->FileId.Vnode,
2299 pDirNode->ObjectInformation->FileId.Unique,
2300 pResultCB->DirEnum.FileId.Cell,
2301 pResultCB->DirEnum.FileId.Volume,
2302 pResultCB->DirEnum.FileId.Vnode,
2303 pResultCB->DirEnum.FileId.Unique);
2305 AFSDeleteDirEntry( TargetParentObjectInfo,
2311 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2313 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2314 AFS_TRACE_LEVEL_VERBOSE,
2315 "AFSNotifyHardLink Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2317 &pDirNode->NameInformation.FileName,
2318 pDirNode->ObjectInformation->FileId.Cell,
2319 pDirNode->ObjectInformation->FileId.Volume,
2320 pDirNode->ObjectInformation->FileId.Vnode,
2321 pDirNode->ObjectInformation->FileId.Unique,
2322 pResultCB->DirEnum.FileId.Cell,
2323 pResultCB->DirEnum.FileId.Volume,
2324 pResultCB->DirEnum.FileId.Vnode,
2325 pResultCB->DirEnum.FileId.Unique);
2327 AFSRemoveNameEntry( TargetParentObjectInfo,
2336 // We are unsure of our current data so set the verify flag. It may already be set
2337 // but no big deal to reset it
2340 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2342 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2346 // Create the hard link entry
2349 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2350 AFS_TRACE_LEVEL_VERBOSE,
2351 "AFSNotifyHardLink Creating new entry %wZ\n",
2355 // Initialize the directory entry
2358 pDirNode = AFSInitDirEntry( TargetParentObjectInfo,
2361 &pResultCB->DirEnum,
2362 (ULONG)InterlockedIncrement( &TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
2364 if( pDirNode == NULL)
2367 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2369 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2371 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2375 // Init the short name if we have one
2378 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2379 pResultCB->DirEnum.ShortNameLength > 0)
2382 UNICODE_STRING uniShortName;
2384 pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
2386 RtlCopyMemory( pDirNode->NameInformation.ShortName,
2387 pResultCB->DirEnum.ShortName,
2388 pDirNode->NameInformation.ShortNameLength);
2391 // Generate the short name index
2394 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
2395 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
2397 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
2400 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2401 AFS_TRACE_LEVEL_VERBOSE,
2402 "AFSNotifyHardLink Initialized short name %wZ for DE %p for %wZ\n",
2405 &pDirNode->NameInformation.FileName);
2410 // No short name or short names are disabled
2413 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2416 if ( !BooleanFlagOn( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2420 // Update the target parent data version
2423 TargetParentObjectInfo->DataVersion = pResultCB->TargetParentDataVersion;
2425 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2426 AFS_TRACE_LEVEL_VERBOSE,
2427 "AFSNotifyHardLink entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
2429 TargetParentObjectInfo->FileId.Cell,
2430 TargetParentObjectInfo->FileId.Volume,
2431 TargetParentObjectInfo->FileId.Vnode,
2432 TargetParentObjectInfo->FileId.Unique,
2433 TargetParentObjectInfo->DataVersion.QuadPart);
2438 if ( TargetDirectoryCB != NULL)
2441 lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
2443 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2444 AFS_TRACE_LEVEL_VERBOSE,
2445 "AFSNotifyHardLink Increment count on %wZ DE %p Cnt %d\n",
2446 &pDirNode->NameInformation.FileName,
2450 ASSERT( lCount >= 0);
2452 *TargetDirectoryCB = pDirNode;
2455 if ( bReleaseTargetParentLock)
2458 AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2461 if ( bReleaseParentLock)
2464 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2467 if( pHardLinkCB != NULL)
2470 AFSExFreePoolWithTag( pHardLinkCB, AFS_HARDLINK_REQUEST_TAG);
2480 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
2482 IN AFSObjectInfoCB *ParentObjectInfo,
2483 IN AFSObjectInfoCB *TargetParentObjectInfo,
2484 IN AFSDirectoryCB *DirectoryCB,
2485 IN UNICODE_STRING *TargetName,
2486 OUT AFSFileID *UpdatedFID)
2489 NTSTATUS ntStatus = STATUS_SUCCESS;
2490 AFSFileRenameCB *pRenameCB = NULL;
2491 AFSFileRenameResultCB *pRenameResultCB = NULL;
2492 ULONG ulResultLen = 0;
2493 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2499 // Init the control block for the request
2502 pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
2504 AFS_RENAME_REQUEST_TAG);
2506 if( pRenameCB == NULL)
2509 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2512 RtlZeroMemory( pRenameCB,
2515 pRenameCB->SourceParentId = ParentObjectInfo->FileId;
2517 pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
2519 pRenameCB->TargetNameLength = TargetName->Length;
2521 RtlCopyMemory( pRenameCB->TargetName,
2523 TargetName->Length);
2526 // Use the same buffer for the result control block
2529 pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
2531 ulResultLen = PAGE_SIZE;
2533 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
2534 AFS_REQUEST_FLAG_SYNCHRONOUS,
2536 &DirectoryCB->NameInformation.FileName,
2537 &ObjectInfo->FileId,
2539 sizeof( AFSFileRenameCB) + TargetName->Length,
2543 if( ntStatus != STATUS_SUCCESS)
2546 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2547 AFS_TRACE_LEVEL_ERROR,
2548 "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2549 ObjectInfo->FileId.Cell,
2550 ObjectInfo->FileId.Volume,
2551 ObjectInfo->FileId.Vnode,
2552 ObjectInfo->FileId.Unique,
2555 try_return( ntStatus);
2559 // Update the information from the returned data
2562 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2565 if ( ParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->SourceParentDataVersion.QuadPart - 1)
2568 ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
2573 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2575 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2578 if ( ParentObjectInfo != TargetParentObjectInfo)
2581 AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2584 if ( TargetParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->TargetParentDataVersion.QuadPart - 1)
2587 TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
2592 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2594 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2599 // Move over the short name
2602 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2604 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2605 DirectoryCB->NameInformation.ShortNameLength > 0)
2608 UNICODE_STRING uniShortName;
2610 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2611 uniShortName.MaximumLength = uniShortName.Length;
2612 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2614 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2615 AFS_TRACE_LEVEL_VERBOSE,
2616 "AFSNotifyRename Update old short name %wZ for DE %p for %wZ\n",
2619 &DirectoryCB->NameInformation.FileName);
2621 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2623 RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
2624 pRenameResultCB->DirEnum.ShortName,
2625 DirectoryCB->NameInformation.ShortNameLength);
2627 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2628 uniShortName.MaximumLength = uniShortName.Length;
2629 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2631 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2632 AFS_TRACE_LEVEL_VERBOSE,
2633 "AFSNotifyRename Initialized short name %wZ for DE %p for %wZ\n",
2636 &DirectoryCB->NameInformation.FileName);
2641 UNICODE_STRING uniShortName;
2643 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2644 uniShortName.MaximumLength = uniShortName.Length;
2645 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2647 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2648 AFS_TRACE_LEVEL_VERBOSE,
2649 "AFSNotifyRename Removing old short name %wZ for DE %p for %wZ\n",
2652 &DirectoryCB->NameInformation.FileName);
2654 DirectoryCB->NameInformation.ShortNameLength = 0;
2656 DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2659 if ( ParentObjectInfo != TargetParentObjectInfo)
2662 AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2665 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2667 if( UpdatedFID != NULL)
2669 *UpdatedFID = pRenameResultCB->DirEnum.FileId;
2674 if( pRenameCB != NULL)
2677 AFSExFreePoolWithTag( pRenameCB, AFS_RENAME_REQUEST_TAG);
2685 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
2687 IN BOOLEAN FastCall,
2688 OUT AFSDirEnumEntry **DirEnumEntry)
2691 NTSTATUS ntStatus = STATUS_SUCCESS;
2692 AFSEvalTargetCB stTargetID;
2693 ULONG ulResultBufferLength;
2694 AFSFileEvalResultCB *pEvalResultCB = NULL;
2695 AFSDirEnumEntry *pDirEnumCB = NULL;
2696 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
2697 AFSObjectInfoCB *pParentInfo = NULL;
2702 RtlZeroMemory( &stTargetID,
2703 sizeof( AFSEvalTargetCB));
2705 pParentInfo = ObjectInfo->ParentObjectInformation;
2707 if( pParentInfo != NULL)
2710 stTargetID.ParentId = pParentInfo->FileId;
2714 // Allocate our response buffer
2717 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2719 AFS_GENERIC_MEMORY_30_TAG);
2721 if( pEvalResultCB == NULL)
2724 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2728 // Call to the service to evaluate the fid
2731 ulResultBufferLength = PAGE_SIZE;
2736 ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
2739 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
2743 &ObjectInfo->FileId,
2745 sizeof( AFSEvalTargetCB),
2747 &ulResultBufferLength);
2749 if( ntStatus != STATUS_SUCCESS)
2753 // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
2757 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2760 if( pParentInfo != NULL)
2763 AFSAcquireExcl( pParentInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2766 SetFlag( pParentInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2768 pParentInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2770 AFSReleaseResource( pParentInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2774 try_return( ntStatus);
2778 // Validate the parent data version
2781 if ( pParentInfo != NULL)
2784 AFSAcquireExcl( pParentInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2787 if ( pParentInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2790 SetFlag( pParentInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2792 pParentInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2795 AFSReleaseResource( pParentInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2799 // Pass back the dir enum entry
2802 if( DirEnumEntry != NULL)
2805 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2807 AFS_GENERIC_MEMORY_2_TAG);
2809 if( pDirEnumCB == NULL)
2812 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2815 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2816 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2818 *DirEnumEntry = pDirEnumCB;
2823 if( pEvalResultCB != NULL)
2826 AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_30_TAG);
2829 if( !NT_SUCCESS( ntStatus))
2832 if( pDirEnumCB != NULL)
2835 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_2_TAG);
2838 *DirEnumEntry = NULL;
2846 AFSEvaluateTargetByName( IN GUID *AuthGroup,
2847 IN AFSObjectInfoCB *ParentObjectInfo,
2848 IN PUNICODE_STRING SourceName,
2849 OUT AFSDirEnumEntry **DirEnumEntry)
2852 NTSTATUS ntStatus = STATUS_SUCCESS;
2853 AFSEvalTargetCB stTargetID;
2854 ULONG ulResultBufferLength;
2855 AFSFileEvalResultCB *pEvalResultCB = NULL;
2856 AFSDirEnumEntry *pDirEnumCB = NULL;
2861 stTargetID.ParentId = ParentObjectInfo->FileId;
2864 // Allocate our response buffer
2867 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2869 AFS_GENERIC_MEMORY_31_TAG);
2871 if( pEvalResultCB == NULL)
2874 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2878 // Call to the service to evaluate the fid
2881 ulResultBufferLength = PAGE_SIZE;
2883 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
2884 AFS_REQUEST_FLAG_SYNCHRONOUS,
2889 sizeof( AFSEvalTargetCB),
2891 &ulResultBufferLength);
2893 if( ntStatus != STATUS_SUCCESS)
2896 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2899 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2902 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2904 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2906 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2909 try_return( ntStatus);
2913 // Validate the parent data version
2916 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,