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;
63 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
66 uniGUID.MaximumLength = 0;
67 uniGUID.Buffer = NULL;
69 if( AuthGroup != NULL)
71 RtlStringFromGUID( *AuthGroup,
75 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
76 AFS_TRACE_LEVEL_VERBOSE,
77 "AFSEnumerateDirectory Enumerating FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
78 ObjectInfoCB->FileId.Cell,
79 ObjectInfoCB->FileId.Volume,
80 ObjectInfoCB->FileId.Vnode,
81 ObjectInfoCB->FileId.Unique,
84 if( AuthGroup != NULL)
86 RtlFreeUnicodeString( &uniGUID);
90 // Initialize the directory enumeration buffer for the directory
93 pBuffer = AFSExAllocatePoolWithTag( PagedPool,
94 AFS_DIR_ENUM_BUFFER_LEN,
100 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
103 RtlZeroMemory( pBuffer,
104 AFS_DIR_ENUM_BUFFER_LEN);
106 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
109 // Use the payload buffer for information we will pass to the service
112 pDirQueryCB = (AFSDirQueryCB *)pBuffer;
114 pDirQueryCB->EnumHandle = 0;
119 ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
123 // Loop on the information
130 // If the enumeration handle is -1 then we are done
133 if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
136 ntStatus = STATUS_NO_MORE_ENTRIES;
142 // Go and retrieve the directory contents
145 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
149 &ObjectInfoCB->FileId,
151 sizeof( AFSDirQueryCB),
156 if( ntStatus != STATUS_SUCCESS ||
160 if( ntStatus == STATUS_NO_MORE_FILES ||
161 ntStatus == STATUS_NO_MORE_ENTRIES)
164 ntStatus = STATUS_SUCCESS;
166 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
168 AFSAcquireExcl( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock,
171 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
172 AFS_TRACE_LEVEL_VERBOSE,
173 "AFSEnumerateDirectory Directory Complete FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX Status %08lX\n",
174 ObjectInfoCB->FileId.Cell,
175 ObjectInfoCB->FileId.Volume,
176 ObjectInfoCB->FileId.Vnode,
177 ObjectInfoCB->FileId.Unique,
178 pDirEnumResponse->SnapshotDataVersion.HighPart,
179 pDirEnumResponse->SnapshotDataVersion.LowPart,
180 pDirEnumResponse->CurrentDataVersion.HighPart,
181 pDirEnumResponse->CurrentDataVersion.LowPart,
184 ObjectInfoCB->DataVersion = pDirEnumResponse->SnapshotDataVersion;
186 if ( pDirEnumResponse->SnapshotDataVersion.QuadPart != pDirEnumResponse->CurrentDataVersion.QuadPart )
189 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
191 ObjectInfoCB->DataVersion.QuadPart = (ULONGLONG)-1;
193 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
194 AFS_TRACE_LEVEL_VERBOSE,
195 "AFSEnumerateDirectory Force Verify due to DV change during enumeration FID %08lX-%08lX-%08lX-%08lX\n",
196 ObjectInfoCB->FileId.Cell,
197 ObjectInfoCB->FileId.Volume,
198 ObjectInfoCB->FileId.Vnode,
199 ObjectInfoCB->FileId.Unique);
202 AFSReleaseResource( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock);
207 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
208 AFS_TRACE_LEVEL_VERBOSE,
209 "AFSEnumerateDirectory Failed to enumerate directory FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ Status %08lX\n",
210 ObjectInfoCB->FileId.Cell,
211 ObjectInfoCB->FileId.Volume,
212 ObjectInfoCB->FileId.Vnode,
213 ObjectInfoCB->FileId.Unique,
221 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
223 pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
225 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
226 AFS_TRACE_LEVEL_VERBOSE,
227 "AFSEnumerateDirectory Enumerating FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX\n",
228 ObjectInfoCB->FileId.Cell,
229 ObjectInfoCB->FileId.Volume,
230 ObjectInfoCB->FileId.Vnode,
231 ObjectInfoCB->FileId.Unique,
232 pDirEnumResponse->SnapshotDataVersion.HighPart,
233 pDirEnumResponse->SnapshotDataVersion.LowPart,
234 pDirEnumResponse->CurrentDataVersion.HighPart,
235 pDirEnumResponse->CurrentDataVersion.LowPart);
238 // Remove the leading header from the processed length
241 ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
243 while( ulResultLen > 0)
246 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
248 uniDirName.MaximumLength = uniDirName.Length;
250 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
252 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
254 uniTargetName.MaximumLength = uniTargetName.Length;
256 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
259 // Be sure we don't have this entry in the case sensitive tree
262 ulCRC = AFSGenerateCRC( &uniDirName,
265 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
269 if( pDirNode != NULL)
273 // Check that the FIDs are the same
276 if( AFSIsEqualFID( &pCurrentDirEntry->FileId,
277 &pDirNode->ObjectInformation->FileId))
281 // Duplicate entry, skip it
284 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
286 uniTargetName.Length);
288 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
290 if( ulResultLen >= ulEntryLength)
292 ulResultLen -= ulEntryLength;
300 // Update the metadata for the entry
303 if( pDirNode->ObjectInformation->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
306 AFSInvalidateObject( &pDirNode->ObjectInformation,
307 + AFS_INVALIDATE_DATA_VERSION);
312 AFSUpdateMetaData( pDirNode,
322 // Need to tear down this entry and rebuild it below
325 if( pDirNode->OpenReferenceCount == 0)
328 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
329 AFS_TRACE_LEVEL_VERBOSE,
330 "AFSEnumerateDirectory Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
332 &pDirNode->NameInformation.FileName,
333 pDirNode->ObjectInformation->FileId.Cell,
334 pDirNode->ObjectInformation->FileId.Volume,
335 pDirNode->ObjectInformation->FileId.Vnode,
336 pDirNode->ObjectInformation->FileId.Unique,
337 pCurrentDirEntry->FileId.Cell,
338 pCurrentDirEntry->FileId.Volume,
339 pCurrentDirEntry->FileId.Vnode,
340 pCurrentDirEntry->FileId.Unique);
342 AFSDeleteDirEntry( ObjectInfoCB,
348 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
350 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
351 AFS_TRACE_LEVEL_VERBOSE,
352 "AFSEnumerateDirectory Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
354 &pDirNode->NameInformation.FileName,
355 pDirNode->ObjectInformation->FileId.Cell,
356 pDirNode->ObjectInformation->FileId.Volume,
357 pDirNode->ObjectInformation->FileId.Vnode,
358 pDirNode->ObjectInformation->FileId.Unique,
359 pCurrentDirEntry->FileId.Cell,
360 pCurrentDirEntry->FileId.Volume,
361 pCurrentDirEntry->FileId.Vnode,
362 pCurrentDirEntry->FileId.Unique);
364 AFSRemoveNameEntry( ObjectInfoCB,
372 pDirNode = AFSInitDirEntry( ObjectInfoCB,
376 (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
378 if( pDirNode == NULL)
381 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
386 AFSUpdateMetaData( pDirNode,
389 if( pDirNode->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
392 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
393 AFS_TRACE_LEVEL_VERBOSE,
394 "AFSEnumerateDirectory Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
396 pDirNode->ObjectInformation->FileId.Cell,
397 pDirNode->ObjectInformation->FileId.Volume,
398 pDirNode->ObjectInformation->FileId.Vnode,
399 pDirNode->ObjectInformation->FileId.Unique);
401 AFSAcquireExcl( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
404 SetFlag( pDirNode->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
406 pDirNode->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
408 AFSReleaseResource( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
412 // Set up the entry length
415 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
416 pCurrentDirEntry->FileNameLength +
417 pCurrentDirEntry->TargetNameLength);
420 // Init the short name if we have one
423 if( pCurrentDirEntry->ShortNameLength > 0)
426 UNICODE_STRING uniShortName;
428 pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
430 RtlCopyMemory( pDirNode->NameInformation.ShortName,
431 pCurrentDirEntry->ShortName,
432 pDirNode->NameInformation.ShortNameLength);
435 // Generate the short name index
438 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
439 uniShortName.MaximumLength = uniShortName.Length;
440 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
442 if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
447 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
450 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
451 AFS_TRACE_LEVEL_VERBOSE,
452 "AFSEnumerateDirectory Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
455 &pDirNode->NameInformation.FileName,
456 pCurrentDirEntry->FileId.Cell,
457 pCurrentDirEntry->FileId.Volume,
458 pCurrentDirEntry->FileId.Vnode,
459 pCurrentDirEntry->FileId.Unique);
463 pDirNode->NameInformation.ShortNameLength = 0;
465 RtlZeroMemory( pDirNode->NameInformation.ShortName,
466 (12 * sizeof( WCHAR)));
471 // Insert the node into the name tree
474 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
477 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
479 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
480 AFS_TRACE_LEVEL_VERBOSE,
481 "AFSEnumerateDirectory Insert DE %p to head of case sensitive tree for %wZ\n",
483 &pDirNode->NameInformation.FileName);
488 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
489 AFS_TRACE_LEVEL_VERBOSE,
490 "AFSEnumerateDirectory Insert DE %p to case sensitive tree for %wZ\n",
492 &pDirNode->NameInformation.FileName);
494 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
499 // Delete this dir entry and continue on
502 AFSDeleteDirEntry( ObjectInfoCB,
505 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
507 if( ulResultLen >= ulEntryLength)
509 ulResultLen -= ulEntryLength;
520 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
522 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
525 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
526 AFS_TRACE_LEVEL_VERBOSE,
527 "AFSEnumerateDirectory Insert DE %p to head of case insensitive tree for %wZ\n",
529 &pDirNode->NameInformation.FileName);
531 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
533 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
538 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
539 AFS_TRACE_LEVEL_VERBOSE,
540 "AFSEnumerateDirectory Insert DE %p to case insensitive tree for %wZ\n",
542 &pDirNode->NameInformation.FileName);
544 AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
548 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
551 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
556 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
558 pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
561 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
563 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
565 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
567 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
568 AFS_TRACE_LEVEL_VERBOSE,
569 "AFSEnumerateDirectory Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
570 &pDirNode->NameInformation.FileName,
571 ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
572 ObjectInfoCB->FileId.Cell,
573 ObjectInfoCB->FileId.Volume,
574 ObjectInfoCB->FileId.Vnode,
575 ObjectInfoCB->FileId.Unique);
577 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
581 // Insert the short name entry if we have a valid short name
584 if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
587 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
588 AFS_TRACE_LEVEL_VERBOSE,
589 "AFSEnumerateDirectory Insert DE %p to head of shortname tree for %wZ\n",
591 &pDirNode->NameInformation.FileName);
593 ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
595 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
600 if( NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
603 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
605 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
606 AFS_TRACE_LEVEL_VERBOSE,
607 "AFSEnumerateDirectory Insert DE %p to shortname tree for %wZ\n",
609 &pDirNode->NameInformation.FileName);
618 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
620 if( ulResultLen >= ulEntryLength)
622 ulResultLen -= ulEntryLength;
630 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
633 // Reset the information in the request buffer since it got trampled
637 pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
639 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
640 AFS_TRACE_LEVEL_VERBOSE,
641 "AFSEnumerateDirectory EnumHandle %08lX\n",
642 pDirQueryCB->EnumHandle);
654 AFSExFreePool( pBuffer);
658 // If the processing failed then we should reset the directory content in the event
659 // it is re-enumerated
662 if( !NT_SUCCESS( ntStatus))
665 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
666 AFS_TRACE_LEVEL_ERROR,
667 "AFSEnumerateDirectory Resetting content for FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
668 ObjectInfoCB->FileId.Cell,
669 ObjectInfoCB->FileId.Volume,
670 ObjectInfoCB->FileId.Vnode,
671 ObjectInfoCB->FileId.Unique,
674 AFSResetDirectoryContent( ObjectInfoCB);
682 AFSEnumerateDirectoryNoResponse( IN GUID *AuthGroup,
683 IN AFSFileID *FileId)
686 NTSTATUS ntStatus = STATUS_SUCCESS;
687 AFSDirQueryCB stDirQueryCB;
688 ULONG ulRequestFlags = 0;
694 // Use the payload buffer for information we will pass to the service
697 stDirQueryCB.EnumHandle = 0;
699 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
704 (void *)&stDirQueryCB,
705 sizeof( AFSDirQueryCB),
709 if( ntStatus != STATUS_SUCCESS)
712 if( ntStatus == STATUS_NO_MORE_FILES ||
713 ntStatus == STATUS_NO_MORE_ENTRIES)
716 ntStatus = STATUS_SUCCESS;
721 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
722 AFS_TRACE_LEVEL_ERROR,
723 "AFSEnumerateDirectoryNoResponse Failed to enumerate directory Status %08lX\n",
733 AFSVerifyDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB,
737 NTSTATUS ntStatus = STATUS_SUCCESS;
738 void *pBuffer = NULL;
739 ULONG ulResultLen = 0;
740 AFSDirQueryCB *pDirQueryCB;
741 AFSDirEnumEntry *pCurrentDirEntry = NULL;
742 AFSDirectoryCB *pDirNode = NULL;
743 ULONG ulEntryLength = 0;
744 AFSDirEnumResp *pDirEnumResponse = NULL;
745 UNICODE_STRING uniDirName, uniTargetName;
746 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_FAST_REQUEST;
748 AFSObjectInfoCB *pObjectInfo = NULL;
749 ULONGLONG ullIndex = 0;
750 UNICODE_STRING uniGUID;
755 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
758 uniGUID.MaximumLength = 0;
759 uniGUID.Buffer = NULL;
761 if( AuthGroup != NULL)
763 RtlStringFromGUID( *AuthGroup,
767 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
768 AFS_TRACE_LEVEL_VERBOSE,
769 "AFSVerifyDirectoryContent Verifying content for FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
770 ObjectInfoCB->FileId.Cell,
771 ObjectInfoCB->FileId.Volume,
772 ObjectInfoCB->FileId.Vnode,
773 ObjectInfoCB->FileId.Unique,
776 if( AuthGroup != NULL)
778 RtlFreeUnicodeString( &uniGUID);
782 // Initialize the directory enumeration buffer for the directory
785 pBuffer = AFSExAllocatePoolWithTag( PagedPool,
786 AFS_DIR_ENUM_BUFFER_LEN,
792 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
795 RtlZeroMemory( pBuffer,
796 AFS_DIR_ENUM_BUFFER_LEN);
798 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
801 // Use the payload buffer for information we will pass to the service
804 pDirQueryCB = (AFSDirQueryCB *)pBuffer;
806 pDirQueryCB->EnumHandle = 0;
809 // Loop on the information
816 // If the enumeration handle is -1 then we are done
819 if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
822 ntStatus = STATUS_NO_MORE_ENTRIES;
828 // Go and retrieve the directory contents
831 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
835 &ObjectInfoCB->FileId,
837 sizeof( AFSDirQueryCB),
842 if( ntStatus != STATUS_SUCCESS ||
846 if( ntStatus == STATUS_NO_MORE_FILES ||
847 ntStatus == STATUS_NO_MORE_ENTRIES)
850 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
852 AFSAcquireExcl( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock,
855 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
856 AFS_TRACE_LEVEL_VERBOSE,
857 "AFSVerifyDirectoryContent Directory Complete FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX Status %08lX\n",
858 ObjectInfoCB->FileId.Cell,
859 ObjectInfoCB->FileId.Volume,
860 ObjectInfoCB->FileId.Vnode,
861 ObjectInfoCB->FileId.Unique,
862 pDirEnumResponse->SnapshotDataVersion.HighPart,
863 pDirEnumResponse->SnapshotDataVersion.LowPart,
864 pDirEnumResponse->CurrentDataVersion.HighPart,
865 pDirEnumResponse->CurrentDataVersion.LowPart,
868 ntStatus = STATUS_SUCCESS;
870 if ( pDirEnumResponse->SnapshotDataVersion.QuadPart != pDirEnumResponse->CurrentDataVersion.QuadPart )
873 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
875 ObjectInfoCB->DataVersion.QuadPart = (ULONGLONG)-1;
877 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
878 AFS_TRACE_LEVEL_VERBOSE,
879 "AFSVerifyDirectoryContent Force Verify due to DV change during enumeration FID %08lX-%08lX-%08lX-%08lX\n",
880 ObjectInfoCB->FileId.Cell,
881 ObjectInfoCB->FileId.Volume,
882 ObjectInfoCB->FileId.Vnode,
883 ObjectInfoCB->FileId.Unique);
888 ObjectInfoCB->DataVersion = pDirEnumResponse->SnapshotDataVersion;
891 AFSReleaseResource( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock);
896 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
897 AFS_TRACE_LEVEL_ERROR,
898 "AFSVerifyDirectoryContent Failed to enumerate directory FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ Status %08lX\n",
899 ObjectInfoCB->FileId.Cell,
900 ObjectInfoCB->FileId.Volume,
901 ObjectInfoCB->FileId.Vnode,
902 ObjectInfoCB->FileId.Unique,
910 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
912 pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
914 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
915 AFS_TRACE_LEVEL_VERBOSE,
916 "AFSVerifyDirectoryContent EnumResponse FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX\n",
917 ObjectInfoCB->FileId.Cell,
918 ObjectInfoCB->FileId.Volume,
919 ObjectInfoCB->FileId.Vnode,
920 ObjectInfoCB->FileId.Unique,
921 pDirEnumResponse->SnapshotDataVersion.HighPart,
922 pDirEnumResponse->SnapshotDataVersion.LowPart,
923 pDirEnumResponse->CurrentDataVersion.HighPart,
924 pDirEnumResponse->CurrentDataVersion.LowPart);
927 // Remove the leading header from the processed length
930 ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
932 while( ulResultLen > 0)
935 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
937 uniDirName.MaximumLength = uniDirName.Length;
939 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
941 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
943 uniTargetName.MaximumLength = uniTargetName.Length;
945 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
948 // Does this entry already exist in the directory?
951 ulCRC = AFSGenerateCRC( &uniDirName,
954 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
960 // Set up the entry length
963 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
964 pCurrentDirEntry->FileNameLength +
965 pCurrentDirEntry->TargetNameLength);
968 AFSIsEqualFID( &pCurrentDirEntry->FileId,
969 &pDirNode->ObjectInformation->FileId))
973 // Found matching directory entry by name and FileID
976 AFSAcquireShared( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock,
979 ullIndex = AFSCreateLowIndex( &pCurrentDirEntry->FileId);
981 ntStatus = AFSLocateHashEntry( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeHead,
983 (AFSBTreeEntry **)&pObjectInfo);
985 AFSReleaseResource( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock);
987 if( NT_SUCCESS( ntStatus) &&
992 // Indicate this is a valid entry
995 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
997 if( pCurrentDirEntry->ShortNameLength > 0 &&
998 pDirNode->NameInformation.ShortNameLength > 0)
1000 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1001 AFS_TRACE_LEVEL_VERBOSE,
1002 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name %S New short name %S\n",
1004 &pDirNode->NameInformation.FileName,
1005 ObjectInfoCB->FileId.Cell,
1006 ObjectInfoCB->FileId.Volume,
1007 ObjectInfoCB->FileId.Vnode,
1008 ObjectInfoCB->FileId.Unique,
1009 pDirNode->NameInformation.ShortName,
1010 pCurrentDirEntry->ShortName);
1012 else if( pCurrentDirEntry->ShortNameLength == 0 &&
1013 pDirNode->NameInformation.ShortNameLength > 0)
1016 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1017 AFS_TRACE_LEVEL_VERBOSE,
1018 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name %S New short name NULL\n",
1020 &pDirNode->NameInformation.FileName,
1021 ObjectInfoCB->FileId.Cell,
1022 ObjectInfoCB->FileId.Volume,
1023 ObjectInfoCB->FileId.Vnode,
1024 ObjectInfoCB->FileId.Unique,
1025 pDirNode->NameInformation.ShortName);
1027 else if( pCurrentDirEntry->ShortNameLength > 0 &&
1028 pDirNode->NameInformation.ShortNameLength == 0)
1030 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1031 AFS_TRACE_LEVEL_VERBOSE,
1032 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name %S\n",
1034 &pDirNode->NameInformation.FileName,
1035 ObjectInfoCB->FileId.Cell,
1036 ObjectInfoCB->FileId.Volume,
1037 ObjectInfoCB->FileId.Vnode,
1038 ObjectInfoCB->FileId.Unique,
1039 pCurrentDirEntry->ShortName);
1043 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1044 AFS_TRACE_LEVEL_VERBOSE,
1045 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name NULL\n",
1047 &pDirNode->NameInformation.FileName,
1048 ObjectInfoCB->FileId.Cell,
1049 ObjectInfoCB->FileId.Volume,
1050 ObjectInfoCB->FileId.Vnode,
1051 ObjectInfoCB->FileId.Unique);
1055 // Update the metadata for the entry
1058 if( pObjectInfo->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
1061 AFSInvalidateObject( &pObjectInfo,
1062 AFS_INVALIDATE_DATA_VERSION);
1067 AFSUpdateMetaData( pDirNode,
1075 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1077 if( ulResultLen >= ulEntryLength)
1079 ulResultLen -= ulEntryLength;
1093 // File name matches but FileID does not.
1096 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1097 AFS_TRACE_LEVEL_VERBOSE,
1098 "AFSVerifyDirectoryContent Processing dir entry %p %wZ with different FID, same name in parent FID %08lX-%08lX-%08lX-%08lX\n",
1100 &pDirNode->NameInformation.FileName,
1101 ObjectInfoCB->FileId.Cell,
1102 ObjectInfoCB->FileId.Volume,
1103 ObjectInfoCB->FileId.Vnode,
1104 ObjectInfoCB->FileId.Unique);
1107 // Need to tear down this entry and rebuild it below
1110 if( pDirNode->OpenReferenceCount == 0)
1113 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1114 AFS_TRACE_LEVEL_VERBOSE,
1115 "AFSVerifyDirectoryContent Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1117 &pDirNode->NameInformation.FileName,
1118 pDirNode->ObjectInformation->FileId.Cell,
1119 pDirNode->ObjectInformation->FileId.Volume,
1120 pDirNode->ObjectInformation->FileId.Vnode,
1121 pDirNode->ObjectInformation->FileId.Unique,
1122 pCurrentDirEntry->FileId.Cell,
1123 pCurrentDirEntry->FileId.Volume,
1124 pCurrentDirEntry->FileId.Vnode,
1125 pCurrentDirEntry->FileId.Unique);
1127 AFSDeleteDirEntry( ObjectInfoCB,
1133 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1135 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1136 AFS_TRACE_LEVEL_WARNING,
1137 "AFSVerifyDirectoryContent Different FIDs - removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1139 &pDirNode->NameInformation.FileName,
1140 pDirNode->ObjectInformation->FileId.Cell,
1141 pDirNode->ObjectInformation->FileId.Volume,
1142 pDirNode->ObjectInformation->FileId.Vnode,
1143 pDirNode->ObjectInformation->FileId.Unique,
1144 pCurrentDirEntry->FileId.Cell,
1145 pCurrentDirEntry->FileId.Volume,
1146 pCurrentDirEntry->FileId.Vnode,
1147 pCurrentDirEntry->FileId.Unique);
1149 AFSRemoveNameEntry( ObjectInfoCB,
1156 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1157 AFS_TRACE_LEVEL_VERBOSE,
1158 "AFSVerifyDirectoryContent New entry %wZ for parent FID %08lX-%08lX-%08lX-%08lX\n",
1160 ObjectInfoCB->FileId.Cell,
1161 ObjectInfoCB->FileId.Volume,
1162 ObjectInfoCB->FileId.Vnode,
1163 ObjectInfoCB->FileId.Unique);
1166 pDirNode = AFSInitDirEntry( ObjectInfoCB,
1170 (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1172 if( pDirNode == NULL)
1175 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
1180 AFSUpdateMetaData( pDirNode,
1183 if( pDirNode->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1186 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1187 AFS_TRACE_LEVEL_VERBOSE,
1188 "AFSVerifyDirectoryContent Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
1190 pDirNode->ObjectInformation->FileId.Cell,
1191 pDirNode->ObjectInformation->FileId.Volume,
1192 pDirNode->ObjectInformation->FileId.Vnode,
1193 pDirNode->ObjectInformation->FileId.Unique);
1195 AFSAcquireExcl( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1198 SetFlag( pDirNode->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1200 pDirNode->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1202 AFSReleaseResource( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1206 // Init the short name if we have one
1209 if( pCurrentDirEntry->ShortNameLength > 0)
1212 UNICODE_STRING uniShortName;
1214 pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
1216 RtlCopyMemory( pDirNode->NameInformation.ShortName,
1217 pCurrentDirEntry->ShortName,
1218 pDirNode->NameInformation.ShortNameLength);
1221 // Generate the short name index
1224 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1225 uniShortName.MaximumLength = uniShortName.Length;
1226 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1228 if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
1233 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1236 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1237 AFS_TRACE_LEVEL_VERBOSE,
1238 "AFSVerifyDirectoryContent Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1241 &pDirNode->NameInformation.FileName,
1242 pCurrentDirEntry->FileId.Cell,
1243 pCurrentDirEntry->FileId.Volume,
1244 pCurrentDirEntry->FileId.Vnode,
1245 pCurrentDirEntry->FileId.Unique);
1249 pDirNode->NameInformation.ShortNameLength = 0;
1251 RtlZeroMemory( pDirNode->NameInformation.ShortName,
1252 (12 * sizeof( WCHAR)));
1258 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1259 AFS_TRACE_LEVEL_VERBOSE,
1260 "AFSVerifyDirectoryContent NO short name for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1262 &pDirNode->NameInformation.FileName,
1263 pCurrentDirEntry->FileId.Cell,
1264 pCurrentDirEntry->FileId.Volume,
1265 pCurrentDirEntry->FileId.Vnode,
1266 pCurrentDirEntry->FileId.Unique);
1270 // Insert the node into the name tree
1273 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
1275 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
1278 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
1280 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1281 AFS_TRACE_LEVEL_VERBOSE,
1282 "AFSVerifyDirectoryContent Insert DE %p to head of case sensitive tree for %wZ\n",
1284 &pDirNode->NameInformation.FileName);
1289 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1292 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1293 AFS_TRACE_LEVEL_VERBOSE,
1294 "AFSVerifyDirectoryContent Failed to insert DE %p to case sensitive tree for %wZ\n",
1296 &pDirNode->NameInformation.FileName);
1299 // Delete this dir entry and continue on
1302 AFSDeleteDirEntry( ObjectInfoCB,
1305 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1307 if( ulResultLen >= ulEntryLength)
1309 ulResultLen -= ulEntryLength;
1320 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1321 AFS_TRACE_LEVEL_VERBOSE,
1322 "AFSVerifyDirectoryContent Insert DE %p to case sensitive tree for %wZ\n",
1324 &pDirNode->NameInformation.FileName);
1328 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1330 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
1333 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
1335 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
1337 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1338 AFS_TRACE_LEVEL_VERBOSE,
1339 "AFSVerifyDirectoryContent Insert DE %p to head of case insensitive tree for %wZ\n",
1341 &pDirNode->NameInformation.FileName);
1346 AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1349 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1350 AFS_TRACE_LEVEL_VERBOSE,
1351 "AFSVerifyDirectoryContent Insert DE %p to case insensitive tree for %wZ\n",
1353 &pDirNode->NameInformation.FileName);
1356 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
1359 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
1364 (ObjectInfoCB->Specific.Directory.DirectoryNodeListTail)->ListEntry.fLink = pDirNode;
1366 pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
1369 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
1371 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
1373 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
1375 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1376 AFS_TRACE_LEVEL_VERBOSE,
1377 "AFSVerifyDirectoryContent Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
1378 &pDirNode->NameInformation.FileName,
1379 ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
1380 ObjectInfoCB->FileId.Cell,
1381 ObjectInfoCB->FileId.Volume,
1382 ObjectInfoCB->FileId.Vnode,
1383 ObjectInfoCB->FileId.Unique);
1385 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
1389 // Insert the short name entry if we have a valid short name
1392 if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
1395 ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
1397 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1398 AFS_TRACE_LEVEL_VERBOSE,
1399 "AFSVerifyDirectoryContent Insert DE %p to head of shortname tree for %wZ\n",
1401 &pDirNode->NameInformation.FileName);
1403 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1408 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
1411 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1412 AFS_TRACE_LEVEL_VERBOSE,
1413 "AFSVerifyDirectoryContent Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
1415 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex,
1416 &pDirNode->NameInformation.FileName);
1420 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1422 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1423 AFS_TRACE_LEVEL_VERBOSE,
1424 "AFSVerifyDirectoryContent Insert DE %p to shortname tree for %wZ\n",
1426 &pDirNode->NameInformation.FileName);
1431 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
1437 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1439 if( ulResultLen >= ulEntryLength)
1441 ulResultLen -= ulEntryLength;
1449 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
1452 // Reset the information in the request buffer since it got trampled
1456 pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
1465 if( pBuffer != NULL)
1468 AFSExFreePool( pBuffer);
1476 AFSNotifyFileCreate( IN GUID *AuthGroup,
1477 IN AFSObjectInfoCB *ParentObjectInfo,
1478 IN PLARGE_INTEGER FileSize,
1479 IN ULONG FileAttributes,
1480 IN UNICODE_STRING *FileName,
1481 OUT AFSDirectoryCB **DirNode)
1484 NTSTATUS ntStatus = STATUS_SUCCESS;
1485 AFSFileCreateCB stCreateCB;
1486 AFSFileCreateResultCB *pResultCB = NULL;
1487 ULONG ulResultLen = 0;
1488 UNICODE_STRING uniTargetName;
1489 AFSDirectoryCB *pDirNode = NULL;
1491 LARGE_INTEGER liOldDataVersion;
1497 // Init the control block for the request
1500 RtlZeroMemory( &stCreateCB,
1501 sizeof( AFSFileCreateCB));
1503 stCreateCB.ParentId = ParentObjectInfo->FileId;
1505 stCreateCB.AllocationSize = *FileSize;
1507 stCreateCB.FileAttributes = FileAttributes;
1509 stCreateCB.EaSize = 0;
1511 liOldDataVersion = ParentObjectInfo->DataVersion;
1514 // Allocate our return buffer
1517 pResultCB = (AFSFileCreateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1519 AFS_GENERIC_MEMORY_1_TAG);
1521 if( pResultCB == NULL)
1524 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1527 RtlZeroMemory( pResultCB,
1530 ulResultLen = PAGE_SIZE;
1533 // Send the call to the service
1536 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_FILE,
1537 AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_HOLD_FID,
1542 sizeof( AFSFileCreateCB),
1546 if( ntStatus != STATUS_SUCCESS)
1549 if( NT_SUCCESS( ntStatus))
1552 ntStatus = STATUS_DEVICE_NOT_READY;
1555 try_return( ntStatus);
1559 // We may have raced with an invalidation call and a subsequent re-enumeration of this parent
1560 // and though we created the node, it is already in our list. If this is the case then
1561 // look up the entry rather than create a new entry
1562 // The check is to ensure the DV has been modified
1565 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1568 if( ParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
1571 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1572 AFS_TRACE_LEVEL_WARNING,
1573 "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",
1575 ParentObjectInfo->FileId.Cell,
1576 ParentObjectInfo->FileId.Volume,
1577 ParentObjectInfo->FileId.Vnode,
1578 ParentObjectInfo->FileId.Unique,
1579 ParentObjectInfo->DataVersion.QuadPart,
1580 pResultCB->ParentDataVersion.QuadPart);
1583 // We raced so go and lookup the directory entry in the parent
1586 ulCRC = AFSGenerateCRC( FileName,
1589 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1593 if( pDirNode != NULL)
1596 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1597 AFS_TRACE_LEVEL_VERBOSE,
1598 "AFSNotifyFileCreate Located dir entry %p for file %wZ\n",
1602 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
1603 &pResultCB->DirEnum.FileId))
1606 InterlockedIncrement( &pDirNode->OpenReferenceCount);
1608 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1609 AFS_TRACE_LEVEL_VERBOSE,
1610 "AFSNotifyFileCreate Increment count on %wZ DE %p Cnt %d\n",
1611 &pDirNode->NameInformation.FileName,
1613 pDirNode->OpenReferenceCount);
1615 *DirNode = pDirNode;
1617 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1619 try_return( ntStatus = STATUS_REPARSE);
1625 // We found an entry that matches the desired name but it is not the
1626 // same as the one that was created for us by the file server.
1629 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1630 AFS_TRACE_LEVEL_ERROR,
1631 "AFSNotifyFileCreate Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
1634 pDirNode->ObjectInformation->FileId.Cell,
1635 pDirNode->ObjectInformation->FileId.Volume,
1636 pDirNode->ObjectInformation->FileId.Vnode,
1637 pDirNode->ObjectInformation->FileId.Unique,
1638 pResultCB->DirEnum.FileId.Cell,
1639 pResultCB->DirEnum.FileId.Volume,
1640 pResultCB->DirEnum.FileId.Vnode,
1641 pResultCB->DirEnum.FileId.Unique);
1643 if( pDirNode->OpenReferenceCount == 0)
1646 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1647 AFS_TRACE_LEVEL_VERBOSE,
1648 "AFSNotifyFileCreate Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1650 &pDirNode->NameInformation.FileName,
1651 pDirNode->ObjectInformation->FileId.Cell,
1652 pDirNode->ObjectInformation->FileId.Volume,
1653 pDirNode->ObjectInformation->FileId.Vnode,
1654 pDirNode->ObjectInformation->FileId.Unique,
1655 pResultCB->DirEnum.FileId.Cell,
1656 pResultCB->DirEnum.FileId.Volume,
1657 pResultCB->DirEnum.FileId.Vnode,
1658 pResultCB->DirEnum.FileId.Unique);
1660 AFSDeleteDirEntry( ParentObjectInfo,
1666 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1668 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1669 AFS_TRACE_LEVEL_VERBOSE,
1670 "AFSNotifyFileCreate Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1672 &pDirNode->NameInformation.FileName,
1673 pDirNode->ObjectInformation->FileId.Cell,
1674 pDirNode->ObjectInformation->FileId.Volume,
1675 pDirNode->ObjectInformation->FileId.Vnode,
1676 pDirNode->ObjectInformation->FileId.Unique,
1677 pResultCB->DirEnum.FileId.Cell,
1678 pResultCB->DirEnum.FileId.Volume,
1679 pResultCB->DirEnum.FileId.Vnode,
1680 pResultCB->DirEnum.FileId.Unique);
1682 AFSRemoveNameEntry( ParentObjectInfo,
1691 // We are unsure of our current data so set the verify flag. It may already be set
1692 // but no big deal to reset it
1695 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1697 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1700 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1701 AFS_TRACE_LEVEL_VERBOSE,
1702 "AFSNotifyFileCreate Creating new entry %wZ\n",
1706 // Initialize the directory entry
1709 uniTargetName.Length = (USHORT)pResultCB->DirEnum.TargetNameLength;
1711 uniTargetName.MaximumLength = uniTargetName.Length;
1713 uniTargetName.Buffer = (WCHAR *)((char *)&pResultCB->DirEnum + pResultCB->DirEnum.TargetNameOffset);
1715 pDirNode = AFSInitDirEntry( ParentObjectInfo,
1718 &pResultCB->DirEnum,
1719 (ULONG)InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1721 if( pDirNode == NULL)
1724 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1726 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1728 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1730 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1734 // Init the short name if we have one
1737 if( pResultCB->DirEnum.ShortNameLength > 0)
1740 UNICODE_STRING uniShortName;
1742 pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
1744 RtlCopyMemory( pDirNode->NameInformation.ShortName,
1745 pResultCB->DirEnum.ShortName,
1746 pDirNode->NameInformation.ShortNameLength);
1749 // Generate the short name index
1752 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1753 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1755 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1758 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1759 AFS_TRACE_LEVEL_VERBOSE,
1760 "AFSNotifyFileCreate Initialized short name %wZ for DE %p for %wZ\n",
1763 &pDirNode->NameInformation.FileName);
1766 if ( !BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1770 // Update the parent data version
1773 ParentObjectInfo->DataVersion = pResultCB->ParentDataVersion;
1775 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1776 AFS_TRACE_LEVEL_VERBOSE,
1777 "AFSNotifyFileCreate entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
1779 ParentObjectInfo->FileId.Cell,
1780 ParentObjectInfo->FileId.Volume,
1781 ParentObjectInfo->FileId.Vnode,
1782 ParentObjectInfo->FileId.Unique,
1783 ParentObjectInfo->DataVersion.QuadPart);
1786 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1789 // Return the directory node
1792 *DirNode = pDirNode;
1796 if( pResultCB != NULL)
1799 AFSExFreePool( pResultCB);
1807 AFSUpdateFileInformation( IN AFSFileID *ParentFid,
1808 IN AFSObjectInfoCB *ObjectInfo,
1812 NTSTATUS ntStatus = STATUS_SUCCESS;
1813 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1814 AFSFileUpdateCB stUpdateCB;
1815 ULONG ulResultLen = 0;
1816 AFSFileUpdateResultCB *pUpdateResultCB = NULL;
1822 // Init the control block for the request
1825 RtlZeroMemory( &stUpdateCB,
1826 sizeof( AFSFileUpdateCB));
1828 stUpdateCB.AllocationSize = ObjectInfo->EndOfFile;
1830 stUpdateCB.FileAttributes = ObjectInfo->FileAttributes;
1832 stUpdateCB.EaSize = ObjectInfo->EaSize;
1834 stUpdateCB.ParentId = *ParentFid;
1836 stUpdateCB.LastAccessTime = ObjectInfo->LastAccessTime;
1838 stUpdateCB.CreateTime = ObjectInfo->CreationTime;
1840 stUpdateCB.ChangeTime = ObjectInfo->ChangeTime;
1842 stUpdateCB.LastWriteTime = ObjectInfo->LastWriteTime;
1844 pUpdateResultCB = (AFSFileUpdateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1846 AFS_UPDATE_RESULT_TAG);
1848 if( pUpdateResultCB == NULL)
1851 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1854 ulResultLen = PAGE_SIZE;
1856 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_UPDATE_FILE,
1857 AFS_REQUEST_FLAG_SYNCHRONOUS,
1860 &ObjectInfo->FileId,
1862 sizeof( AFSFileUpdateCB),
1866 if( ntStatus != STATUS_SUCCESS)
1869 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1870 AFS_TRACE_LEVEL_ERROR,
1871 "AFSUpdateFileInformation failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1872 ObjectInfo->FileId.Cell,
1873 ObjectInfo->FileId.Volume,
1874 ObjectInfo->FileId.Vnode,
1875 ObjectInfo->FileId.Unique,
1878 try_return( ntStatus);
1882 // Update the data version
1885 AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1888 if ( !BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1891 ObjectInfo->DataVersion = pUpdateResultCB->DirEnum.DataVersion;
1894 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1898 if( pUpdateResultCB != NULL)
1901 AFSExFreePool( pUpdateResultCB);
1909 AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
1911 IN BOOLEAN CheckOnly)
1913 NTSTATUS ntStatus = STATUS_SUCCESS;
1914 ULONG ulResultLen = 0;
1915 AFSFileDeleteCB stDelete;
1916 AFSFileDeleteResultCB stDeleteResult;
1917 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1922 stDelete.ParentId = DirectoryCB->ObjectInformation->ParentObjectInformation->FileId;
1924 stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
1926 ulResultLen = sizeof( AFSFileDeleteResultCB);
1930 ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
1933 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
1936 &DirectoryCB->NameInformation.FileName,
1937 &DirectoryCB->ObjectInformation->FileId,
1939 sizeof( AFSFileDeleteCB),
1943 if( ntStatus != STATUS_SUCCESS)
1946 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1947 AFS_TRACE_LEVEL_ERROR,
1948 "AFSNotifyDelete failed ParentFID %08lX-%08lX-%08lX-%08lX %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1949 stDelete.ParentId.Cell,
1950 stDelete.ParentId.Volume,
1951 stDelete.ParentId.Vnode,
1952 stDelete.ParentId.Unique,
1953 &DirectoryCB->NameInformation.FileName,
1954 DirectoryCB->ObjectInformation->FileId.Cell,
1955 DirectoryCB->ObjectInformation->FileId.Volume,
1956 DirectoryCB->ObjectInformation->FileId.Vnode,
1957 DirectoryCB->ObjectInformation->FileId.Unique,
1960 try_return( ntStatus);
1963 AFSAcquireExcl( DirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1970 // Validate the parent data version
1973 if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
1976 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1978 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1985 // Update the parent data version
1988 if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart - 1)
1991 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1993 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1999 // TODO -- The entry must be removed from the directory at which point the
2000 // Directory data version number can be updated. Until then we must force
2003 // DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = stDeleteResult.ParentDataVersion.QuadPart;
2006 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
2008 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
2012 AFSReleaseResource( DirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2023 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
2025 IN AFSObjectInfoCB *ParentObjectInfo,
2026 IN AFSObjectInfoCB *TargetParentObjectInfo,
2027 IN AFSDirectoryCB *DirectoryCB,
2028 IN UNICODE_STRING *TargetName,
2029 OUT AFSFileID *UpdatedFID)
2032 NTSTATUS ntStatus = STATUS_SUCCESS;
2033 AFSFileRenameCB *pRenameCB = NULL;
2034 AFSFileRenameResultCB *pRenameResultCB = NULL;
2035 ULONG ulResultLen = 0;
2041 // Init the control block for the request
2044 pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
2046 AFS_RENAME_REQUEST_TAG);
2048 if( pRenameCB == NULL)
2051 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2054 RtlZeroMemory( pRenameCB,
2057 pRenameCB->SourceParentId = ParentObjectInfo->FileId;
2059 pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
2061 pRenameCB->TargetNameLength = TargetName->Length;
2063 RtlCopyMemory( pRenameCB->TargetName,
2065 TargetName->Length);
2068 // Use the same buffer for the result control block
2071 pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
2073 ulResultLen = PAGE_SIZE;
2075 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
2076 AFS_REQUEST_FLAG_SYNCHRONOUS,
2078 &DirectoryCB->NameInformation.FileName,
2079 &ObjectInfo->FileId,
2081 sizeof( AFSFileRenameCB) + TargetName->Length,
2085 if( ntStatus != STATUS_SUCCESS)
2088 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2089 AFS_TRACE_LEVEL_ERROR,
2090 "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2091 ObjectInfo->FileId.Cell,
2092 ObjectInfo->FileId.Volume,
2093 ObjectInfo->FileId.Vnode,
2094 ObjectInfo->FileId.Unique,
2097 try_return( ntStatus);
2101 // Update the information from the returned data
2104 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2107 if ( ParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->SourceParentDataVersion.QuadPart - 1)
2110 ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
2115 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2117 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2120 if ( ParentObjectInfo != TargetParentObjectInfo)
2123 if ( TargetParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->TargetParentDataVersion.QuadPart - 1)
2126 TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
2131 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2133 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2138 // Move over the short name
2141 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2143 if( DirectoryCB->NameInformation.ShortNameLength > 0)
2146 UNICODE_STRING uniShortName;
2148 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2149 uniShortName.MaximumLength = uniShortName.Length;
2150 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2152 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2153 AFS_TRACE_LEVEL_VERBOSE,
2154 "AFSNotifyRename Update old short name %wZ for DE %p for %wZ\n",
2157 &DirectoryCB->NameInformation.FileName);
2159 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2161 RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
2162 pRenameResultCB->DirEnum.ShortName,
2163 DirectoryCB->NameInformation.ShortNameLength);
2165 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2166 uniShortName.MaximumLength = uniShortName.Length;
2167 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2169 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2170 AFS_TRACE_LEVEL_VERBOSE,
2171 "AFSNotifyRename Initialized short name %wZ for DE %p for %wZ\n",
2174 &DirectoryCB->NameInformation.FileName);
2179 UNICODE_STRING uniShortName;
2181 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2182 uniShortName.MaximumLength = uniShortName.Length;
2183 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2185 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2186 AFS_TRACE_LEVEL_VERBOSE,
2187 "AFSNotifyRename Removing old short name %wZ for DE %p for %wZ\n",
2190 &DirectoryCB->NameInformation.FileName);
2192 DirectoryCB->NameInformation.ShortNameLength = 0;
2194 DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2197 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2199 if( UpdatedFID != NULL)
2201 *UpdatedFID = pRenameResultCB->DirEnum.FileId;
2206 if( pRenameCB != NULL)
2209 AFSExFreePool( pRenameCB);
2217 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
2219 IN BOOLEAN FastCall,
2220 OUT AFSDirEnumEntry **DirEnumEntry)
2223 NTSTATUS ntStatus = STATUS_SUCCESS;
2224 AFSEvalTargetCB stTargetID;
2225 ULONG ulResultBufferLength;
2226 AFSFileEvalResultCB *pEvalResultCB = NULL;
2227 AFSDirEnumEntry *pDirEnumCB = NULL;
2228 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
2233 RtlZeroMemory( &stTargetID,
2234 sizeof( AFSEvalTargetCB));
2236 if( ObjectInfo->ParentObjectInformation != NULL)
2239 stTargetID.ParentId = ObjectInfo->ParentObjectInformation->FileId;
2243 // Allocate our response buffer
2246 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2248 AFS_GENERIC_MEMORY_30_TAG);
2250 if( pEvalResultCB == NULL)
2253 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2257 // Call to the service to evaluate the fid
2260 ulResultBufferLength = PAGE_SIZE;
2265 ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
2268 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
2272 &ObjectInfo->FileId,
2274 sizeof( AFSEvalTargetCB),
2276 &ulResultBufferLength);
2278 if( ntStatus != STATUS_SUCCESS)
2282 // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
2286 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2289 if( ObjectInfo->ParentObjectInformation != NULL)
2292 AFSAcquireExcl( ObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
2295 SetFlag( ObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
2297 ObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
2299 AFSReleaseResource( ObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2303 try_return( ntStatus);
2307 // Validate the parent data version
2310 if ( ObjectInfo->ParentObjectInformation != NULL)
2313 AFSAcquireExcl( ObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
2316 if ( ObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2319 SetFlag( ObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
2321 ObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
2324 AFSReleaseResource( ObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2328 // Pass back the dir enum entry
2331 if( DirEnumEntry != NULL)
2334 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2336 AFS_GENERIC_MEMORY_2_TAG);
2338 if( pDirEnumCB == NULL)
2341 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2344 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2345 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2347 *DirEnumEntry = pDirEnumCB;
2352 if( pEvalResultCB != NULL)
2355 AFSExFreePool( pEvalResultCB);
2358 if( !NT_SUCCESS( ntStatus))
2361 if( pDirEnumCB != NULL)
2364 AFSExFreePool( pDirEnumCB);
2367 *DirEnumEntry = NULL;
2375 AFSEvaluateTargetByName( IN GUID *AuthGroup,
2376 IN AFSObjectInfoCB *ParentObjectInfo,
2377 IN PUNICODE_STRING SourceName,
2378 OUT AFSDirEnumEntry **DirEnumEntry)
2381 NTSTATUS ntStatus = STATUS_SUCCESS;
2382 AFSEvalTargetCB stTargetID;
2383 ULONG ulResultBufferLength;
2384 AFSFileEvalResultCB *pEvalResultCB = NULL;
2385 AFSDirEnumEntry *pDirEnumCB = NULL;
2390 stTargetID.ParentId = ParentObjectInfo->FileId;
2393 // Allocate our response buffer
2396 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2398 AFS_GENERIC_MEMORY_31_TAG);
2400 if( pEvalResultCB == NULL)
2403 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2407 // Call to the service to evaluate the fid
2410 ulResultBufferLength = PAGE_SIZE;
2412 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
2413 AFS_REQUEST_FLAG_SYNCHRONOUS,
2418 sizeof( AFSEvalTargetCB),
2420 &ulResultBufferLength);
2422 if( ntStatus != STATUS_SUCCESS)
2425 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2428 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2431 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2433 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2435 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2438 try_return( ntStatus);
2442 // Validate the parent data version
2445 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2448 if ( ParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2451 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2453 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2456 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2459 // Pass back the dir enum entry
2462 if( DirEnumEntry != NULL)
2465 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2467 AFS_GENERIC_MEMORY_3_TAG);
2469 if( pDirEnumCB == NULL)
2472 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2475 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2476 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2478 *DirEnumEntry = pDirEnumCB;
2483 if( pEvalResultCB != NULL)
2486 AFSExFreePool( pEvalResultCB);
2489 if( !NT_SUCCESS( ntStatus))
2492 if( pDirEnumCB != NULL)
2495 AFSExFreePool( pDirEnumCB);
2498 *DirEnumEntry = NULL;
2506 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
2507 IN AFSFileID *FileID,
2508 OUT AFSVolumeInfoCB *VolumeInformation)
2511 NTSTATUS ntStatus = STATUS_SUCCESS;
2512 ULONG ulResultLen = 0;
2517 ulResultLen = sizeof( AFSVolumeInfoCB);
2519 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
2520 AFS_REQUEST_FLAG_SYNCHRONOUS,
2529 if( ntStatus != STATUS_SUCCESS)
2532 try_return( ntStatus);
2544 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
2545 IN ULONG InputLength,
2546 IN ULONG OutputLength,
2547 IN void *InputDataBuffer,
2548 OUT void *OutputDataBuffer,
2549 OUT ULONG *BytesReturned)
2552 NTSTATUS ntStatus = STATUS_SUCCESS;
2553 ULONG ulResultLen = 0;
2554 MDL *pInputMdl = NULL, *pOutputMdl = NULL;
2555 void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
2556 ULONG ulBufferLength = OutputLength;
2557 AFSPipeIORequestCB *pIoRequest = NULL;
2563 // Map the user buffer to a system address
2566 pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
2570 if( pInputSystemBuffer == NULL)
2573 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2576 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2577 sizeof( AFSPipeIORequestCB) +
2579 AFS_GENERIC_MEMORY_4_TAG);
2581 if( pIoRequest == NULL)
2584 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2587 RtlZeroMemory( pIoRequest,
2588 sizeof( AFSPipeIORequestCB) + InputLength);
2590 pIoRequest->RequestId = Ccb->RequestID;
2592 pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2594 pIoRequest->BufferLength = InputLength;
2596 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
2600 pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
2604 if( pOutputSystemBuffer == NULL)
2607 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2611 // Send the call to the service
2614 ulResultLen = OutputLength;
2616 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
2617 AFS_REQUEST_FLAG_SYNCHRONOUS,
2619 &Ccb->DirectoryCB->NameInformation.FileName,
2622 sizeof( AFSPipeIORequestCB) + InputLength,
2623 pOutputSystemBuffer,
2626 if( ntStatus != STATUS_SUCCESS &&
2627 ntStatus != STATUS_BUFFER_OVERFLOW)
2630 if( NT_SUCCESS( ntStatus))
2633 ntStatus = STATUS_DEVICE_NOT_READY;
2636 try_return( ntStatus);
2640 // Return the bytes processed
2643 *BytesReturned = ulResultLen;
2647 if( pInputMdl != NULL)
2650 MmUnlockPages( pInputMdl);
2652 IoFreeMdl( pInputMdl);
2655 if( pOutputMdl != NULL)
2658 MmUnlockPages( pOutputMdl);
2660 IoFreeMdl( pOutputMdl);
2663 if( pIoRequest != NULL)
2666 AFSExFreePool( pIoRequest);
2674 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
2675 IN ULONG InformationClass,
2676 IN ULONG InputLength,
2677 IN void *DataBuffer)
2680 NTSTATUS ntStatus = STATUS_SUCCESS;
2681 AFSPipeInfoRequestCB *pInfoRequest = NULL;
2686 pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2687 sizeof( AFSPipeInfoRequestCB) +
2689 AFS_GENERIC_MEMORY_5_TAG);
2691 if( pInfoRequest == NULL)
2694 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2697 RtlZeroMemory( pInfoRequest,
2698 sizeof( AFSPipeInfoRequestCB) + InputLength);
2700 pInfoRequest->RequestId = Ccb->RequestID;
2702 pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2704 pInfoRequest->BufferLength = InputLength;
2706 pInfoRequest->InformationClass = InformationClass;
2708 RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
2713 // Send the call to the service
2716 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
2717 AFS_REQUEST_FLAG_SYNCHRONOUS,
2719 &Ccb->DirectoryCB->NameInformation.FileName,
2722 sizeof( AFSPipeInfoRequestCB) + InputLength,
2726 if( ntStatus != STATUS_SUCCESS)
2729 if( NT_SUCCESS( ntStatus))
2732 ntStatus = STATUS_DEVICE_NOT_READY;
2735 try_return( ntStatus);
2740 if( pInfoRequest != NULL)
2743 AFSExFreePool( pInfoRequest);
2751 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
2752 IN ULONG InformationClass,
2753 IN ULONG OutputLength,
2754 IN void *DataBuffer,
2755 OUT ULONG *BytesReturned)
2758 NTSTATUS ntStatus = STATUS_SUCCESS;
2759 AFSPipeInfoRequestCB stInfoRequest;
2760 ULONG ulBytesProcessed = 0;
2765 RtlZeroMemory( &stInfoRequest,
2766 sizeof( AFSPipeInfoRequestCB));
2768 stInfoRequest.RequestId = Ccb->RequestID;
2770 stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2772 stInfoRequest.BufferLength = OutputLength;
2774 stInfoRequest.InformationClass = InformationClass;
2776 ulBytesProcessed = OutputLength;
2779 // Send the call to the service
2782 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
2783 AFS_REQUEST_FLAG_SYNCHRONOUS,
2785 &Ccb->DirectoryCB->NameInformation.FileName,
2788 sizeof( AFSPipeInfoRequestCB),
2792 if( ntStatus != STATUS_SUCCESS)
2795 if( NT_SUCCESS( ntStatus))
2798 ntStatus = STATUS_DEVICE_NOT_READY;
2801 try_return( ntStatus);
2804 *BytesReturned = ulBytesProcessed;
2815 AFSReleaseFid( IN AFSFileID *FileId)
2818 NTSTATUS ntStatus = STATUS_SUCCESS;
2823 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
2838 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
2839 IN LARGE_INTEGER *ExtentOffset,
2843 BOOLEAN bRequestQueued = FALSE;
2844 NTSTATUS ntStatus = STATUS_SUCCESS;
2845 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2846 AFSCommSrvcCB *pCommSrvc = NULL;
2847 AFSPoolEntry *pPoolEntry = NULL;
2848 AFSRequestExtentsCB *pRequestExtents = NULL;
2854 pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
2856 AFSAcquireShared( &pCommSrvc->IrpPoolLock,
2859 pPoolEntry = pCommSrvc->RequestPoolHead;
2861 while( pPoolEntry != NULL)
2864 if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
2867 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
2870 pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
2872 if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
2873 pRequestExtents->Length == Length)
2876 bRequestQueued = TRUE;
2881 pPoolEntry = pPoolEntry->fLink;
2884 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
2887 return bRequestQueued;