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)
307 AFSObjectInfoCB *pObjectInfo = pDirNode->ObjectInformation;
310 // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
313 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
315 AFSPerformObjectInvalidate( pObjectInfo,
316 AFS_INVALIDATE_DATA_VERSION);
321 AFSUpdateMetaData( pDirNode,
331 // Need to tear down this entry and rebuild it below
334 if( pDirNode->OpenReferenceCount == 0)
337 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
338 AFS_TRACE_LEVEL_VERBOSE,
339 "AFSEnumerateDirectory Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
341 &pDirNode->NameInformation.FileName,
342 pDirNode->ObjectInformation->FileId.Cell,
343 pDirNode->ObjectInformation->FileId.Volume,
344 pDirNode->ObjectInformation->FileId.Vnode,
345 pDirNode->ObjectInformation->FileId.Unique,
346 pCurrentDirEntry->FileId.Cell,
347 pCurrentDirEntry->FileId.Volume,
348 pCurrentDirEntry->FileId.Vnode,
349 pCurrentDirEntry->FileId.Unique);
351 AFSDeleteDirEntry( ObjectInfoCB,
357 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
359 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
360 AFS_TRACE_LEVEL_VERBOSE,
361 "AFSEnumerateDirectory Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
363 &pDirNode->NameInformation.FileName,
364 pDirNode->ObjectInformation->FileId.Cell,
365 pDirNode->ObjectInformation->FileId.Volume,
366 pDirNode->ObjectInformation->FileId.Vnode,
367 pDirNode->ObjectInformation->FileId.Unique,
368 pCurrentDirEntry->FileId.Cell,
369 pCurrentDirEntry->FileId.Volume,
370 pCurrentDirEntry->FileId.Vnode,
371 pCurrentDirEntry->FileId.Unique);
373 AFSRemoveNameEntry( ObjectInfoCB,
381 pDirNode = AFSInitDirEntry( ObjectInfoCB,
385 (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
387 if( pDirNode == NULL)
390 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
395 AFSUpdateMetaData( pDirNode,
398 if( pDirNode->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
401 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
402 AFS_TRACE_LEVEL_VERBOSE,
403 "AFSEnumerateDirectory Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
405 pDirNode->ObjectInformation->FileId.Cell,
406 pDirNode->ObjectInformation->FileId.Volume,
407 pDirNode->ObjectInformation->FileId.Vnode,
408 pDirNode->ObjectInformation->FileId.Unique);
410 AFSAcquireExcl( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
413 SetFlag( pDirNode->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
415 pDirNode->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
417 AFSReleaseResource( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
421 // Set up the entry length
424 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
425 pCurrentDirEntry->FileNameLength +
426 pCurrentDirEntry->TargetNameLength);
429 // Init the short name if we have one
432 if( pCurrentDirEntry->ShortNameLength > 0)
435 UNICODE_STRING uniShortName;
437 pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
439 RtlCopyMemory( pDirNode->NameInformation.ShortName,
440 pCurrentDirEntry->ShortName,
441 pDirNode->NameInformation.ShortNameLength);
444 // Generate the short name index
447 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
448 uniShortName.MaximumLength = uniShortName.Length;
449 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
451 if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
456 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
459 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
460 AFS_TRACE_LEVEL_VERBOSE,
461 "AFSEnumerateDirectory Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
464 &pDirNode->NameInformation.FileName,
465 pCurrentDirEntry->FileId.Cell,
466 pCurrentDirEntry->FileId.Volume,
467 pCurrentDirEntry->FileId.Vnode,
468 pCurrentDirEntry->FileId.Unique);
472 pDirNode->NameInformation.ShortNameLength = 0;
474 RtlZeroMemory( pDirNode->NameInformation.ShortName,
475 (12 * sizeof( WCHAR)));
480 // Insert the node into the name tree
483 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
486 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
488 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
489 AFS_TRACE_LEVEL_VERBOSE,
490 "AFSEnumerateDirectory Insert DE %p to head of case sensitive tree for %wZ\n",
492 &pDirNode->NameInformation.FileName);
497 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
498 AFS_TRACE_LEVEL_VERBOSE,
499 "AFSEnumerateDirectory Insert DE %p to case sensitive tree for %wZ\n",
501 &pDirNode->NameInformation.FileName);
503 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
508 // Delete this dir entry and continue on
511 AFSDeleteDirEntry( ObjectInfoCB,
514 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
516 if( ulResultLen >= ulEntryLength)
518 ulResultLen -= ulEntryLength;
529 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
531 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
534 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
535 AFS_TRACE_LEVEL_VERBOSE,
536 "AFSEnumerateDirectory Insert DE %p to head of case insensitive tree for %wZ\n",
538 &pDirNode->NameInformation.FileName);
540 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
542 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
547 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
548 AFS_TRACE_LEVEL_VERBOSE,
549 "AFSEnumerateDirectory Insert DE %p to case insensitive tree for %wZ\n",
551 &pDirNode->NameInformation.FileName);
553 AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
557 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
560 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
565 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
567 pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
570 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
572 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
574 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
576 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
577 AFS_TRACE_LEVEL_VERBOSE,
578 "AFSEnumerateDirectory Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
579 &pDirNode->NameInformation.FileName,
580 ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
581 ObjectInfoCB->FileId.Cell,
582 ObjectInfoCB->FileId.Volume,
583 ObjectInfoCB->FileId.Vnode,
584 ObjectInfoCB->FileId.Unique);
586 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
590 // Insert the short name entry if we have a valid short name
593 if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
596 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
597 AFS_TRACE_LEVEL_VERBOSE,
598 "AFSEnumerateDirectory Insert DE %p to head of shortname tree for %wZ\n",
600 &pDirNode->NameInformation.FileName);
602 ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
604 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
609 if( NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
612 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
614 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
615 AFS_TRACE_LEVEL_VERBOSE,
616 "AFSEnumerateDirectory Insert DE %p to shortname tree for %wZ\n",
618 &pDirNode->NameInformation.FileName);
627 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
629 if( ulResultLen >= ulEntryLength)
631 ulResultLen -= ulEntryLength;
639 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
642 // Reset the information in the request buffer since it got trampled
646 pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
648 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
649 AFS_TRACE_LEVEL_VERBOSE,
650 "AFSEnumerateDirectory EnumHandle %08lX\n",
651 pDirQueryCB->EnumHandle);
663 AFSExFreePool( pBuffer);
667 // If the processing failed then we should reset the directory content in the event
668 // it is re-enumerated
671 if( !NT_SUCCESS( ntStatus))
674 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
675 AFS_TRACE_LEVEL_ERROR,
676 "AFSEnumerateDirectory Resetting content for FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
677 ObjectInfoCB->FileId.Cell,
678 ObjectInfoCB->FileId.Volume,
679 ObjectInfoCB->FileId.Vnode,
680 ObjectInfoCB->FileId.Unique,
683 AFSResetDirectoryContent( ObjectInfoCB);
691 AFSEnumerateDirectoryNoResponse( IN GUID *AuthGroup,
692 IN AFSFileID *FileId)
695 NTSTATUS ntStatus = STATUS_SUCCESS;
696 AFSDirQueryCB stDirQueryCB;
697 ULONG ulRequestFlags = 0;
703 // Use the payload buffer for information we will pass to the service
706 stDirQueryCB.EnumHandle = 0;
708 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
713 (void *)&stDirQueryCB,
714 sizeof( AFSDirQueryCB),
718 if( ntStatus != STATUS_SUCCESS)
721 if( ntStatus == STATUS_NO_MORE_FILES ||
722 ntStatus == STATUS_NO_MORE_ENTRIES)
725 ntStatus = STATUS_SUCCESS;
730 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
731 AFS_TRACE_LEVEL_ERROR,
732 "AFSEnumerateDirectoryNoResponse Failed to enumerate directory Status %08lX\n",
742 AFSVerifyDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB,
746 NTSTATUS ntStatus = STATUS_SUCCESS;
747 void *pBuffer = NULL;
748 ULONG ulResultLen = 0;
749 AFSDirQueryCB *pDirQueryCB;
750 AFSDirEnumEntry *pCurrentDirEntry = NULL;
751 AFSDirectoryCB *pDirNode = NULL;
752 ULONG ulEntryLength = 0;
753 AFSDirEnumResp *pDirEnumResponse = NULL;
754 UNICODE_STRING uniDirName, uniTargetName;
755 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_FAST_REQUEST;
757 AFSObjectInfoCB *pObjectInfo = NULL;
758 ULONGLONG ullIndex = 0;
759 UNICODE_STRING uniGUID;
765 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
768 uniGUID.MaximumLength = 0;
769 uniGUID.Buffer = NULL;
771 if( AuthGroup != NULL)
773 RtlStringFromGUID( *AuthGroup,
777 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
778 AFS_TRACE_LEVEL_VERBOSE,
779 "AFSVerifyDirectoryContent Verifying content for FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
780 ObjectInfoCB->FileId.Cell,
781 ObjectInfoCB->FileId.Volume,
782 ObjectInfoCB->FileId.Vnode,
783 ObjectInfoCB->FileId.Unique,
786 if( AuthGroup != NULL)
788 RtlFreeUnicodeString( &uniGUID);
792 // Initialize the directory enumeration buffer for the directory
795 pBuffer = AFSExAllocatePoolWithTag( PagedPool,
796 AFS_DIR_ENUM_BUFFER_LEN,
802 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
805 RtlZeroMemory( pBuffer,
806 AFS_DIR_ENUM_BUFFER_LEN);
808 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
811 // Use the payload buffer for information we will pass to the service
814 pDirQueryCB = (AFSDirQueryCB *)pBuffer;
816 pDirQueryCB->EnumHandle = 0;
819 // Loop on the information
826 // If the enumeration handle is -1 then we are done
829 if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
832 ntStatus = STATUS_NO_MORE_ENTRIES;
838 // Go and retrieve the directory contents
841 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
845 &ObjectInfoCB->FileId,
847 sizeof( AFSDirQueryCB),
852 if( ntStatus != STATUS_SUCCESS ||
856 if( ntStatus == STATUS_NO_MORE_FILES ||
857 ntStatus == STATUS_NO_MORE_ENTRIES)
860 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
862 AFSAcquireExcl( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock,
865 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
866 AFS_TRACE_LEVEL_VERBOSE,
867 "AFSVerifyDirectoryContent Directory Complete FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX Status %08lX\n",
868 ObjectInfoCB->FileId.Cell,
869 ObjectInfoCB->FileId.Volume,
870 ObjectInfoCB->FileId.Vnode,
871 ObjectInfoCB->FileId.Unique,
872 pDirEnumResponse->SnapshotDataVersion.HighPart,
873 pDirEnumResponse->SnapshotDataVersion.LowPart,
874 pDirEnumResponse->CurrentDataVersion.HighPart,
875 pDirEnumResponse->CurrentDataVersion.LowPart,
878 ntStatus = STATUS_SUCCESS;
880 if ( pDirEnumResponse->SnapshotDataVersion.QuadPart != pDirEnumResponse->CurrentDataVersion.QuadPart )
883 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
885 ObjectInfoCB->DataVersion.QuadPart = (ULONGLONG)-1;
887 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
888 AFS_TRACE_LEVEL_VERBOSE,
889 "AFSVerifyDirectoryContent Force Verify due to DV change during enumeration FID %08lX-%08lX-%08lX-%08lX\n",
890 ObjectInfoCB->FileId.Cell,
891 ObjectInfoCB->FileId.Volume,
892 ObjectInfoCB->FileId.Vnode,
893 ObjectInfoCB->FileId.Unique);
898 ObjectInfoCB->DataVersion = pDirEnumResponse->SnapshotDataVersion;
901 AFSReleaseResource( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock);
906 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
907 AFS_TRACE_LEVEL_ERROR,
908 "AFSVerifyDirectoryContent Failed to enumerate directory FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ Status %08lX\n",
909 ObjectInfoCB->FileId.Cell,
910 ObjectInfoCB->FileId.Volume,
911 ObjectInfoCB->FileId.Vnode,
912 ObjectInfoCB->FileId.Unique,
920 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
922 pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
924 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
925 AFS_TRACE_LEVEL_VERBOSE,
926 "AFSVerifyDirectoryContent EnumResponse FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX\n",
927 ObjectInfoCB->FileId.Cell,
928 ObjectInfoCB->FileId.Volume,
929 ObjectInfoCB->FileId.Vnode,
930 ObjectInfoCB->FileId.Unique,
931 pDirEnumResponse->SnapshotDataVersion.HighPart,
932 pDirEnumResponse->SnapshotDataVersion.LowPart,
933 pDirEnumResponse->CurrentDataVersion.HighPart,
934 pDirEnumResponse->CurrentDataVersion.LowPart);
937 // Remove the leading header from the processed length
940 ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
942 while( ulResultLen > 0)
945 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
947 uniDirName.MaximumLength = uniDirName.Length;
949 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
951 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
953 uniTargetName.MaximumLength = uniTargetName.Length;
955 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
958 // Does this entry already exist in the directory?
961 ulCRC = AFSGenerateCRC( &uniDirName,
964 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
970 // Set up the entry length
973 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
974 pCurrentDirEntry->FileNameLength +
975 pCurrentDirEntry->TargetNameLength);
978 AFSIsEqualFID( &pCurrentDirEntry->FileId,
979 &pDirNode->ObjectInformation->FileId))
983 // Found matching directory entry by name and FileID
986 AFSAcquireShared( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock,
989 ullIndex = AFSCreateLowIndex( &pCurrentDirEntry->FileId);
991 ntStatus = AFSLocateHashEntry( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeHead,
993 (AFSBTreeEntry **)&pObjectInfo);
995 AFSReleaseResource( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock);
997 if( NT_SUCCESS( ntStatus) &&
1002 // Indicate this is a valid entry
1005 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
1007 if( pCurrentDirEntry->ShortNameLength > 0 &&
1008 pDirNode->NameInformation.ShortNameLength > 0)
1010 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1011 AFS_TRACE_LEVEL_VERBOSE,
1012 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name %S New short name %S\n",
1014 &pDirNode->NameInformation.FileName,
1015 ObjectInfoCB->FileId.Cell,
1016 ObjectInfoCB->FileId.Volume,
1017 ObjectInfoCB->FileId.Vnode,
1018 ObjectInfoCB->FileId.Unique,
1019 pDirNode->NameInformation.ShortName,
1020 pCurrentDirEntry->ShortName);
1022 else if( pCurrentDirEntry->ShortNameLength == 0 &&
1023 pDirNode->NameInformation.ShortNameLength > 0)
1026 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1027 AFS_TRACE_LEVEL_VERBOSE,
1028 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name %S New short name NULL\n",
1030 &pDirNode->NameInformation.FileName,
1031 ObjectInfoCB->FileId.Cell,
1032 ObjectInfoCB->FileId.Volume,
1033 ObjectInfoCB->FileId.Vnode,
1034 ObjectInfoCB->FileId.Unique,
1035 pDirNode->NameInformation.ShortName);
1037 else if( pCurrentDirEntry->ShortNameLength > 0 &&
1038 pDirNode->NameInformation.ShortNameLength == 0)
1040 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1041 AFS_TRACE_LEVEL_VERBOSE,
1042 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name %S\n",
1044 &pDirNode->NameInformation.FileName,
1045 ObjectInfoCB->FileId.Cell,
1046 ObjectInfoCB->FileId.Volume,
1047 ObjectInfoCB->FileId.Vnode,
1048 ObjectInfoCB->FileId.Unique,
1049 pCurrentDirEntry->ShortName);
1053 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1054 AFS_TRACE_LEVEL_VERBOSE,
1055 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name NULL\n",
1057 &pDirNode->NameInformation.FileName,
1058 ObjectInfoCB->FileId.Cell,
1059 ObjectInfoCB->FileId.Volume,
1060 ObjectInfoCB->FileId.Vnode,
1061 ObjectInfoCB->FileId.Unique);
1065 // Update the metadata for the entry
1068 if( pObjectInfo->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
1072 // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
1075 lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1077 AFSPerformObjectInvalidate( pObjectInfo,
1078 AFS_INVALIDATE_DATA_VERSION);
1083 AFSUpdateMetaData( pDirNode,
1091 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1093 if( ulResultLen >= ulEntryLength)
1095 ulResultLen -= ulEntryLength;
1109 // File name matches but FileID does not.
1112 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1113 AFS_TRACE_LEVEL_VERBOSE,
1114 "AFSVerifyDirectoryContent Processing dir entry %p %wZ with different FID, same name in parent FID %08lX-%08lX-%08lX-%08lX\n",
1116 &pDirNode->NameInformation.FileName,
1117 ObjectInfoCB->FileId.Cell,
1118 ObjectInfoCB->FileId.Volume,
1119 ObjectInfoCB->FileId.Vnode,
1120 ObjectInfoCB->FileId.Unique);
1123 // Need to tear down this entry and rebuild it below
1126 if( pDirNode->OpenReferenceCount == 0)
1129 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1130 AFS_TRACE_LEVEL_VERBOSE,
1131 "AFSVerifyDirectoryContent Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1133 &pDirNode->NameInformation.FileName,
1134 pDirNode->ObjectInformation->FileId.Cell,
1135 pDirNode->ObjectInformation->FileId.Volume,
1136 pDirNode->ObjectInformation->FileId.Vnode,
1137 pDirNode->ObjectInformation->FileId.Unique,
1138 pCurrentDirEntry->FileId.Cell,
1139 pCurrentDirEntry->FileId.Volume,
1140 pCurrentDirEntry->FileId.Vnode,
1141 pCurrentDirEntry->FileId.Unique);
1143 AFSDeleteDirEntry( ObjectInfoCB,
1149 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1151 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1152 AFS_TRACE_LEVEL_WARNING,
1153 "AFSVerifyDirectoryContent Different FIDs - removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1155 &pDirNode->NameInformation.FileName,
1156 pDirNode->ObjectInformation->FileId.Cell,
1157 pDirNode->ObjectInformation->FileId.Volume,
1158 pDirNode->ObjectInformation->FileId.Vnode,
1159 pDirNode->ObjectInformation->FileId.Unique,
1160 pCurrentDirEntry->FileId.Cell,
1161 pCurrentDirEntry->FileId.Volume,
1162 pCurrentDirEntry->FileId.Vnode,
1163 pCurrentDirEntry->FileId.Unique);
1165 AFSRemoveNameEntry( ObjectInfoCB,
1172 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1173 AFS_TRACE_LEVEL_VERBOSE,
1174 "AFSVerifyDirectoryContent New entry %wZ for parent FID %08lX-%08lX-%08lX-%08lX\n",
1176 ObjectInfoCB->FileId.Cell,
1177 ObjectInfoCB->FileId.Volume,
1178 ObjectInfoCB->FileId.Vnode,
1179 ObjectInfoCB->FileId.Unique);
1182 pDirNode = AFSInitDirEntry( ObjectInfoCB,
1186 (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1188 if( pDirNode == NULL)
1191 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
1196 AFSUpdateMetaData( pDirNode,
1199 if( pDirNode->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1202 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1203 AFS_TRACE_LEVEL_VERBOSE,
1204 "AFSVerifyDirectoryContent Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
1206 pDirNode->ObjectInformation->FileId.Cell,
1207 pDirNode->ObjectInformation->FileId.Volume,
1208 pDirNode->ObjectInformation->FileId.Vnode,
1209 pDirNode->ObjectInformation->FileId.Unique);
1211 AFSAcquireExcl( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1214 SetFlag( pDirNode->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1216 pDirNode->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1218 AFSReleaseResource( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1222 // Init the short name if we have one
1225 if( pCurrentDirEntry->ShortNameLength > 0)
1228 UNICODE_STRING uniShortName;
1230 pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
1232 RtlCopyMemory( pDirNode->NameInformation.ShortName,
1233 pCurrentDirEntry->ShortName,
1234 pDirNode->NameInformation.ShortNameLength);
1237 // Generate the short name index
1240 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1241 uniShortName.MaximumLength = uniShortName.Length;
1242 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1244 if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
1249 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1252 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1253 AFS_TRACE_LEVEL_VERBOSE,
1254 "AFSVerifyDirectoryContent Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1257 &pDirNode->NameInformation.FileName,
1258 pCurrentDirEntry->FileId.Cell,
1259 pCurrentDirEntry->FileId.Volume,
1260 pCurrentDirEntry->FileId.Vnode,
1261 pCurrentDirEntry->FileId.Unique);
1265 pDirNode->NameInformation.ShortNameLength = 0;
1267 RtlZeroMemory( pDirNode->NameInformation.ShortName,
1268 (12 * sizeof( WCHAR)));
1274 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1275 AFS_TRACE_LEVEL_VERBOSE,
1276 "AFSVerifyDirectoryContent NO short name for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1278 &pDirNode->NameInformation.FileName,
1279 pCurrentDirEntry->FileId.Cell,
1280 pCurrentDirEntry->FileId.Volume,
1281 pCurrentDirEntry->FileId.Vnode,
1282 pCurrentDirEntry->FileId.Unique);
1286 // Insert the node into the name tree
1289 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
1291 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
1294 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
1296 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1297 AFS_TRACE_LEVEL_VERBOSE,
1298 "AFSVerifyDirectoryContent Insert DE %p to head of case sensitive tree for %wZ\n",
1300 &pDirNode->NameInformation.FileName);
1305 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1308 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1309 AFS_TRACE_LEVEL_VERBOSE,
1310 "AFSVerifyDirectoryContent Failed to insert DE %p to case sensitive tree for %wZ\n",
1312 &pDirNode->NameInformation.FileName);
1315 // Delete this dir entry and continue on
1318 AFSDeleteDirEntry( ObjectInfoCB,
1321 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1323 if( ulResultLen >= ulEntryLength)
1325 ulResultLen -= ulEntryLength;
1336 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1337 AFS_TRACE_LEVEL_VERBOSE,
1338 "AFSVerifyDirectoryContent Insert DE %p to case sensitive tree for %wZ\n",
1340 &pDirNode->NameInformation.FileName);
1344 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1346 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
1349 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
1351 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
1353 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1354 AFS_TRACE_LEVEL_VERBOSE,
1355 "AFSVerifyDirectoryContent Insert DE %p to head of case insensitive tree for %wZ\n",
1357 &pDirNode->NameInformation.FileName);
1362 AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1365 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1366 AFS_TRACE_LEVEL_VERBOSE,
1367 "AFSVerifyDirectoryContent Insert DE %p to case insensitive tree for %wZ\n",
1369 &pDirNode->NameInformation.FileName);
1372 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
1375 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
1380 (ObjectInfoCB->Specific.Directory.DirectoryNodeListTail)->ListEntry.fLink = pDirNode;
1382 pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
1385 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
1387 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
1389 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
1391 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1392 AFS_TRACE_LEVEL_VERBOSE,
1393 "AFSVerifyDirectoryContent Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
1394 &pDirNode->NameInformation.FileName,
1395 ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
1396 ObjectInfoCB->FileId.Cell,
1397 ObjectInfoCB->FileId.Volume,
1398 ObjectInfoCB->FileId.Vnode,
1399 ObjectInfoCB->FileId.Unique);
1401 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
1405 // Insert the short name entry if we have a valid short name
1408 if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
1411 ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
1413 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1414 AFS_TRACE_LEVEL_VERBOSE,
1415 "AFSVerifyDirectoryContent Insert DE %p to head of shortname tree for %wZ\n",
1417 &pDirNode->NameInformation.FileName);
1419 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1424 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
1427 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1428 AFS_TRACE_LEVEL_VERBOSE,
1429 "AFSVerifyDirectoryContent Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
1431 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex,
1432 &pDirNode->NameInformation.FileName);
1436 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1438 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1439 AFS_TRACE_LEVEL_VERBOSE,
1440 "AFSVerifyDirectoryContent Insert DE %p to shortname tree for %wZ\n",
1442 &pDirNode->NameInformation.FileName);
1447 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
1453 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1455 if( ulResultLen >= ulEntryLength)
1457 ulResultLen -= ulEntryLength;
1465 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
1468 // Reset the information in the request buffer since it got trampled
1472 pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
1481 if( pBuffer != NULL)
1484 AFSExFreePool( pBuffer);
1492 AFSNotifyFileCreate( IN GUID *AuthGroup,
1493 IN AFSObjectInfoCB *ParentObjectInfo,
1494 IN PLARGE_INTEGER FileSize,
1495 IN ULONG FileAttributes,
1496 IN UNICODE_STRING *FileName,
1497 OUT AFSDirectoryCB **DirNode)
1500 NTSTATUS ntStatus = STATUS_SUCCESS;
1501 AFSFileCreateCB stCreateCB;
1502 AFSFileCreateResultCB *pResultCB = NULL;
1503 ULONG ulResultLen = 0;
1504 UNICODE_STRING uniTargetName;
1505 AFSDirectoryCB *pDirNode = NULL;
1507 LARGE_INTEGER liOldDataVersion;
1513 // Init the control block for the request
1516 RtlZeroMemory( &stCreateCB,
1517 sizeof( AFSFileCreateCB));
1519 stCreateCB.ParentId = ParentObjectInfo->FileId;
1521 stCreateCB.AllocationSize = *FileSize;
1523 stCreateCB.FileAttributes = FileAttributes;
1525 stCreateCB.EaSize = 0;
1527 liOldDataVersion = ParentObjectInfo->DataVersion;
1530 // Allocate our return buffer
1533 pResultCB = (AFSFileCreateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1535 AFS_GENERIC_MEMORY_1_TAG);
1537 if( pResultCB == NULL)
1540 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1543 RtlZeroMemory( pResultCB,
1546 ulResultLen = PAGE_SIZE;
1549 // Send the call to the service
1552 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_FILE,
1553 AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_HOLD_FID,
1558 sizeof( AFSFileCreateCB),
1562 if( ntStatus != STATUS_SUCCESS)
1565 if( NT_SUCCESS( ntStatus))
1568 ntStatus = STATUS_DEVICE_NOT_READY;
1571 try_return( ntStatus);
1575 // We may have raced with an invalidation call and a subsequent re-enumeration of this parent
1576 // and though we created the node, it is already in our list. If this is the case then
1577 // look up the entry rather than create a new entry
1578 // The check is to ensure the DV has been modified
1581 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1584 if( ParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
1587 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1588 AFS_TRACE_LEVEL_WARNING,
1589 "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",
1591 ParentObjectInfo->FileId.Cell,
1592 ParentObjectInfo->FileId.Volume,
1593 ParentObjectInfo->FileId.Vnode,
1594 ParentObjectInfo->FileId.Unique,
1595 ParentObjectInfo->DataVersion.QuadPart,
1596 pResultCB->ParentDataVersion.QuadPart);
1599 // We raced so go and lookup the directory entry in the parent
1602 ulCRC = AFSGenerateCRC( FileName,
1605 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1609 if( pDirNode != NULL)
1612 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1613 AFS_TRACE_LEVEL_VERBOSE,
1614 "AFSNotifyFileCreate Located dir entry %p for file %wZ\n",
1618 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
1619 &pResultCB->DirEnum.FileId))
1622 InterlockedIncrement( &pDirNode->OpenReferenceCount);
1624 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1625 AFS_TRACE_LEVEL_VERBOSE,
1626 "AFSNotifyFileCreate Increment count on %wZ DE %p Cnt %d\n",
1627 &pDirNode->NameInformation.FileName,
1629 pDirNode->OpenReferenceCount);
1631 *DirNode = pDirNode;
1633 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1635 try_return( ntStatus = STATUS_REPARSE);
1641 // We found an entry that matches the desired name but it is not the
1642 // same as the one that was created for us by the file server.
1645 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1646 AFS_TRACE_LEVEL_ERROR,
1647 "AFSNotifyFileCreate Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
1650 pDirNode->ObjectInformation->FileId.Cell,
1651 pDirNode->ObjectInformation->FileId.Volume,
1652 pDirNode->ObjectInformation->FileId.Vnode,
1653 pDirNode->ObjectInformation->FileId.Unique,
1654 pResultCB->DirEnum.FileId.Cell,
1655 pResultCB->DirEnum.FileId.Volume,
1656 pResultCB->DirEnum.FileId.Vnode,
1657 pResultCB->DirEnum.FileId.Unique);
1659 if( pDirNode->OpenReferenceCount == 0)
1662 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1663 AFS_TRACE_LEVEL_VERBOSE,
1664 "AFSNotifyFileCreate Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1666 &pDirNode->NameInformation.FileName,
1667 pDirNode->ObjectInformation->FileId.Cell,
1668 pDirNode->ObjectInformation->FileId.Volume,
1669 pDirNode->ObjectInformation->FileId.Vnode,
1670 pDirNode->ObjectInformation->FileId.Unique,
1671 pResultCB->DirEnum.FileId.Cell,
1672 pResultCB->DirEnum.FileId.Volume,
1673 pResultCB->DirEnum.FileId.Vnode,
1674 pResultCB->DirEnum.FileId.Unique);
1676 AFSDeleteDirEntry( ParentObjectInfo,
1682 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1684 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1685 AFS_TRACE_LEVEL_VERBOSE,
1686 "AFSNotifyFileCreate Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1688 &pDirNode->NameInformation.FileName,
1689 pDirNode->ObjectInformation->FileId.Cell,
1690 pDirNode->ObjectInformation->FileId.Volume,
1691 pDirNode->ObjectInformation->FileId.Vnode,
1692 pDirNode->ObjectInformation->FileId.Unique,
1693 pResultCB->DirEnum.FileId.Cell,
1694 pResultCB->DirEnum.FileId.Volume,
1695 pResultCB->DirEnum.FileId.Vnode,
1696 pResultCB->DirEnum.FileId.Unique);
1698 AFSRemoveNameEntry( ParentObjectInfo,
1707 // We are unsure of our current data so set the verify flag. It may already be set
1708 // but no big deal to reset it
1711 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1713 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1716 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1717 AFS_TRACE_LEVEL_VERBOSE,
1718 "AFSNotifyFileCreate Creating new entry %wZ\n",
1722 // Initialize the directory entry
1725 uniTargetName.Length = (USHORT)pResultCB->DirEnum.TargetNameLength;
1727 uniTargetName.MaximumLength = uniTargetName.Length;
1729 uniTargetName.Buffer = (WCHAR *)((char *)&pResultCB->DirEnum + pResultCB->DirEnum.TargetNameOffset);
1731 pDirNode = AFSInitDirEntry( ParentObjectInfo,
1734 &pResultCB->DirEnum,
1735 (ULONG)InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1737 if( pDirNode == NULL)
1740 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1742 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1744 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1746 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1750 // Init the short name if we have one
1753 if( pResultCB->DirEnum.ShortNameLength > 0)
1756 UNICODE_STRING uniShortName;
1758 pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
1760 RtlCopyMemory( pDirNode->NameInformation.ShortName,
1761 pResultCB->DirEnum.ShortName,
1762 pDirNode->NameInformation.ShortNameLength);
1765 // Generate the short name index
1768 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1769 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1771 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1774 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1775 AFS_TRACE_LEVEL_VERBOSE,
1776 "AFSNotifyFileCreate Initialized short name %wZ for DE %p for %wZ\n",
1779 &pDirNode->NameInformation.FileName);
1782 if ( !BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1786 // Update the parent data version
1789 ParentObjectInfo->DataVersion = pResultCB->ParentDataVersion;
1791 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1792 AFS_TRACE_LEVEL_VERBOSE,
1793 "AFSNotifyFileCreate entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
1795 ParentObjectInfo->FileId.Cell,
1796 ParentObjectInfo->FileId.Volume,
1797 ParentObjectInfo->FileId.Vnode,
1798 ParentObjectInfo->FileId.Unique,
1799 ParentObjectInfo->DataVersion.QuadPart);
1802 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1805 // Return the directory node
1808 *DirNode = pDirNode;
1812 if( pResultCB != NULL)
1815 AFSExFreePool( pResultCB);
1823 AFSUpdateFileInformation( IN AFSFileID *ParentFid,
1824 IN AFSObjectInfoCB *ObjectInfo,
1828 NTSTATUS ntStatus = STATUS_SUCCESS;
1829 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1830 AFSFileUpdateCB stUpdateCB;
1831 ULONG ulResultLen = 0;
1832 AFSFileUpdateResultCB *pUpdateResultCB = NULL;
1838 // Init the control block for the request
1841 RtlZeroMemory( &stUpdateCB,
1842 sizeof( AFSFileUpdateCB));
1844 stUpdateCB.AllocationSize = ObjectInfo->EndOfFile;
1846 stUpdateCB.FileAttributes = ObjectInfo->FileAttributes;
1848 stUpdateCB.EaSize = ObjectInfo->EaSize;
1850 stUpdateCB.ParentId = *ParentFid;
1852 stUpdateCB.LastAccessTime = ObjectInfo->LastAccessTime;
1854 stUpdateCB.CreateTime = ObjectInfo->CreationTime;
1856 stUpdateCB.ChangeTime = ObjectInfo->ChangeTime;
1858 stUpdateCB.LastWriteTime = ObjectInfo->LastWriteTime;
1860 pUpdateResultCB = (AFSFileUpdateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1862 AFS_UPDATE_RESULT_TAG);
1864 if( pUpdateResultCB == NULL)
1867 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1870 ulResultLen = PAGE_SIZE;
1872 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_UPDATE_FILE,
1873 AFS_REQUEST_FLAG_SYNCHRONOUS,
1876 &ObjectInfo->FileId,
1878 sizeof( AFSFileUpdateCB),
1882 if( ntStatus != STATUS_SUCCESS)
1885 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1886 AFS_TRACE_LEVEL_ERROR,
1887 "AFSUpdateFileInformation failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1888 ObjectInfo->FileId.Cell,
1889 ObjectInfo->FileId.Volume,
1890 ObjectInfo->FileId.Vnode,
1891 ObjectInfo->FileId.Unique,
1894 try_return( ntStatus);
1898 // Update the data version
1901 AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1904 if ( !BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1907 ObjectInfo->DataVersion = pUpdateResultCB->DirEnum.DataVersion;
1910 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1914 if( pUpdateResultCB != NULL)
1917 AFSExFreePool( pUpdateResultCB);
1925 AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
1927 IN BOOLEAN CheckOnly)
1929 NTSTATUS ntStatus = STATUS_SUCCESS;
1930 ULONG ulResultLen = 0;
1931 AFSFileDeleteCB stDelete;
1932 AFSFileDeleteResultCB stDeleteResult;
1933 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1938 stDelete.ParentId = DirectoryCB->ObjectInformation->ParentObjectInformation->FileId;
1940 stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
1942 ulResultLen = sizeof( AFSFileDeleteResultCB);
1946 ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
1949 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
1952 &DirectoryCB->NameInformation.FileName,
1953 &DirectoryCB->ObjectInformation->FileId,
1955 sizeof( AFSFileDeleteCB),
1959 if( ntStatus != STATUS_SUCCESS)
1962 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1963 AFS_TRACE_LEVEL_ERROR,
1964 "AFSNotifyDelete failed ParentFID %08lX-%08lX-%08lX-%08lX %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1965 stDelete.ParentId.Cell,
1966 stDelete.ParentId.Volume,
1967 stDelete.ParentId.Vnode,
1968 stDelete.ParentId.Unique,
1969 &DirectoryCB->NameInformation.FileName,
1970 DirectoryCB->ObjectInformation->FileId.Cell,
1971 DirectoryCB->ObjectInformation->FileId.Volume,
1972 DirectoryCB->ObjectInformation->FileId.Vnode,
1973 DirectoryCB->ObjectInformation->FileId.Unique,
1976 try_return( ntStatus);
1979 AFSAcquireExcl( DirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1986 // Validate the parent data version
1989 if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
1992 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1994 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
2001 // Update the parent data version
2004 if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart - 1)
2007 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
2009 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
2015 // TODO -- The entry must be removed from the directory at which point the
2016 // Directory data version number can be updated. Until then we must force
2019 // DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = stDeleteResult.ParentDataVersion.QuadPart;
2022 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
2024 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
2028 AFSReleaseResource( DirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2039 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
2041 IN AFSObjectInfoCB *ParentObjectInfo,
2042 IN AFSObjectInfoCB *TargetParentObjectInfo,
2043 IN AFSDirectoryCB *DirectoryCB,
2044 IN UNICODE_STRING *TargetName,
2045 OUT AFSFileID *UpdatedFID)
2048 NTSTATUS ntStatus = STATUS_SUCCESS;
2049 AFSFileRenameCB *pRenameCB = NULL;
2050 AFSFileRenameResultCB *pRenameResultCB = NULL;
2051 ULONG ulResultLen = 0;
2057 // Init the control block for the request
2060 pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
2062 AFS_RENAME_REQUEST_TAG);
2064 if( pRenameCB == NULL)
2067 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2070 RtlZeroMemory( pRenameCB,
2073 pRenameCB->SourceParentId = ParentObjectInfo->FileId;
2075 pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
2077 pRenameCB->TargetNameLength = TargetName->Length;
2079 RtlCopyMemory( pRenameCB->TargetName,
2081 TargetName->Length);
2084 // Use the same buffer for the result control block
2087 pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
2089 ulResultLen = PAGE_SIZE;
2091 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
2092 AFS_REQUEST_FLAG_SYNCHRONOUS,
2094 &DirectoryCB->NameInformation.FileName,
2095 &ObjectInfo->FileId,
2097 sizeof( AFSFileRenameCB) + TargetName->Length,
2101 if( ntStatus != STATUS_SUCCESS)
2104 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2105 AFS_TRACE_LEVEL_ERROR,
2106 "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2107 ObjectInfo->FileId.Cell,
2108 ObjectInfo->FileId.Volume,
2109 ObjectInfo->FileId.Vnode,
2110 ObjectInfo->FileId.Unique,
2113 try_return( ntStatus);
2117 // Update the information from the returned data
2120 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2123 if ( ParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->SourceParentDataVersion.QuadPart - 1)
2126 ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
2131 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2133 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2136 if ( ParentObjectInfo != TargetParentObjectInfo)
2139 if ( TargetParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->TargetParentDataVersion.QuadPart - 1)
2142 TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
2147 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2149 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2154 // Move over the short name
2157 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2159 if( DirectoryCB->NameInformation.ShortNameLength > 0)
2162 UNICODE_STRING uniShortName;
2164 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2165 uniShortName.MaximumLength = uniShortName.Length;
2166 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2168 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2169 AFS_TRACE_LEVEL_VERBOSE,
2170 "AFSNotifyRename Update old short name %wZ for DE %p for %wZ\n",
2173 &DirectoryCB->NameInformation.FileName);
2175 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2177 RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
2178 pRenameResultCB->DirEnum.ShortName,
2179 DirectoryCB->NameInformation.ShortNameLength);
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 Initialized short name %wZ for DE %p for %wZ\n",
2190 &DirectoryCB->NameInformation.FileName);
2195 UNICODE_STRING uniShortName;
2197 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2198 uniShortName.MaximumLength = uniShortName.Length;
2199 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2201 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2202 AFS_TRACE_LEVEL_VERBOSE,
2203 "AFSNotifyRename Removing old short name %wZ for DE %p for %wZ\n",
2206 &DirectoryCB->NameInformation.FileName);
2208 DirectoryCB->NameInformation.ShortNameLength = 0;
2210 DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2213 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2215 if( UpdatedFID != NULL)
2217 *UpdatedFID = pRenameResultCB->DirEnum.FileId;
2222 if( pRenameCB != NULL)
2225 AFSExFreePool( pRenameCB);
2233 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
2235 IN BOOLEAN FastCall,
2236 OUT AFSDirEnumEntry **DirEnumEntry)
2239 NTSTATUS ntStatus = STATUS_SUCCESS;
2240 AFSEvalTargetCB stTargetID;
2241 ULONG ulResultBufferLength;
2242 AFSFileEvalResultCB *pEvalResultCB = NULL;
2243 AFSDirEnumEntry *pDirEnumCB = NULL;
2244 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
2249 RtlZeroMemory( &stTargetID,
2250 sizeof( AFSEvalTargetCB));
2252 if( ObjectInfo->ParentObjectInformation != NULL)
2255 stTargetID.ParentId = ObjectInfo->ParentObjectInformation->FileId;
2259 // Allocate our response buffer
2262 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2264 AFS_GENERIC_MEMORY_30_TAG);
2266 if( pEvalResultCB == NULL)
2269 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2273 // Call to the service to evaluate the fid
2276 ulResultBufferLength = PAGE_SIZE;
2281 ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
2284 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
2288 &ObjectInfo->FileId,
2290 sizeof( AFSEvalTargetCB),
2292 &ulResultBufferLength);
2294 if( ntStatus != STATUS_SUCCESS)
2298 // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
2302 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2305 if( ObjectInfo->ParentObjectInformation != NULL)
2308 AFSAcquireExcl( ObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
2311 SetFlag( ObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
2313 ObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
2315 AFSReleaseResource( ObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2319 try_return( ntStatus);
2323 // Validate the parent data version
2326 if ( ObjectInfo->ParentObjectInformation != NULL)
2329 AFSAcquireExcl( ObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
2332 if ( ObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2335 SetFlag( ObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
2337 ObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
2340 AFSReleaseResource( ObjectInfo->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2344 // Pass back the dir enum entry
2347 if( DirEnumEntry != NULL)
2350 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2352 AFS_GENERIC_MEMORY_2_TAG);
2354 if( pDirEnumCB == NULL)
2357 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2360 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2361 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2363 *DirEnumEntry = pDirEnumCB;
2368 if( pEvalResultCB != NULL)
2371 AFSExFreePool( pEvalResultCB);
2374 if( !NT_SUCCESS( ntStatus))
2377 if( pDirEnumCB != NULL)
2380 AFSExFreePool( pDirEnumCB);
2383 *DirEnumEntry = NULL;
2391 AFSEvaluateTargetByName( IN GUID *AuthGroup,
2392 IN AFSObjectInfoCB *ParentObjectInfo,
2393 IN PUNICODE_STRING SourceName,
2394 OUT AFSDirEnumEntry **DirEnumEntry)
2397 NTSTATUS ntStatus = STATUS_SUCCESS;
2398 AFSEvalTargetCB stTargetID;
2399 ULONG ulResultBufferLength;
2400 AFSFileEvalResultCB *pEvalResultCB = NULL;
2401 AFSDirEnumEntry *pDirEnumCB = NULL;
2406 stTargetID.ParentId = ParentObjectInfo->FileId;
2409 // Allocate our response buffer
2412 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2414 AFS_GENERIC_MEMORY_31_TAG);
2416 if( pEvalResultCB == NULL)
2419 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2423 // Call to the service to evaluate the fid
2426 ulResultBufferLength = PAGE_SIZE;
2428 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
2429 AFS_REQUEST_FLAG_SYNCHRONOUS,
2434 sizeof( AFSEvalTargetCB),
2436 &ulResultBufferLength);
2438 if( ntStatus != STATUS_SUCCESS)
2441 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2444 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2447 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2449 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2451 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2454 try_return( ntStatus);
2458 // Validate the parent data version
2461 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2464 if ( ParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2467 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2469 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2472 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2475 // Pass back the dir enum entry
2478 if( DirEnumEntry != NULL)
2481 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2483 AFS_GENERIC_MEMORY_3_TAG);
2485 if( pDirEnumCB == NULL)
2488 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2491 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2492 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2494 *DirEnumEntry = pDirEnumCB;
2499 if( pEvalResultCB != NULL)
2502 AFSExFreePool( pEvalResultCB);
2505 if( !NT_SUCCESS( ntStatus))
2508 if( pDirEnumCB != NULL)
2511 AFSExFreePool( pDirEnumCB);
2514 *DirEnumEntry = NULL;
2522 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
2523 IN AFSFileID *FileID,
2524 OUT AFSVolumeInfoCB *VolumeInformation)
2527 NTSTATUS ntStatus = STATUS_SUCCESS;
2528 ULONG ulResultLen = 0;
2533 ulResultLen = sizeof( AFSVolumeInfoCB);
2535 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
2536 AFS_REQUEST_FLAG_SYNCHRONOUS,
2545 if( ntStatus != STATUS_SUCCESS)
2548 try_return( ntStatus);
2560 AFSRetrieveVolumeSizeInformation( IN GUID *AuthGroup,
2561 IN AFSFileID *FileID,
2562 OUT AFSVolumeSizeInfoCB *VolumeSizeInformation)
2565 NTSTATUS ntStatus = STATUS_SUCCESS;
2566 ULONG ulResultLen = 0;
2571 ulResultLen = sizeof( AFSVolumeSizeInfoCB);
2573 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_SIZE_INFO,
2574 AFS_REQUEST_FLAG_SYNCHRONOUS,
2580 VolumeSizeInformation,
2583 if( ntStatus != STATUS_SUCCESS)
2586 try_return( ntStatus);
2598 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
2599 IN ULONG InputLength,
2600 IN ULONG OutputLength,
2601 IN void *InputDataBuffer,
2602 OUT void *OutputDataBuffer,
2603 OUT ULONG *BytesReturned)
2606 NTSTATUS ntStatus = STATUS_SUCCESS;
2607 ULONG ulResultLen = 0;
2608 MDL *pInputMdl = NULL, *pOutputMdl = NULL;
2609 void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
2610 ULONG ulBufferLength = OutputLength;
2611 AFSPipeIORequestCB *pIoRequest = NULL;
2617 // Map the user buffer to a system address
2620 pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
2624 if( pInputSystemBuffer == NULL)
2627 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2630 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2631 sizeof( AFSPipeIORequestCB) +
2633 AFS_GENERIC_MEMORY_4_TAG);
2635 if( pIoRequest == NULL)
2638 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2641 RtlZeroMemory( pIoRequest,
2642 sizeof( AFSPipeIORequestCB) + InputLength);
2644 pIoRequest->RequestId = Ccb->RequestID;
2646 pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2648 pIoRequest->BufferLength = InputLength;
2650 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
2654 pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
2658 if( pOutputSystemBuffer == NULL)
2661 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2665 // Send the call to the service
2668 ulResultLen = OutputLength;
2670 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
2671 AFS_REQUEST_FLAG_SYNCHRONOUS,
2673 &Ccb->DirectoryCB->NameInformation.FileName,
2676 sizeof( AFSPipeIORequestCB) + InputLength,
2677 pOutputSystemBuffer,
2680 if( ntStatus != STATUS_SUCCESS &&
2681 ntStatus != STATUS_BUFFER_OVERFLOW)
2684 if( NT_SUCCESS( ntStatus))
2687 ntStatus = STATUS_DEVICE_NOT_READY;
2690 try_return( ntStatus);
2694 // Return the bytes processed
2697 *BytesReturned = ulResultLen;
2701 if( pInputMdl != NULL)
2704 MmUnlockPages( pInputMdl);
2706 IoFreeMdl( pInputMdl);
2709 if( pOutputMdl != NULL)
2712 MmUnlockPages( pOutputMdl);
2714 IoFreeMdl( pOutputMdl);
2717 if( pIoRequest != NULL)
2720 AFSExFreePool( pIoRequest);
2728 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
2729 IN ULONG InformationClass,
2730 IN ULONG InputLength,
2731 IN void *DataBuffer)
2734 NTSTATUS ntStatus = STATUS_SUCCESS;
2735 AFSPipeInfoRequestCB *pInfoRequest = NULL;
2740 pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2741 sizeof( AFSPipeInfoRequestCB) +
2743 AFS_GENERIC_MEMORY_5_TAG);
2745 if( pInfoRequest == NULL)
2748 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2751 RtlZeroMemory( pInfoRequest,
2752 sizeof( AFSPipeInfoRequestCB) + InputLength);
2754 pInfoRequest->RequestId = Ccb->RequestID;
2756 pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2758 pInfoRequest->BufferLength = InputLength;
2760 pInfoRequest->InformationClass = InformationClass;
2762 RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
2767 // Send the call to the service
2770 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
2771 AFS_REQUEST_FLAG_SYNCHRONOUS,
2773 &Ccb->DirectoryCB->NameInformation.FileName,
2776 sizeof( AFSPipeInfoRequestCB) + InputLength,
2780 if( ntStatus != STATUS_SUCCESS)
2783 if( NT_SUCCESS( ntStatus))
2786 ntStatus = STATUS_DEVICE_NOT_READY;
2789 try_return( ntStatus);
2794 if( pInfoRequest != NULL)
2797 AFSExFreePool( pInfoRequest);
2805 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
2806 IN ULONG InformationClass,
2807 IN ULONG OutputLength,
2808 IN void *DataBuffer,
2809 OUT ULONG *BytesReturned)
2812 NTSTATUS ntStatus = STATUS_SUCCESS;
2813 AFSPipeInfoRequestCB stInfoRequest;
2814 ULONG ulBytesProcessed = 0;
2819 RtlZeroMemory( &stInfoRequest,
2820 sizeof( AFSPipeInfoRequestCB));
2822 stInfoRequest.RequestId = Ccb->RequestID;
2824 stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2826 stInfoRequest.BufferLength = OutputLength;
2828 stInfoRequest.InformationClass = InformationClass;
2830 ulBytesProcessed = OutputLength;
2833 // Send the call to the service
2836 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
2837 AFS_REQUEST_FLAG_SYNCHRONOUS,
2839 &Ccb->DirectoryCB->NameInformation.FileName,
2842 sizeof( AFSPipeInfoRequestCB),
2846 if( ntStatus != STATUS_SUCCESS)
2849 if( NT_SUCCESS( ntStatus))
2852 ntStatus = STATUS_DEVICE_NOT_READY;
2855 try_return( ntStatus);
2858 *BytesReturned = ulBytesProcessed;
2869 AFSReleaseFid( IN AFSFileID *FileId)
2872 NTSTATUS ntStatus = STATUS_SUCCESS;
2877 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
2892 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
2893 IN LARGE_INTEGER *ExtentOffset,
2897 BOOLEAN bRequestQueued = FALSE;
2898 NTSTATUS ntStatus = STATUS_SUCCESS;
2899 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2900 AFSCommSrvcCB *pCommSrvc = NULL;
2901 AFSPoolEntry *pPoolEntry = NULL;
2902 AFSRequestExtentsCB *pRequestExtents = NULL;
2908 pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
2910 AFSAcquireShared( &pCommSrvc->IrpPoolLock,
2913 pPoolEntry = pCommSrvc->RequestPoolHead;
2915 while( pPoolEntry != NULL)
2918 if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
2921 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
2924 pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
2926 if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
2927 pRequestExtents->Length == Length)
2930 bRequestQueued = TRUE;
2935 pPoolEntry = pPoolEntry->fLink;
2938 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
2941 return bRequestQueued;