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 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
169 AFS_TRACE_LEVEL_VERBOSE,
170 "AFSEnumerateDirectory Directory Complete FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX Status %08lX\n",
171 ObjectInfoCB->FileId.Cell,
172 ObjectInfoCB->FileId.Volume,
173 ObjectInfoCB->FileId.Vnode,
174 ObjectInfoCB->FileId.Unique,
175 pDirEnumResponse->SnapshotDataVersion.HighPart,
176 pDirEnumResponse->SnapshotDataVersion.LowPart,
177 pDirEnumResponse->CurrentDataVersion.HighPart,
178 pDirEnumResponse->CurrentDataVersion.LowPart,
181 ObjectInfoCB->DataVersion = pDirEnumResponse->SnapshotDataVersion;
183 if ( pDirEnumResponse->SnapshotDataVersion.QuadPart != pDirEnumResponse->CurrentDataVersion.QuadPart )
186 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
188 ObjectInfoCB->DataVersion.QuadPart = (ULONGLONG)-1;
190 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
191 AFS_TRACE_LEVEL_VERBOSE,
192 "AFSEnumerateDirectory Force Verify due to DV change during enumeration FID %08lX-%08lX-%08lX-%08lX\n",
193 ObjectInfoCB->FileId.Cell,
194 ObjectInfoCB->FileId.Volume,
195 ObjectInfoCB->FileId.Vnode,
196 ObjectInfoCB->FileId.Unique);
202 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
203 AFS_TRACE_LEVEL_VERBOSE,
204 "AFSEnumerateDirectory Failed to enumerate directory FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ Status %08lX\n",
205 ObjectInfoCB->FileId.Cell,
206 ObjectInfoCB->FileId.Volume,
207 ObjectInfoCB->FileId.Vnode,
208 ObjectInfoCB->FileId.Unique,
216 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
218 pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
220 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
221 AFS_TRACE_LEVEL_VERBOSE,
222 "AFSEnumerateDirectory Enumerating FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX\n",
223 ObjectInfoCB->FileId.Cell,
224 ObjectInfoCB->FileId.Volume,
225 ObjectInfoCB->FileId.Vnode,
226 ObjectInfoCB->FileId.Unique,
227 pDirEnumResponse->SnapshotDataVersion.HighPart,
228 pDirEnumResponse->SnapshotDataVersion.LowPart,
229 pDirEnumResponse->CurrentDataVersion.HighPart,
230 pDirEnumResponse->CurrentDataVersion.LowPart);
233 // Remove the leading header from the processed length
236 ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
238 while( ulResultLen > 0)
241 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
243 uniDirName.MaximumLength = uniDirName.Length;
245 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
247 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
249 uniTargetName.MaximumLength = uniTargetName.Length;
251 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
254 // Be sure we don't have this entry in the case sensitive tree
257 ulCRC = AFSGenerateCRC( &uniDirName,
260 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
264 if( pDirNode != NULL)
268 // Check that the FIDs are the same
271 if( AFSIsEqualFID( &pCurrentDirEntry->FileId,
272 &pDirNode->ObjectInformation->FileId))
276 // Duplicate entry, skip it
279 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
281 uniTargetName.Length);
283 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
285 if( ulResultLen >= ulEntryLength)
287 ulResultLen -= ulEntryLength;
295 // Update the metadata for the entry
298 if( pDirNode->ObjectInformation->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
301 AFSUpdateMetaData( pDirNode,
304 if( pDirNode->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
307 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
308 AFS_TRACE_LEVEL_VERBOSE,
309 "AFSEnumerateDirectory Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
311 pDirNode->ObjectInformation->FileId.Cell,
312 pDirNode->ObjectInformation->FileId.Volume,
313 pDirNode->ObjectInformation->FileId.Vnode,
314 pDirNode->ObjectInformation->FileId.Unique);
316 SetFlag( pDirNode->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
318 pDirNode->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
328 // Need to tear down this entry and rebuild it below
331 if( pDirNode->OpenReferenceCount == 0)
334 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
335 AFS_TRACE_LEVEL_VERBOSE,
336 "AFSEnumerateDirectory Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
338 &pDirNode->NameInformation.FileName,
339 pDirNode->ObjectInformation->FileId.Cell,
340 pDirNode->ObjectInformation->FileId.Volume,
341 pDirNode->ObjectInformation->FileId.Vnode,
342 pDirNode->ObjectInformation->FileId.Unique,
343 pCurrentDirEntry->FileId.Cell,
344 pCurrentDirEntry->FileId.Volume,
345 pCurrentDirEntry->FileId.Vnode,
346 pCurrentDirEntry->FileId.Unique);
348 AFSDeleteDirEntry( ObjectInfoCB,
354 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
356 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
357 AFS_TRACE_LEVEL_VERBOSE,
358 "AFSEnumerateDirectory Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
360 &pDirNode->NameInformation.FileName,
361 pDirNode->ObjectInformation->FileId.Cell,
362 pDirNode->ObjectInformation->FileId.Volume,
363 pDirNode->ObjectInformation->FileId.Vnode,
364 pDirNode->ObjectInformation->FileId.Unique,
365 pCurrentDirEntry->FileId.Cell,
366 pCurrentDirEntry->FileId.Volume,
367 pCurrentDirEntry->FileId.Vnode,
368 pCurrentDirEntry->FileId.Unique);
370 AFSRemoveNameEntry( ObjectInfoCB,
378 pDirNode = AFSInitDirEntry( ObjectInfoCB,
382 (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
384 if( pDirNode == NULL)
387 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
392 AFSUpdateMetaData( pDirNode,
395 if( ObjectInfoCB->FileType == AFS_FILE_TYPE_DIRECTORY)
398 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
399 AFS_TRACE_LEVEL_VERBOSE,
400 "AFSEnumerateDirectory Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
402 ObjectInfoCB->FileId.Cell,
403 ObjectInfoCB->FileId.Volume,
404 ObjectInfoCB->FileId.Vnode,
405 ObjectInfoCB->FileId.Unique);
407 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
409 ObjectInfoCB->DataVersion.QuadPart = (ULONGLONG)-1;
413 // Set up the entry length
416 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
417 pCurrentDirEntry->FileNameLength +
418 pCurrentDirEntry->TargetNameLength);
421 // Init the short name if we have one
424 if( pCurrentDirEntry->ShortNameLength > 0)
427 UNICODE_STRING uniShortName;
429 pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
431 RtlCopyMemory( pDirNode->NameInformation.ShortName,
432 pCurrentDirEntry->ShortName,
433 pDirNode->NameInformation.ShortNameLength);
436 // Generate the short name index
439 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
440 uniShortName.MaximumLength = uniShortName.Length;
441 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
443 if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
448 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
451 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
452 AFS_TRACE_LEVEL_VERBOSE,
453 "AFSEnumerateDirectory Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
456 &pDirNode->NameInformation.FileName,
457 pCurrentDirEntry->FileId.Cell,
458 pCurrentDirEntry->FileId.Volume,
459 pCurrentDirEntry->FileId.Vnode,
460 pCurrentDirEntry->FileId.Unique);
464 pDirNode->NameInformation.ShortNameLength = 0;
466 RtlZeroMemory( pDirNode->NameInformation.ShortName,
467 (12 * sizeof( WCHAR)));
472 // Insert the node into the name tree
475 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
478 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
480 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
481 AFS_TRACE_LEVEL_VERBOSE,
482 "AFSEnumerateDirectory Insert DE %p to head of case sensitive tree for %wZ\n",
484 &pDirNode->NameInformation.FileName);
489 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
490 AFS_TRACE_LEVEL_VERBOSE,
491 "AFSEnumerateDirectory Insert DE %p to case sensitive tree for %wZ\n",
493 &pDirNode->NameInformation.FileName);
495 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
500 // Delete this dir entry and continue on
503 AFSDeleteDirEntry( ObjectInfoCB,
506 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
508 if( ulResultLen >= ulEntryLength)
510 ulResultLen -= ulEntryLength;
521 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
523 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
526 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
527 AFS_TRACE_LEVEL_VERBOSE,
528 "AFSEnumerateDirectory Insert DE %p to head of case insensitive tree for %wZ\n",
530 &pDirNode->NameInformation.FileName);
532 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
534 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
539 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
540 AFS_TRACE_LEVEL_VERBOSE,
541 "AFSEnumerateDirectory Insert DE %p to case insensitive tree for %wZ\n",
543 &pDirNode->NameInformation.FileName);
545 AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
549 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
552 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
557 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
559 pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
562 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
564 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
566 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
568 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
569 AFS_TRACE_LEVEL_VERBOSE,
570 "AFSEnumerateDirectory Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
571 &pDirNode->NameInformation.FileName,
572 ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
573 ObjectInfoCB->FileId.Cell,
574 ObjectInfoCB->FileId.Volume,
575 ObjectInfoCB->FileId.Vnode,
576 ObjectInfoCB->FileId.Unique);
578 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
582 // Insert the short name entry if we have a valid short name
585 if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
588 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
589 AFS_TRACE_LEVEL_VERBOSE,
590 "AFSEnumerateDirectory Insert DE %p to head of shortname tree for %wZ\n",
592 &pDirNode->NameInformation.FileName);
594 ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
596 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
601 if( NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
604 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
606 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
607 AFS_TRACE_LEVEL_VERBOSE,
608 "AFSEnumerateDirectory Insert DE %p to shortname tree for %wZ\n",
610 &pDirNode->NameInformation.FileName);
619 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
621 if( ulResultLen >= ulEntryLength)
623 ulResultLen -= ulEntryLength;
631 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
634 // Reset the information in the request buffer since it got trampled
638 pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
640 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
641 AFS_TRACE_LEVEL_VERBOSE,
642 "AFSEnumerateDirectory EnumHandle %08lX\n",
643 pDirQueryCB->EnumHandle);
655 AFSExFreePool( pBuffer);
659 // If the processing failed then we should reset the directory content in the event
660 // it is re-enumerated
663 if( !NT_SUCCESS( ntStatus))
666 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
667 AFS_TRACE_LEVEL_ERROR,
668 "AFSEnumerateDirectory Resetting content for FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
669 ObjectInfoCB->FileId.Cell,
670 ObjectInfoCB->FileId.Volume,
671 ObjectInfoCB->FileId.Vnode,
672 ObjectInfoCB->FileId.Unique,
675 AFSResetDirectoryContent( ObjectInfoCB);
683 AFSEnumerateDirectoryNoResponse( IN GUID *AuthGroup,
684 IN AFSFileID *FileId)
687 NTSTATUS ntStatus = STATUS_SUCCESS;
688 AFSDirQueryCB stDirQueryCB;
689 ULONG ulRequestFlags = 0;
695 // Use the payload buffer for information we will pass to the service
698 stDirQueryCB.EnumHandle = 0;
700 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
705 (void *)&stDirQueryCB,
706 sizeof( AFSDirQueryCB),
710 if( ntStatus != STATUS_SUCCESS)
713 if( ntStatus == STATUS_NO_MORE_FILES ||
714 ntStatus == STATUS_NO_MORE_ENTRIES)
717 ntStatus = STATUS_SUCCESS;
722 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
723 AFS_TRACE_LEVEL_ERROR,
724 "AFSEnumerateDirectoryNoResponse Failed to enumerate directory Status %08lX\n",
734 AFSVerifyDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB,
738 NTSTATUS ntStatus = STATUS_SUCCESS;
739 void *pBuffer = NULL;
740 ULONG ulResultLen = 0;
741 AFSDirQueryCB *pDirQueryCB;
742 AFSDirEnumEntry *pCurrentDirEntry = NULL;
743 AFSDirectoryCB *pDirNode = NULL;
744 ULONG ulEntryLength = 0;
745 AFSDirEnumResp *pDirEnumResponse = NULL;
746 UNICODE_STRING uniDirName, uniTargetName;
747 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_FAST_REQUEST;
749 AFSObjectInfoCB *pObjectInfo = NULL;
750 ULONGLONG ullIndex = 0;
751 UNICODE_STRING uniGUID;
756 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
759 uniGUID.MaximumLength = 0;
760 uniGUID.Buffer = NULL;
762 if( AuthGroup != NULL)
764 RtlStringFromGUID( *AuthGroup,
768 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
769 AFS_TRACE_LEVEL_VERBOSE,
770 "AFSVerifyDirectoryContent Verifying content for FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
771 ObjectInfoCB->FileId.Cell,
772 ObjectInfoCB->FileId.Volume,
773 ObjectInfoCB->FileId.Vnode,
774 ObjectInfoCB->FileId.Unique,
777 if( AuthGroup != NULL)
779 RtlFreeUnicodeString( &uniGUID);
783 // Initialize the directory enumeration buffer for the directory
786 pBuffer = AFSExAllocatePoolWithTag( PagedPool,
787 AFS_DIR_ENUM_BUFFER_LEN,
793 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
796 RtlZeroMemory( pBuffer,
797 AFS_DIR_ENUM_BUFFER_LEN);
799 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
802 // Use the payload buffer for information we will pass to the service
805 pDirQueryCB = (AFSDirQueryCB *)pBuffer;
807 pDirQueryCB->EnumHandle = 0;
810 // Loop on the information
817 // If the enumeration handle is -1 then we are done
820 if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
823 ntStatus = STATUS_NO_MORE_ENTRIES;
829 // Go and retrieve the directory contents
832 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
836 &ObjectInfoCB->FileId,
838 sizeof( AFSDirQueryCB),
843 if( ntStatus != STATUS_SUCCESS ||
847 if( ntStatus == STATUS_NO_MORE_FILES ||
848 ntStatus == STATUS_NO_MORE_ENTRIES)
851 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
853 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
854 AFS_TRACE_LEVEL_VERBOSE,
855 "AFSVerifyDirectoryContent Directory Complete FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX Status %08lX\n",
856 ObjectInfoCB->FileId.Cell,
857 ObjectInfoCB->FileId.Volume,
858 ObjectInfoCB->FileId.Vnode,
859 ObjectInfoCB->FileId.Unique,
860 pDirEnumResponse->SnapshotDataVersion.HighPart,
861 pDirEnumResponse->SnapshotDataVersion.LowPart,
862 pDirEnumResponse->CurrentDataVersion.HighPart,
863 pDirEnumResponse->CurrentDataVersion.LowPart,
866 ntStatus = STATUS_SUCCESS;
868 ObjectInfoCB->DataVersion = pDirEnumResponse->SnapshotDataVersion;
870 if ( pDirEnumResponse->SnapshotDataVersion.QuadPart != pDirEnumResponse->CurrentDataVersion.QuadPart )
873 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
875 pDirNode->ObjectInformation->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);
889 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
890 AFS_TRACE_LEVEL_ERROR,
891 "AFSVerifyDirectoryContent Failed to enumerate directory FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ Status %08lX\n",
892 ObjectInfoCB->FileId.Cell,
893 ObjectInfoCB->FileId.Volume,
894 ObjectInfoCB->FileId.Vnode,
895 ObjectInfoCB->FileId.Unique,
903 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
905 pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
907 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
908 AFS_TRACE_LEVEL_VERBOSE,
909 "AFSVerifyDirectoryContent EnumResponse FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX\n",
910 ObjectInfoCB->FileId.Cell,
911 ObjectInfoCB->FileId.Volume,
912 ObjectInfoCB->FileId.Vnode,
913 ObjectInfoCB->FileId.Unique,
914 pDirEnumResponse->SnapshotDataVersion.HighPart,
915 pDirEnumResponse->SnapshotDataVersion.LowPart,
916 pDirEnumResponse->CurrentDataVersion.HighPart,
917 pDirEnumResponse->CurrentDataVersion.LowPart);
920 // Remove the leading header from the processed length
923 ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
925 while( ulResultLen > 0)
928 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
930 uniDirName.MaximumLength = uniDirName.Length;
932 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
934 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
936 uniTargetName.MaximumLength = uniTargetName.Length;
938 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
941 // Does this entry already exist in the directory?
944 ulCRC = AFSGenerateCRC( &uniDirName,
947 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
953 // Set up the entry length
956 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
957 pCurrentDirEntry->FileNameLength +
958 pCurrentDirEntry->TargetNameLength);
960 if( pDirNode != NULL)
964 // Check that the FIDs are the same
967 if( AFSIsEqualFID( &pCurrentDirEntry->FileId,
968 &pDirNode->ObjectInformation->FileId))
971 AFSAcquireShared( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock,
974 ullIndex = AFSCreateLowIndex( &pCurrentDirEntry->FileId);
976 ntStatus = AFSLocateHashEntry( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeHead,
978 (AFSBTreeEntry **)&pObjectInfo);
980 AFSReleaseResource( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock);
982 if( NT_SUCCESS( ntStatus) &&
987 // Indicate this is a valid entry
990 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
992 if( pCurrentDirEntry->ShortNameLength > 0 &&
993 pDirNode->NameInformation.ShortNameLength > 0)
995 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
996 AFS_TRACE_LEVEL_VERBOSE,
997 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name %S New short name %S\n",
999 &pDirNode->NameInformation.FileName,
1000 ObjectInfoCB->FileId.Cell,
1001 ObjectInfoCB->FileId.Volume,
1002 ObjectInfoCB->FileId.Vnode,
1003 ObjectInfoCB->FileId.Unique,
1004 pDirNode->NameInformation.ShortName,
1005 pCurrentDirEntry->ShortName);
1007 else 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 NULL\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);
1021 else if( pCurrentDirEntry->ShortNameLength > 0 &&
1022 pDirNode->NameInformation.ShortNameLength == 0)
1024 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1025 AFS_TRACE_LEVEL_VERBOSE,
1026 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name %S\n",
1028 &pDirNode->NameInformation.FileName,
1029 ObjectInfoCB->FileId.Cell,
1030 ObjectInfoCB->FileId.Volume,
1031 ObjectInfoCB->FileId.Vnode,
1032 ObjectInfoCB->FileId.Unique,
1033 pCurrentDirEntry->ShortName);
1037 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1038 AFS_TRACE_LEVEL_VERBOSE,
1039 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name NULL\n",
1041 &pDirNode->NameInformation.FileName,
1042 ObjectInfoCB->FileId.Cell,
1043 ObjectInfoCB->FileId.Volume,
1044 ObjectInfoCB->FileId.Vnode,
1045 ObjectInfoCB->FileId.Unique);
1049 // Update the metadata for the entry
1052 if( pObjectInfo->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
1055 AFSUpdateMetaData( pDirNode,
1058 if( pObjectInfo->FileType == AFS_FILE_TYPE_DIRECTORY)
1061 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1062 AFS_TRACE_LEVEL_VERBOSE,
1063 "AFSVerifyDirectoryContent Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
1065 pObjectInfo->FileId.Cell,
1066 pObjectInfo->FileId.Volume,
1067 pObjectInfo->FileId.Vnode,
1068 pObjectInfo->FileId.Unique);
1070 SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1072 pObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1080 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1082 if( ulResultLen >= ulEntryLength)
1084 ulResultLen -= ulEntryLength;
1095 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1096 AFS_TRACE_LEVEL_VERBOSE,
1097 "AFSVerifyDirectoryContent Processing dir entry %p %wZ with different FID, same name in parent FID %08lX-%08lX-%08lX-%08lX\n",
1099 &pDirNode->NameInformation.FileName,
1100 ObjectInfoCB->FileId.Cell,
1101 ObjectInfoCB->FileId.Volume,
1102 ObjectInfoCB->FileId.Vnode,
1103 ObjectInfoCB->FileId.Unique);
1106 // Need to tear down this entry and rebuild it below
1109 if( pDirNode->OpenReferenceCount == 0)
1112 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1113 AFS_TRACE_LEVEL_VERBOSE,
1114 "AFSVerifyDirectoryContent Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1116 &pDirNode->NameInformation.FileName,
1117 pDirNode->ObjectInformation->FileId.Cell,
1118 pDirNode->ObjectInformation->FileId.Volume,
1119 pDirNode->ObjectInformation->FileId.Vnode,
1120 pDirNode->ObjectInformation->FileId.Unique,
1121 pCurrentDirEntry->FileId.Cell,
1122 pCurrentDirEntry->FileId.Volume,
1123 pCurrentDirEntry->FileId.Vnode,
1124 pCurrentDirEntry->FileId.Unique);
1126 AFSDeleteDirEntry( ObjectInfoCB,
1132 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1134 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1135 AFS_TRACE_LEVEL_WARNING,
1136 "AFSVerifyDirectoryContent Different FIDs - removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1138 &pDirNode->NameInformation.FileName,
1139 pDirNode->ObjectInformation->FileId.Cell,
1140 pDirNode->ObjectInformation->FileId.Volume,
1141 pDirNode->ObjectInformation->FileId.Vnode,
1142 pDirNode->ObjectInformation->FileId.Unique,
1143 pCurrentDirEntry->FileId.Cell,
1144 pCurrentDirEntry->FileId.Volume,
1145 pCurrentDirEntry->FileId.Vnode,
1146 pCurrentDirEntry->FileId.Unique);
1148 AFSRemoveNameEntry( ObjectInfoCB,
1155 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1156 AFS_TRACE_LEVEL_VERBOSE,
1157 "AFSVerifyDirectoryContent New entry %wZ for parent FID %08lX-%08lX-%08lX-%08lX\n",
1159 ObjectInfoCB->FileId.Cell,
1160 ObjectInfoCB->FileId.Volume,
1161 ObjectInfoCB->FileId.Vnode,
1162 ObjectInfoCB->FileId.Unique);
1165 pDirNode = AFSInitDirEntry( ObjectInfoCB,
1169 (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1171 if( pDirNode == NULL)
1174 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
1179 AFSUpdateMetaData( pDirNode,
1182 if( ObjectInfoCB->FileType == AFS_FILE_TYPE_DIRECTORY)
1185 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1186 AFS_TRACE_LEVEL_VERBOSE,
1187 "AFSVerifyDirectoryContent Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
1189 ObjectInfoCB->FileId.Cell,
1190 ObjectInfoCB->FileId.Volume,
1191 ObjectInfoCB->FileId.Vnode,
1192 ObjectInfoCB->FileId.Unique);
1194 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
1196 ObjectInfoCB->DataVersion.QuadPart = (ULONGLONG)-1;
1200 // Init the short name if we have one
1203 if( pCurrentDirEntry->ShortNameLength > 0)
1206 UNICODE_STRING uniShortName;
1208 pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
1210 RtlCopyMemory( pDirNode->NameInformation.ShortName,
1211 pCurrentDirEntry->ShortName,
1212 pDirNode->NameInformation.ShortNameLength);
1215 // Generate the short name index
1218 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1219 uniShortName.MaximumLength = uniShortName.Length;
1220 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1222 if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
1227 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1230 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1231 AFS_TRACE_LEVEL_VERBOSE,
1232 "AFSVerifyDirectoryContent Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1235 &pDirNode->NameInformation.FileName,
1236 pCurrentDirEntry->FileId.Cell,
1237 pCurrentDirEntry->FileId.Volume,
1238 pCurrentDirEntry->FileId.Vnode,
1239 pCurrentDirEntry->FileId.Unique);
1243 pDirNode->NameInformation.ShortNameLength = 0;
1245 RtlZeroMemory( pDirNode->NameInformation.ShortName,
1246 (12 * sizeof( WCHAR)));
1252 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1253 AFS_TRACE_LEVEL_VERBOSE,
1254 "AFSVerifyDirectoryContent NO short name for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1256 &pDirNode->NameInformation.FileName,
1257 pCurrentDirEntry->FileId.Cell,
1258 pCurrentDirEntry->FileId.Volume,
1259 pCurrentDirEntry->FileId.Vnode,
1260 pCurrentDirEntry->FileId.Unique);
1264 // Insert the node into the name tree
1267 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
1269 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
1272 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
1274 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1275 AFS_TRACE_LEVEL_VERBOSE,
1276 "AFSVerifyDirectoryContent Insert DE %p to head of case sensitive tree for %wZ\n",
1278 &pDirNode->NameInformation.FileName);
1283 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1286 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1287 AFS_TRACE_LEVEL_VERBOSE,
1288 "AFSVerifyDirectoryContent Failed to insert DE %p to case sensitive tree for %wZ\n",
1290 &pDirNode->NameInformation.FileName);
1293 // Delete this dir entry and continue on
1296 AFSDeleteDirEntry( ObjectInfoCB,
1299 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1301 if( ulResultLen >= ulEntryLength)
1303 ulResultLen -= ulEntryLength;
1314 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1315 AFS_TRACE_LEVEL_VERBOSE,
1316 "AFSVerifyDirectoryContent Insert DE %p to case sensitive tree for %wZ\n",
1318 &pDirNode->NameInformation.FileName);
1322 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1324 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
1327 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
1329 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
1331 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1332 AFS_TRACE_LEVEL_VERBOSE,
1333 "AFSVerifyDirectoryContent Insert DE %p to head of case insensitive tree for %wZ\n",
1335 &pDirNode->NameInformation.FileName);
1340 AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1343 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1344 AFS_TRACE_LEVEL_VERBOSE,
1345 "AFSVerifyDirectoryContent Insert DE %p to case insensitive tree for %wZ\n",
1347 &pDirNode->NameInformation.FileName);
1350 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
1353 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
1358 (ObjectInfoCB->Specific.Directory.DirectoryNodeListTail)->ListEntry.fLink = pDirNode;
1360 pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
1363 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
1365 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
1367 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
1369 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1370 AFS_TRACE_LEVEL_VERBOSE,
1371 "AFSVerifyDirectoryContent Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
1372 &pDirNode->NameInformation.FileName,
1373 ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
1374 ObjectInfoCB->FileId.Cell,
1375 ObjectInfoCB->FileId.Volume,
1376 ObjectInfoCB->FileId.Vnode,
1377 ObjectInfoCB->FileId.Unique);
1379 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
1383 // Insert the short name entry if we have a valid short name
1386 if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
1389 ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
1391 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1392 AFS_TRACE_LEVEL_VERBOSE,
1393 "AFSVerifyDirectoryContent Insert DE %p to head of shortname tree for %wZ\n",
1395 &pDirNode->NameInformation.FileName);
1397 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1402 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
1405 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1406 AFS_TRACE_LEVEL_VERBOSE,
1407 "AFSVerifyDirectoryContent Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
1409 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex,
1410 &pDirNode->NameInformation.FileName);
1414 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1416 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1417 AFS_TRACE_LEVEL_VERBOSE,
1418 "AFSVerifyDirectoryContent Insert DE %p to shortname tree for %wZ\n",
1420 &pDirNode->NameInformation.FileName);
1425 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
1431 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1433 if( ulResultLen >= ulEntryLength)
1435 ulResultLen -= ulEntryLength;
1443 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
1446 // Reset the information in the request buffer since it got trampled
1450 pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
1459 if( pBuffer != NULL)
1462 AFSExFreePool( pBuffer);
1470 AFSNotifyFileCreate( IN GUID *AuthGroup,
1471 IN AFSObjectInfoCB *ParentObjectInfo,
1472 IN PLARGE_INTEGER FileSize,
1473 IN ULONG FileAttributes,
1474 IN UNICODE_STRING *FileName,
1475 OUT AFSDirectoryCB **DirNode)
1478 NTSTATUS ntStatus = STATUS_SUCCESS;
1479 AFSFileCreateCB stCreateCB;
1480 AFSFileCreateResultCB *pResultCB = NULL;
1481 ULONG ulResultLen = 0;
1482 UNICODE_STRING uniTargetName;
1483 AFSDirectoryCB *pDirNode = NULL;
1485 LARGE_INTEGER liOldDataVersion;
1491 // Init the control block for the request
1494 RtlZeroMemory( &stCreateCB,
1495 sizeof( AFSFileCreateCB));
1497 stCreateCB.ParentId = ParentObjectInfo->FileId;
1499 stCreateCB.AllocationSize = *FileSize;
1501 stCreateCB.FileAttributes = FileAttributes;
1503 stCreateCB.EaSize = 0;
1505 liOldDataVersion = ParentObjectInfo->DataVersion;
1508 // Allocate our return buffer
1511 pResultCB = (AFSFileCreateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1513 AFS_GENERIC_MEMORY_1_TAG);
1515 if( pResultCB == NULL)
1518 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1521 RtlZeroMemory( pResultCB,
1524 ulResultLen = PAGE_SIZE;
1527 // Send the call to the service
1530 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_FILE,
1531 AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_HOLD_FID,
1536 sizeof( AFSFileCreateCB),
1540 if( ntStatus != STATUS_SUCCESS)
1543 if( NT_SUCCESS( ntStatus))
1546 ntStatus = STATUS_DEVICE_NOT_READY;
1549 try_return( ntStatus);
1553 // We may have raced with an invalidation call and a subsequent re-enumeration of this parent
1554 // and though we created the node, it is already in our list. If this is the case then
1555 // look up the entry rather than create a new entry
1556 // The check is to ensure the DV has been modified
1559 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1562 if( ParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
1565 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1566 AFS_TRACE_LEVEL_WARNING,
1567 "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",
1569 ParentObjectInfo->FileId.Cell,
1570 ParentObjectInfo->FileId.Volume,
1571 ParentObjectInfo->FileId.Vnode,
1572 ParentObjectInfo->FileId.Unique,
1573 ParentObjectInfo->DataVersion.QuadPart,
1574 pResultCB->ParentDataVersion.QuadPart);
1577 // We raced so go and lookup the directory entry in the parent
1580 ulCRC = AFSGenerateCRC( FileName,
1583 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1587 if( pDirNode != NULL)
1590 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1591 AFS_TRACE_LEVEL_VERBOSE,
1592 "AFSNotifyFileCreate Located dir entry %p for file %wZ\n",
1596 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
1597 &pResultCB->DirEnum.FileId))
1600 InterlockedIncrement( &pDirNode->OpenReferenceCount);
1602 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1603 AFS_TRACE_LEVEL_VERBOSE,
1604 "AFSNotifyFileCreate Increment count on %wZ DE %p Cnt %d\n",
1605 &pDirNode->NameInformation.FileName,
1607 pDirNode->OpenReferenceCount);
1609 *DirNode = pDirNode;
1611 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1613 try_return( ntStatus = STATUS_REPARSE);
1619 // We found an entry that matches the desired name but it is not the
1620 // same as the one that was created for us by the file server.
1623 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1624 AFS_TRACE_LEVEL_ERROR,
1625 "AFSNotifyFileCreate Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
1628 pDirNode->ObjectInformation->FileId.Cell,
1629 pDirNode->ObjectInformation->FileId.Volume,
1630 pDirNode->ObjectInformation->FileId.Vnode,
1631 pDirNode->ObjectInformation->FileId.Unique,
1632 pResultCB->DirEnum.FileId.Cell,
1633 pResultCB->DirEnum.FileId.Volume,
1634 pResultCB->DirEnum.FileId.Vnode,
1635 pResultCB->DirEnum.FileId.Unique);
1637 if( pDirNode->OpenReferenceCount == 0)
1640 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1641 AFS_TRACE_LEVEL_VERBOSE,
1642 "AFSNotifyFileCreate Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1644 &pDirNode->NameInformation.FileName,
1645 pDirNode->ObjectInformation->FileId.Cell,
1646 pDirNode->ObjectInformation->FileId.Volume,
1647 pDirNode->ObjectInformation->FileId.Vnode,
1648 pDirNode->ObjectInformation->FileId.Unique,
1649 pResultCB->DirEnum.FileId.Cell,
1650 pResultCB->DirEnum.FileId.Volume,
1651 pResultCB->DirEnum.FileId.Vnode,
1652 pResultCB->DirEnum.FileId.Unique);
1654 AFSDeleteDirEntry( ParentObjectInfo,
1660 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1662 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1663 AFS_TRACE_LEVEL_VERBOSE,
1664 "AFSNotifyFileCreate Different FIDs - Removing 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 AFSRemoveNameEntry( ParentObjectInfo,
1685 // We are unsure of our current data so set the verify flag. It may already be set
1686 // but no big deal to reset it
1689 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1691 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1697 // Update the parent data version
1700 ParentObjectInfo->DataVersion = pResultCB->ParentDataVersion;
1702 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1703 AFS_TRACE_LEVEL_VERBOSE,
1704 "AFSNotifyFileCreate entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
1706 ParentObjectInfo->FileId.Cell,
1707 ParentObjectInfo->FileId.Volume,
1708 ParentObjectInfo->FileId.Vnode,
1709 ParentObjectInfo->FileId.Unique,
1710 ParentObjectInfo->DataVersion.QuadPart);
1713 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1715 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1716 AFS_TRACE_LEVEL_VERBOSE,
1717 "AFSNotifyFileCreate Creating new entry %wZ\n",
1721 // Initialize the directory entry
1724 uniTargetName.Length = (USHORT)pResultCB->DirEnum.TargetNameLength;
1726 uniTargetName.MaximumLength = uniTargetName.Length;
1728 uniTargetName.Buffer = (WCHAR *)((char *)&pResultCB->DirEnum + pResultCB->DirEnum.TargetNameOffset);
1730 pDirNode = AFSInitDirEntry( ParentObjectInfo,
1733 &pResultCB->DirEnum,
1734 (ULONG)InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1736 if( pDirNode == NULL)
1739 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1743 // Init the short name if we have one
1746 if( pResultCB->DirEnum.ShortNameLength > 0)
1749 UNICODE_STRING uniShortName;
1751 pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
1753 RtlCopyMemory( pDirNode->NameInformation.ShortName,
1754 pResultCB->DirEnum.ShortName,
1755 pDirNode->NameInformation.ShortNameLength);
1758 // Generate the short name index
1761 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1762 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1764 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1767 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1768 AFS_TRACE_LEVEL_VERBOSE,
1769 "AFSNotifyFileCreate Initialized short name %wZ for DE %p for %wZ\n",
1772 &pDirNode->NameInformation.FileName);
1776 // Return the directory node
1779 *DirNode = pDirNode;
1783 if( pResultCB != NULL)
1786 AFSExFreePool( pResultCB);
1794 AFSUpdateFileInformation( IN AFSFileID *ParentFid,
1795 IN AFSObjectInfoCB *ObjectInfo,
1799 NTSTATUS ntStatus = STATUS_SUCCESS;
1800 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1801 AFSFileUpdateCB stUpdateCB;
1802 ULONG ulResultLen = 0;
1803 AFSFileUpdateResultCB *pUpdateResultCB = NULL;
1809 // Init the control block for the request
1812 RtlZeroMemory( &stUpdateCB,
1813 sizeof( AFSFileUpdateCB));
1815 stUpdateCB.AllocationSize = ObjectInfo->EndOfFile;
1817 stUpdateCB.FileAttributes = ObjectInfo->FileAttributes;
1819 stUpdateCB.EaSize = ObjectInfo->EaSize;
1821 stUpdateCB.ParentId = *ParentFid;
1823 stUpdateCB.LastAccessTime = ObjectInfo->LastAccessTime;
1825 stUpdateCB.CreateTime = ObjectInfo->CreationTime;
1827 stUpdateCB.ChangeTime = ObjectInfo->ChangeTime;
1829 stUpdateCB.LastWriteTime = ObjectInfo->LastWriteTime;
1831 pUpdateResultCB = (AFSFileUpdateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1833 AFS_UPDATE_RESULT_TAG);
1835 if( pUpdateResultCB == NULL)
1838 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1841 ulResultLen = PAGE_SIZE;
1843 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_UPDATE_FILE,
1844 AFS_REQUEST_FLAG_SYNCHRONOUS,
1847 &ObjectInfo->FileId,
1849 sizeof( AFSFileUpdateCB),
1853 if( ntStatus != STATUS_SUCCESS)
1856 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1857 AFS_TRACE_LEVEL_ERROR,
1858 "AFSUpdateFileInformation failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1859 ObjectInfo->FileId.Cell,
1860 ObjectInfo->FileId.Volume,
1861 ObjectInfo->FileId.Vnode,
1862 ObjectInfo->FileId.Unique,
1865 try_return( ntStatus);
1869 // Update the data version
1872 ObjectInfo->DataVersion = pUpdateResultCB->DirEnum.DataVersion;
1876 if( pUpdateResultCB != NULL)
1879 AFSExFreePool( pUpdateResultCB);
1887 AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
1889 IN BOOLEAN CheckOnly)
1891 NTSTATUS ntStatus = STATUS_SUCCESS;
1892 ULONG ulResultLen = 0;
1893 AFSFileDeleteCB stDelete;
1894 AFSFileDeleteResultCB stDeleteResult;
1895 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1900 stDelete.ParentId = DirectoryCB->ObjectInformation->ParentObjectInformation->FileId;
1902 stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
1904 ulResultLen = sizeof( AFSFileDeleteResultCB);
1908 ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
1911 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
1914 &DirectoryCB->NameInformation.FileName,
1915 &DirectoryCB->ObjectInformation->FileId,
1917 sizeof( AFSFileDeleteCB),
1921 if( ntStatus != STATUS_SUCCESS)
1924 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1925 AFS_TRACE_LEVEL_ERROR,
1926 "AFSNotifyDelete failed ParentFID %08lX-%08lX-%08lX-%08lX %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1927 stDelete.ParentId.Cell,
1928 stDelete.ParentId.Volume,
1929 stDelete.ParentId.Vnode,
1930 stDelete.ParentId.Unique,
1931 &DirectoryCB->NameInformation.FileName,
1932 DirectoryCB->ObjectInformation->FileId.Cell,
1933 DirectoryCB->ObjectInformation->FileId.Volume,
1934 DirectoryCB->ObjectInformation->FileId.Vnode,
1935 DirectoryCB->ObjectInformation->FileId.Unique,
1938 try_return( ntStatus);
1945 // Validate the parent data version
1948 if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
1951 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1953 DirectoryCB->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1960 // Update the parent data version
1963 if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart - 1)
1966 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1968 DirectoryCB->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1974 // TODO -- The entry must be removed from the directory at which point the
1975 // Directory data version number can be updated. Until then we must force
1978 // DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = stDeleteResult.ParentDataVersion.QuadPart;
1981 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1983 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1997 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
1999 IN AFSObjectInfoCB *ParentObjectInfo,
2000 IN AFSObjectInfoCB *TargetParentObjectInfo,
2001 IN AFSDirectoryCB *DirectoryCB,
2002 IN UNICODE_STRING *TargetName,
2003 OUT AFSFileID *UpdatedFID)
2006 NTSTATUS ntStatus = STATUS_SUCCESS;
2007 AFSFileRenameCB *pRenameCB = NULL;
2008 AFSFileRenameResultCB *pRenameResultCB = NULL;
2009 ULONG ulResultLen = 0;
2015 // Init the control block for the request
2018 pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
2020 AFS_RENAME_REQUEST_TAG);
2022 if( pRenameCB == NULL)
2025 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2028 RtlZeroMemory( pRenameCB,
2031 pRenameCB->SourceParentId = ParentObjectInfo->FileId;
2033 pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
2035 pRenameCB->TargetNameLength = TargetName->Length;
2037 RtlCopyMemory( pRenameCB->TargetName,
2039 TargetName->Length);
2042 // Use the same buffer for the result control block
2045 pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
2047 ulResultLen = PAGE_SIZE;
2049 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
2050 AFS_REQUEST_FLAG_SYNCHRONOUS,
2052 &DirectoryCB->NameInformation.FileName,
2053 &ObjectInfo->FileId,
2055 sizeof( AFSFileRenameCB) + TargetName->Length,
2059 if( ntStatus != STATUS_SUCCESS)
2062 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2063 AFS_TRACE_LEVEL_ERROR,
2064 "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2065 ObjectInfo->FileId.Cell,
2066 ObjectInfo->FileId.Volume,
2067 ObjectInfo->FileId.Vnode,
2068 ObjectInfo->FileId.Unique,
2071 try_return( ntStatus);
2075 // Update the information from the returned data
2078 if ( ParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->SourceParentDataVersion.QuadPart - 1)
2081 ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
2086 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2088 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2091 if ( TargetParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->TargetParentDataVersion.QuadPart - 1)
2094 TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
2099 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2101 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2105 // Move over the short name
2108 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2110 if( DirectoryCB->NameInformation.ShortNameLength > 0)
2113 UNICODE_STRING uniShortName;
2115 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2116 uniShortName.MaximumLength = uniShortName.Length;
2117 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2119 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2120 AFS_TRACE_LEVEL_VERBOSE,
2121 "AFSNotifyRename Update old short name %wZ for DE %p for %wZ\n",
2124 &DirectoryCB->NameInformation.FileName);
2126 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2128 RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
2129 pRenameResultCB->DirEnum.ShortName,
2130 DirectoryCB->NameInformation.ShortNameLength);
2132 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2133 uniShortName.MaximumLength = uniShortName.Length;
2134 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2136 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2137 AFS_TRACE_LEVEL_VERBOSE,
2138 "AFSNotifyRename Initialized short name %wZ for DE %p for %wZ\n",
2141 &DirectoryCB->NameInformation.FileName);
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 Removing old short name %wZ for DE %p for %wZ\n",
2157 &DirectoryCB->NameInformation.FileName);
2159 DirectoryCB->NameInformation.ShortNameLength = 0;
2161 DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2164 if( UpdatedFID != NULL)
2166 *UpdatedFID = pRenameResultCB->DirEnum.FileId;
2171 if( pRenameCB != NULL)
2174 AFSExFreePool( pRenameCB);
2182 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
2184 IN BOOLEAN FastCall,
2185 OUT AFSDirEnumEntry **DirEnumEntry)
2188 NTSTATUS ntStatus = STATUS_SUCCESS;
2189 AFSEvalTargetCB stTargetID;
2190 ULONG ulResultBufferLength;
2191 AFSFileEvalResultCB *pEvalResultCB = NULL;
2192 AFSDirEnumEntry *pDirEnumCB = NULL;
2193 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
2198 RtlZeroMemory( &stTargetID,
2199 sizeof( AFSEvalTargetCB));
2201 if( ObjectInfo->ParentObjectInformation != NULL)
2204 stTargetID.ParentId = ObjectInfo->ParentObjectInformation->FileId;
2208 // Allocate our response buffer
2211 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2213 AFS_GENERIC_MEMORY_30_TAG);
2215 if( pEvalResultCB == NULL)
2218 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2222 // Call to the service to evaluate the fid
2225 ulResultBufferLength = PAGE_SIZE;
2230 ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
2233 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
2237 &ObjectInfo->FileId,
2239 sizeof( AFSEvalTargetCB),
2241 &ulResultBufferLength);
2243 if( ntStatus != STATUS_SUCCESS)
2247 // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
2251 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2254 if( ObjectInfo->ParentObjectInformation != NULL)
2257 SetFlag( ObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
2259 ObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
2263 try_return( ntStatus);
2267 // Validate the parent data version
2270 if ( ObjectInfo->ParentObjectInformation != NULL &&
2271 ObjectInfo->ParentObjectInformation->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2274 SetFlag( ObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
2276 ObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
2280 // Pass back the dir enum entry
2283 if( DirEnumEntry != NULL)
2286 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2288 AFS_GENERIC_MEMORY_2_TAG);
2290 if( pDirEnumCB == NULL)
2293 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2296 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2297 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2299 *DirEnumEntry = pDirEnumCB;
2304 if( pEvalResultCB != NULL)
2307 AFSExFreePool( pEvalResultCB);
2310 if( !NT_SUCCESS( ntStatus))
2313 if( pDirEnumCB != NULL)
2316 AFSExFreePool( pDirEnumCB);
2319 *DirEnumEntry = NULL;
2327 AFSEvaluateTargetByName( IN GUID *AuthGroup,
2328 IN AFSObjectInfoCB *ParentObjectInfo,
2329 IN PUNICODE_STRING SourceName,
2330 OUT AFSDirEnumEntry **DirEnumEntry)
2333 NTSTATUS ntStatus = STATUS_SUCCESS;
2334 AFSEvalTargetCB stTargetID;
2335 ULONG ulResultBufferLength;
2336 AFSFileEvalResultCB *pEvalResultCB = NULL;
2337 AFSDirEnumEntry *pDirEnumCB = NULL;
2342 stTargetID.ParentId = ParentObjectInfo->FileId;
2345 // Allocate our response buffer
2348 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2350 AFS_GENERIC_MEMORY_31_TAG);
2352 if( pEvalResultCB == NULL)
2355 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2359 // Call to the service to evaluate the fid
2362 ulResultBufferLength = PAGE_SIZE;
2364 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
2365 AFS_REQUEST_FLAG_SYNCHRONOUS,
2370 sizeof( AFSEvalTargetCB),
2372 &ulResultBufferLength);
2374 if( ntStatus != STATUS_SUCCESS)
2377 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2380 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2382 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2385 try_return( ntStatus);
2389 // Validate the parent data version
2392 if ( ParentObjectInfo != NULL &&
2393 ParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2396 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2398 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2402 // Pass back the dir enum entry
2405 if( DirEnumEntry != NULL)
2408 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2410 AFS_GENERIC_MEMORY_3_TAG);
2412 if( pDirEnumCB == NULL)
2415 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2418 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2419 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2421 *DirEnumEntry = pDirEnumCB;
2426 if( pEvalResultCB != NULL)
2429 AFSExFreePool( pEvalResultCB);
2432 if( !NT_SUCCESS( ntStatus))
2435 if( pDirEnumCB != NULL)
2438 AFSExFreePool( pDirEnumCB);
2441 *DirEnumEntry = NULL;
2449 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
2450 IN AFSFileID *FileID,
2451 OUT AFSVolumeInfoCB *VolumeInformation)
2454 NTSTATUS ntStatus = STATUS_SUCCESS;
2455 ULONG ulResultLen = 0;
2460 ulResultLen = sizeof( AFSVolumeInfoCB);
2462 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
2463 AFS_REQUEST_FLAG_SYNCHRONOUS,
2472 if( ntStatus != STATUS_SUCCESS)
2475 try_return( ntStatus);
2487 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
2488 IN ULONG InputLength,
2489 IN ULONG OutputLength,
2490 IN void *InputDataBuffer,
2491 OUT void *OutputDataBuffer,
2492 OUT ULONG *BytesReturned)
2495 NTSTATUS ntStatus = STATUS_SUCCESS;
2496 ULONG ulResultLen = 0;
2497 MDL *pInputMdl = NULL, *pOutputMdl = NULL;
2498 void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
2499 ULONG ulBufferLength = OutputLength;
2500 AFSPipeIORequestCB *pIoRequest = NULL;
2506 // Map the user buffer to a system address
2509 pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
2513 if( pInputSystemBuffer == NULL)
2516 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2519 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2520 sizeof( AFSPipeIORequestCB) +
2522 AFS_GENERIC_MEMORY_4_TAG);
2524 if( pIoRequest == NULL)
2527 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2530 RtlZeroMemory( pIoRequest,
2531 sizeof( AFSPipeIORequestCB) + InputLength);
2533 pIoRequest->RequestId = Ccb->RequestID;
2535 pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2537 pIoRequest->BufferLength = InputLength;
2539 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
2543 pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
2547 if( pOutputSystemBuffer == NULL)
2550 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2554 // Send the call to the service
2557 ulResultLen = OutputLength;
2559 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
2560 AFS_REQUEST_FLAG_SYNCHRONOUS,
2562 &Ccb->DirectoryCB->NameInformation.FileName,
2565 sizeof( AFSPipeIORequestCB) + InputLength,
2566 pOutputSystemBuffer,
2569 if( ntStatus != STATUS_SUCCESS &&
2570 ntStatus != STATUS_BUFFER_OVERFLOW)
2573 if( NT_SUCCESS( ntStatus))
2576 ntStatus = STATUS_DEVICE_NOT_READY;
2579 try_return( ntStatus);
2583 // Return the bytes processed
2586 *BytesReturned = ulResultLen;
2590 if( pInputMdl != NULL)
2593 MmUnlockPages( pInputMdl);
2595 IoFreeMdl( pInputMdl);
2598 if( pOutputMdl != NULL)
2601 MmUnlockPages( pOutputMdl);
2603 IoFreeMdl( pOutputMdl);
2606 if( pIoRequest != NULL)
2609 AFSExFreePool( pIoRequest);
2617 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
2618 IN ULONG InformationClass,
2619 IN ULONG InputLength,
2620 IN void *DataBuffer)
2623 NTSTATUS ntStatus = STATUS_SUCCESS;
2624 AFSPipeInfoRequestCB *pInfoRequest = NULL;
2629 pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2630 sizeof( AFSPipeInfoRequestCB) +
2632 AFS_GENERIC_MEMORY_5_TAG);
2634 if( pInfoRequest == NULL)
2637 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2640 RtlZeroMemory( pInfoRequest,
2641 sizeof( AFSPipeInfoRequestCB) + InputLength);
2643 pInfoRequest->RequestId = Ccb->RequestID;
2645 pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2647 pInfoRequest->BufferLength = InputLength;
2649 pInfoRequest->InformationClass = InformationClass;
2651 RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
2656 // Send the call to the service
2659 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
2660 AFS_REQUEST_FLAG_SYNCHRONOUS,
2662 &Ccb->DirectoryCB->NameInformation.FileName,
2665 sizeof( AFSPipeInfoRequestCB) + InputLength,
2669 if( ntStatus != STATUS_SUCCESS)
2672 if( NT_SUCCESS( ntStatus))
2675 ntStatus = STATUS_DEVICE_NOT_READY;
2678 try_return( ntStatus);
2683 if( pInfoRequest != NULL)
2686 AFSExFreePool( pInfoRequest);
2694 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
2695 IN ULONG InformationClass,
2696 IN ULONG OutputLength,
2697 IN void *DataBuffer,
2698 OUT ULONG *BytesReturned)
2701 NTSTATUS ntStatus = STATUS_SUCCESS;
2702 AFSPipeInfoRequestCB stInfoRequest;
2703 ULONG ulBytesProcessed = 0;
2708 RtlZeroMemory( &stInfoRequest,
2709 sizeof( AFSPipeInfoRequestCB));
2711 stInfoRequest.RequestId = Ccb->RequestID;
2713 stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2715 stInfoRequest.BufferLength = OutputLength;
2717 stInfoRequest.InformationClass = InformationClass;
2719 ulBytesProcessed = OutputLength;
2722 // Send the call to the service
2725 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
2726 AFS_REQUEST_FLAG_SYNCHRONOUS,
2728 &Ccb->DirectoryCB->NameInformation.FileName,
2731 sizeof( AFSPipeInfoRequestCB),
2735 if( ntStatus != STATUS_SUCCESS)
2738 if( NT_SUCCESS( ntStatus))
2741 ntStatus = STATUS_DEVICE_NOT_READY;
2744 try_return( ntStatus);
2747 *BytesReturned = ulBytesProcessed;
2758 AFSReleaseFid( IN AFSFileID *FileId)
2761 NTSTATUS ntStatus = STATUS_SUCCESS;
2766 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
2781 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
2782 IN LARGE_INTEGER *ExtentOffset,
2786 BOOLEAN bRequestQueued = FALSE;
2787 NTSTATUS ntStatus = STATUS_SUCCESS;
2788 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2789 AFSCommSrvcCB *pCommSrvc = NULL;
2790 AFSPoolEntry *pPoolEntry = NULL;
2791 AFSRequestExtentsCB *pRequestExtents = NULL;
2797 pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
2799 AFSAcquireShared( &pCommSrvc->IrpPoolLock,
2802 pPoolEntry = pCommSrvc->RequestPoolHead;
2804 while( pPoolEntry != NULL)
2807 if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
2810 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
2813 pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
2815 if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
2816 pRequestExtents->Length == Length)
2819 bRequestQueued = TRUE;
2824 pPoolEntry = pPoolEntry->fLink;
2827 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
2830 return bRequestQueued;