2 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011, 2012, 2013 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
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
16 * nor the names of their contributors may be used to endorse or promote
17 * products derived from this software without specific prior written
18 * permission from Kernel Drivers, LLC and Your File System, Inc.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
24 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 // File: AFSCommSupport.cpp
37 #include "AFSCommon.h"
40 AFSEnumerateDirectory( IN GUID *AuthGroup,
41 IN AFSObjectInfoCB *ObjectInfoCB,
45 NTSTATUS ntStatus = STATUS_SUCCESS;
47 ULONG ulResultLen = 0;
48 AFSDirQueryCB *pDirQueryCB;
49 AFSDirEnumEntry *pCurrentDirEntry = NULL;
50 AFSDirectoryCB *pDirNode = NULL;
51 ULONG ulEntryLength = 0;
52 AFSDirEnumResp *pDirEnumResponse = NULL;
53 UNICODE_STRING uniDirName, uniTargetName;
54 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
56 UNICODE_STRING uniGUID;
57 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
62 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
64 if( BooleanFlagOn( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
67 try_return( ntStatus = STATUS_SUCCESS);
71 uniGUID.MaximumLength = 0;
72 uniGUID.Buffer = NULL;
74 if( AuthGroup != NULL)
76 RtlStringFromGUID( *AuthGroup,
80 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
81 AFS_TRACE_LEVEL_VERBOSE,
82 "AFSEnumerateDirectory Enumerating FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
83 ObjectInfoCB->FileId.Cell,
84 ObjectInfoCB->FileId.Volume,
85 ObjectInfoCB->FileId.Vnode,
86 ObjectInfoCB->FileId.Unique,
89 if( AuthGroup != NULL)
91 RtlFreeUnicodeString( &uniGUID);
95 // Initialize the directory enumeration buffer for the directory
98 pBuffer = AFSLibExAllocatePoolWithTag( PagedPool,
99 AFS_DIR_ENUM_BUFFER_LEN,
105 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
108 RtlZeroMemory( pBuffer,
109 AFS_DIR_ENUM_BUFFER_LEN);
111 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
114 // Use the payload buffer for information we will pass to the service
117 pDirQueryCB = (AFSDirQueryCB *)pBuffer;
119 pDirQueryCB->EnumHandle = 0;
124 ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
128 // Loop on the information
135 // If the enumeration handle is -1 then we are done
138 if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
141 ntStatus = STATUS_NO_MORE_ENTRIES;
147 // Go and retrieve the directory contents
150 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
154 &ObjectInfoCB->FileId,
155 ObjectInfoCB->VolumeCB->VolumeInformation.Cell,
156 ObjectInfoCB->VolumeCB->VolumeInformation.CellLength,
158 sizeof( AFSDirQueryCB),
163 if( ntStatus != STATUS_SUCCESS ||
167 if( ntStatus == STATUS_NO_MORE_FILES ||
168 ntStatus == STATUS_NO_MORE_ENTRIES)
171 ntStatus = STATUS_SUCCESS;
173 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
175 AFSAcquireExcl( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock,
178 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
179 AFS_TRACE_LEVEL_VERBOSE,
180 "AFSEnumerateDirectory Directory Complete FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX Status %08lX\n",
181 ObjectInfoCB->FileId.Cell,
182 ObjectInfoCB->FileId.Volume,
183 ObjectInfoCB->FileId.Vnode,
184 ObjectInfoCB->FileId.Unique,
185 pDirEnumResponse->SnapshotDataVersion.HighPart,
186 pDirEnumResponse->SnapshotDataVersion.LowPart,
187 pDirEnumResponse->CurrentDataVersion.HighPart,
188 pDirEnumResponse->CurrentDataVersion.LowPart,
191 ObjectInfoCB->DataVersion = pDirEnumResponse->SnapshotDataVersion;
193 if ( pDirEnumResponse->SnapshotDataVersion.QuadPart != pDirEnumResponse->CurrentDataVersion.QuadPart )
196 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
198 ObjectInfoCB->DataVersion.QuadPart = (ULONGLONG)-1;
200 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
201 AFS_TRACE_LEVEL_VERBOSE,
202 "AFSEnumerateDirectory Force Verify due to DV change during enumeration FID %08lX-%08lX-%08lX-%08lX\n",
203 ObjectInfoCB->FileId.Cell,
204 ObjectInfoCB->FileId.Volume,
205 ObjectInfoCB->FileId.Vnode,
206 ObjectInfoCB->FileId.Unique));
209 AFSReleaseResource( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock);
214 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
215 AFS_TRACE_LEVEL_VERBOSE,
216 "AFSEnumerateDirectory Failed to enumerate directory FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ Status %08lX\n",
217 ObjectInfoCB->FileId.Cell,
218 ObjectInfoCB->FileId.Volume,
219 ObjectInfoCB->FileId.Vnode,
220 ObjectInfoCB->FileId.Unique,
228 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
230 pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
232 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
233 AFS_TRACE_LEVEL_VERBOSE,
234 "AFSEnumerateDirectory Enumerating FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX\n",
235 ObjectInfoCB->FileId.Cell,
236 ObjectInfoCB->FileId.Volume,
237 ObjectInfoCB->FileId.Vnode,
238 ObjectInfoCB->FileId.Unique,
239 pDirEnumResponse->SnapshotDataVersion.HighPart,
240 pDirEnumResponse->SnapshotDataVersion.LowPart,
241 pDirEnumResponse->CurrentDataVersion.HighPart,
242 pDirEnumResponse->CurrentDataVersion.LowPart));
245 // Remove the leading header from the processed length
248 ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
250 while( ulResultLen > 0)
253 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
255 uniDirName.MaximumLength = uniDirName.Length;
257 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
259 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
261 uniTargetName.MaximumLength = uniTargetName.Length;
263 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
266 // Be sure we don't have this entry in the case sensitive tree
269 ulCRC = AFSGenerateCRC( &uniDirName,
272 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
276 if( pDirNode != NULL)
280 // Check that the FIDs are the same
283 if( AFSIsEqualFID( &pCurrentDirEntry->FileId,
284 &pDirNode->ObjectInformation->FileId))
288 // Duplicate entry, skip it
291 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
293 uniTargetName.Length);
295 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
297 if( ulResultLen >= ulEntryLength)
299 ulResultLen -= ulEntryLength;
307 // Update the metadata for the entry
310 if( pDirNode->ObjectInformation->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
313 AFSUpdateMetaData( pDirNode,
323 // Need to tear down this entry and rebuild it below
326 if( pDirNode->DirOpenReferenceCount <= 0 &&
327 pDirNode->NameArrayReferenceCount <= 0)
330 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
331 AFS_TRACE_LEVEL_VERBOSE,
332 "AFSEnumerateDirectory Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
334 &pDirNode->NameInformation.FileName,
335 pDirNode->ObjectInformation->FileId.Cell,
336 pDirNode->ObjectInformation->FileId.Volume,
337 pDirNode->ObjectInformation->FileId.Vnode,
338 pDirNode->ObjectInformation->FileId.Unique,
339 pCurrentDirEntry->FileId.Cell,
340 pCurrentDirEntry->FileId.Volume,
341 pCurrentDirEntry->FileId.Vnode,
342 pCurrentDirEntry->FileId.Unique));
344 AFSDeleteDirEntry( ObjectInfoCB,
350 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
352 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
353 AFS_TRACE_LEVEL_VERBOSE,
354 "AFSEnumerateDirectory Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
356 &pDirNode->NameInformation.FileName,
357 pDirNode->ObjectInformation->FileId.Cell,
358 pDirNode->ObjectInformation->FileId.Volume,
359 pDirNode->ObjectInformation->FileId.Vnode,
360 pDirNode->ObjectInformation->FileId.Unique,
361 pCurrentDirEntry->FileId.Cell,
362 pCurrentDirEntry->FileId.Volume,
363 pCurrentDirEntry->FileId.Vnode,
364 pCurrentDirEntry->FileId.Unique));
366 AFSRemoveNameEntry( ObjectInfoCB,
374 pDirNode = AFSInitDirEntry( ObjectInfoCB,
378 (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
380 if( pDirNode == NULL)
383 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
388 AFSUpdateMetaData( pDirNode,
391 if( pDirNode->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
394 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
395 AFS_TRACE_LEVEL_VERBOSE,
396 "AFSEnumerateDirectory Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
398 pDirNode->ObjectInformation->FileId.Cell,
399 pDirNode->ObjectInformation->FileId.Volume,
400 pDirNode->ObjectInformation->FileId.Vnode,
401 pDirNode->ObjectInformation->FileId.Unique));
403 AFSAcquireExcl( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
406 SetFlag( pDirNode->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
408 pDirNode->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
410 AFSReleaseResource( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
414 // Set up the entry length
417 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
418 pCurrentDirEntry->FileNameLength +
419 pCurrentDirEntry->TargetNameLength);
422 // Init the short name if we have one
425 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
426 pCurrentDirEntry->ShortNameLength > 0)
429 UNICODE_STRING uniShortName;
431 pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
433 RtlCopyMemory( pDirNode->NameInformation.ShortName,
434 pCurrentDirEntry->ShortName,
435 pDirNode->NameInformation.ShortNameLength);
438 // Generate the short name index
441 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
442 uniShortName.MaximumLength = uniShortName.Length;
443 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
445 if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
450 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
453 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
454 AFS_TRACE_LEVEL_VERBOSE,
455 "AFSEnumerateDirectory Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
458 &pDirNode->NameInformation.FileName,
459 pCurrentDirEntry->FileId.Cell,
460 pCurrentDirEntry->FileId.Volume,
461 pCurrentDirEntry->FileId.Vnode,
462 pCurrentDirEntry->FileId.Unique));
466 pDirNode->NameInformation.ShortNameLength = 0;
468 RtlZeroMemory( pDirNode->NameInformation.ShortName,
469 (12 * sizeof( WCHAR)));
476 // No short name or short names are disabled
479 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
483 // Insert the node into the name tree
486 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
489 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
491 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
492 AFS_TRACE_LEVEL_VERBOSE,
493 "AFSEnumerateDirectory Insert DE %p to head of case sensitive tree for %wZ\n",
495 &pDirNode->NameInformation.FileName));
500 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
501 AFS_TRACE_LEVEL_VERBOSE,
502 "AFSEnumerateDirectory Insert DE %p to case sensitive tree for %wZ\n",
504 &pDirNode->NameInformation.FileName));
506 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
511 // Delete this dir entry and continue on
514 AFSDeleteDirEntry( ObjectInfoCB,
517 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
519 if( ulResultLen >= ulEntryLength)
521 ulResultLen -= ulEntryLength;
532 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
534 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
537 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
538 AFS_TRACE_LEVEL_VERBOSE,
539 "AFSEnumerateDirectory Insert DE %p to head of case insensitive tree for %wZ\n",
541 &pDirNode->NameInformation.FileName));
543 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
545 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
550 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
551 AFS_TRACE_LEVEL_VERBOSE,
552 "AFSEnumerateDirectory Insert DE %p to case insensitive tree for %wZ\n",
554 &pDirNode->NameInformation.FileName));
556 AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
560 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
563 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
568 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
570 pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
573 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
575 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
577 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
579 AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
580 AFS_TRACE_LEVEL_VERBOSE,
581 "AFSEnumerateDirectory Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
582 &pDirNode->NameInformation.FileName,
583 ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
584 ObjectInfoCB->FileId.Cell,
585 ObjectInfoCB->FileId.Volume,
586 ObjectInfoCB->FileId.Vnode,
587 ObjectInfoCB->FileId.Unique));
589 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
593 // Insert the short name entry if we have a valid short name
596 if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
599 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
600 AFS_TRACE_LEVEL_VERBOSE,
601 "AFSEnumerateDirectory Insert DE %p to head of shortname tree for %wZ\n",
603 &pDirNode->NameInformation.FileName));
605 ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
607 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
612 if( NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
615 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
617 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
618 AFS_TRACE_LEVEL_VERBOSE,
619 "AFSEnumerateDirectory Insert DE %p to shortname tree for %wZ\n",
621 &pDirNode->NameInformation.FileName));
630 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
632 if( ulResultLen >= ulEntryLength)
634 ulResultLen -= ulEntryLength;
642 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
645 // Reset the information in the request buffer since it got trampled
649 pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
651 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
652 AFS_TRACE_LEVEL_VERBOSE,
653 "AFSEnumerateDirectory EnumHandle %08lX\n",
654 pDirQueryCB->EnumHandle));
666 AFSExFreePoolWithTag( pBuffer, AFS_DIR_BUFFER_TAG);
669 if ( NT_SUCCESS( ntStatus))
672 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
678 // If the processing failed then we should reset the directory
679 // content in the event it is re-enumerated
682 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
683 AFS_TRACE_LEVEL_ERROR,
684 "AFSEnumerateDirectory Resetting content for FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
685 ObjectInfoCB->FileId.Cell,
686 ObjectInfoCB->FileId.Volume,
687 ObjectInfoCB->FileId.Vnode,
688 ObjectInfoCB->FileId.Unique,
691 AFSResetDirectoryContent( ObjectInfoCB);
699 AFSEnumerateDirectoryNoResponse( IN GUID *AuthGroup,
700 IN AFSFileID *FileId)
703 NTSTATUS ntStatus = STATUS_SUCCESS;
704 AFSDirQueryCB stDirQueryCB;
705 ULONG ulRequestFlags = 0;
711 // Use the payload buffer for information we will pass to the service
714 stDirQueryCB.EnumHandle = 0;
716 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
723 (void *)&stDirQueryCB,
724 sizeof( AFSDirQueryCB),
728 if( ntStatus != STATUS_SUCCESS)
731 if( ntStatus == STATUS_NO_MORE_FILES ||
732 ntStatus == STATUS_NO_MORE_ENTRIES)
735 ntStatus = STATUS_SUCCESS;
740 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
741 AFS_TRACE_LEVEL_ERROR,
742 "AFSEnumerateDirectoryNoResponse Failed to enumerate directory Status %08lX\n",
752 AFSVerifyDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB,
756 NTSTATUS ntStatus = STATUS_SUCCESS;
757 void *pBuffer = NULL;
758 ULONG ulResultLen = 0;
759 AFSDirQueryCB *pDirQueryCB;
760 AFSDirEnumEntry *pCurrentDirEntry = NULL;
761 AFSDirectoryCB *pDirNode = NULL;
762 ULONG ulEntryLength = 0;
763 AFSDirEnumResp *pDirEnumResponse = NULL;
764 UNICODE_STRING uniDirName, uniTargetName;
765 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_FAST_REQUEST;
767 AFSObjectInfoCB *pObjectInfo = NULL;
768 ULONGLONG ullIndex = 0;
769 UNICODE_STRING uniGUID;
771 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
776 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
779 uniGUID.MaximumLength = 0;
780 uniGUID.Buffer = NULL;
782 if( AuthGroup != NULL)
784 RtlStringFromGUID( *AuthGroup,
788 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
789 AFS_TRACE_LEVEL_VERBOSE,
790 "AFSVerifyDirectoryContent Verifying content for FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
791 ObjectInfoCB->FileId.Cell,
792 ObjectInfoCB->FileId.Volume,
793 ObjectInfoCB->FileId.Vnode,
794 ObjectInfoCB->FileId.Unique,
797 if( AuthGroup != NULL)
799 RtlFreeUnicodeString( &uniGUID);
803 // Initialize the directory enumeration buffer for the directory
806 pBuffer = AFSLibExAllocatePoolWithTag( PagedPool,
807 AFS_DIR_ENUM_BUFFER_LEN,
813 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
816 RtlZeroMemory( pBuffer,
817 AFS_DIR_ENUM_BUFFER_LEN);
819 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
822 // Use the payload buffer for information we will pass to the service
825 pDirQueryCB = (AFSDirQueryCB *)pBuffer;
827 pDirQueryCB->EnumHandle = 0;
830 // Loop on the information
837 // If the enumeration handle is -1 then we are done
840 if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
843 ntStatus = STATUS_NO_MORE_ENTRIES;
849 // Go and retrieve the directory contents
852 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
856 &ObjectInfoCB->FileId,
857 ObjectInfoCB->VolumeCB->VolumeInformation.Cell,
858 ObjectInfoCB->VolumeCB->VolumeInformation.CellLength,
860 sizeof( AFSDirQueryCB),
865 if( ntStatus != STATUS_SUCCESS ||
869 if( ntStatus == STATUS_NO_MORE_FILES ||
870 ntStatus == STATUS_NO_MORE_ENTRIES)
873 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
875 AFSAcquireExcl( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock,
878 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
879 AFS_TRACE_LEVEL_VERBOSE,
880 "AFSVerifyDirectoryContent Directory Complete FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX Status %08lX\n",
881 ObjectInfoCB->FileId.Cell,
882 ObjectInfoCB->FileId.Volume,
883 ObjectInfoCB->FileId.Vnode,
884 ObjectInfoCB->FileId.Unique,
885 pDirEnumResponse->SnapshotDataVersion.HighPart,
886 pDirEnumResponse->SnapshotDataVersion.LowPart,
887 pDirEnumResponse->CurrentDataVersion.HighPart,
888 pDirEnumResponse->CurrentDataVersion.LowPart,
891 ntStatus = STATUS_SUCCESS;
893 if ( pDirEnumResponse->SnapshotDataVersion.QuadPart != pDirEnumResponse->CurrentDataVersion.QuadPart )
896 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
898 ObjectInfoCB->DataVersion.QuadPart = (ULONGLONG)-1;
900 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
901 AFS_TRACE_LEVEL_VERBOSE,
902 "AFSVerifyDirectoryContent Force Verify due to DV change during enumeration FID %08lX-%08lX-%08lX-%08lX\n",
903 ObjectInfoCB->FileId.Cell,
904 ObjectInfoCB->FileId.Volume,
905 ObjectInfoCB->FileId.Vnode,
906 ObjectInfoCB->FileId.Unique));
911 ObjectInfoCB->DataVersion = pDirEnumResponse->SnapshotDataVersion;
914 AFSReleaseResource( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock);
919 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
920 AFS_TRACE_LEVEL_ERROR,
921 "AFSVerifyDirectoryContent Failed to enumerate directory FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ Status %08lX\n",
922 ObjectInfoCB->FileId.Cell,
923 ObjectInfoCB->FileId.Volume,
924 ObjectInfoCB->FileId.Vnode,
925 ObjectInfoCB->FileId.Unique,
933 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
935 pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
937 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
938 AFS_TRACE_LEVEL_VERBOSE,
939 "AFSVerifyDirectoryContent EnumResponse FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX\n",
940 ObjectInfoCB->FileId.Cell,
941 ObjectInfoCB->FileId.Volume,
942 ObjectInfoCB->FileId.Vnode,
943 ObjectInfoCB->FileId.Unique,
944 pDirEnumResponse->SnapshotDataVersion.HighPart,
945 pDirEnumResponse->SnapshotDataVersion.LowPart,
946 pDirEnumResponse->CurrentDataVersion.HighPart,
947 pDirEnumResponse->CurrentDataVersion.LowPart));
950 // Remove the leading header from the processed length
953 ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
955 while( ulResultLen > 0)
958 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
960 uniDirName.MaximumLength = uniDirName.Length;
962 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
964 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
966 uniTargetName.MaximumLength = uniTargetName.Length;
968 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
971 // Does this entry already exist in the directory?
974 ulCRC = AFSGenerateCRC( &uniDirName,
977 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
983 // Set up the entry length
986 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
987 pCurrentDirEntry->FileNameLength +
988 pCurrentDirEntry->TargetNameLength);
991 AFSIsEqualFID( &pCurrentDirEntry->FileId,
992 &pDirNode->ObjectInformation->FileId))
996 // Found matching directory entry by name and FileID
999 AFSAcquireShared( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock,
1002 ullIndex = AFSCreateLowIndex( &pCurrentDirEntry->FileId);
1004 ntStatus = AFSLocateHashEntry( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeHead,
1006 (AFSBTreeEntry **)&pObjectInfo);
1008 AFSReleaseResource( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock);
1010 if( NT_SUCCESS( ntStatus) &&
1011 pObjectInfo != NULL)
1015 // Indicate this is a valid entry
1018 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
1020 KeQueryTickCount( &ObjectInfoCB->LastAccessCount);
1022 if( pCurrentDirEntry->ShortNameLength > 0 &&
1023 pDirNode->NameInformation.ShortNameLength > 0)
1025 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1026 AFS_TRACE_LEVEL_VERBOSE,
1027 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name %S New short name %S\n",
1029 &pDirNode->NameInformation.FileName,
1030 ObjectInfoCB->FileId.Cell,
1031 ObjectInfoCB->FileId.Volume,
1032 ObjectInfoCB->FileId.Vnode,
1033 ObjectInfoCB->FileId.Unique,
1034 pDirNode->NameInformation.ShortName,
1035 pCurrentDirEntry->ShortName));
1037 else if( pCurrentDirEntry->ShortNameLength == 0 &&
1038 pDirNode->NameInformation.ShortNameLength > 0)
1041 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1042 AFS_TRACE_LEVEL_VERBOSE,
1043 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name %S New short name NULL\n",
1045 &pDirNode->NameInformation.FileName,
1046 ObjectInfoCB->FileId.Cell,
1047 ObjectInfoCB->FileId.Volume,
1048 ObjectInfoCB->FileId.Vnode,
1049 ObjectInfoCB->FileId.Unique,
1050 pDirNode->NameInformation.ShortName));
1052 else if( pCurrentDirEntry->ShortNameLength > 0 &&
1053 pDirNode->NameInformation.ShortNameLength == 0)
1055 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1056 AFS_TRACE_LEVEL_VERBOSE,
1057 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name %S\n",
1059 &pDirNode->NameInformation.FileName,
1060 ObjectInfoCB->FileId.Cell,
1061 ObjectInfoCB->FileId.Volume,
1062 ObjectInfoCB->FileId.Vnode,
1063 ObjectInfoCB->FileId.Unique,
1064 pCurrentDirEntry->ShortName));
1068 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1069 AFS_TRACE_LEVEL_VERBOSE,
1070 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name NULL\n",
1072 &pDirNode->NameInformation.FileName,
1073 ObjectInfoCB->FileId.Cell,
1074 ObjectInfoCB->FileId.Volume,
1075 ObjectInfoCB->FileId.Vnode,
1076 ObjectInfoCB->FileId.Unique));
1080 // Update the metadata for the entry
1083 if( pObjectInfo->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
1086 AFSUpdateMetaData( pDirNode,
1094 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1096 if( ulResultLen >= ulEntryLength)
1098 ulResultLen -= ulEntryLength;
1112 // File name matches but FileID does not.
1115 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1116 AFS_TRACE_LEVEL_VERBOSE,
1117 "AFSVerifyDirectoryContent Processing dir entry %p %wZ with different FID, same name in parent FID %08lX-%08lX-%08lX-%08lX\n",
1119 &pDirNode->NameInformation.FileName,
1120 ObjectInfoCB->FileId.Cell,
1121 ObjectInfoCB->FileId.Volume,
1122 ObjectInfoCB->FileId.Vnode,
1123 ObjectInfoCB->FileId.Unique));
1126 // Need to tear down this entry and rebuild it below
1129 if( pDirNode->DirOpenReferenceCount <= 0 &&
1130 pDirNode->NameArrayReferenceCount <= 0)
1133 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1134 AFS_TRACE_LEVEL_VERBOSE,
1135 "AFSVerifyDirectoryContent Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1137 &pDirNode->NameInformation.FileName,
1138 pDirNode->ObjectInformation->FileId.Cell,
1139 pDirNode->ObjectInformation->FileId.Volume,
1140 pDirNode->ObjectInformation->FileId.Vnode,
1141 pDirNode->ObjectInformation->FileId.Unique,
1142 pCurrentDirEntry->FileId.Cell,
1143 pCurrentDirEntry->FileId.Volume,
1144 pCurrentDirEntry->FileId.Vnode,
1145 pCurrentDirEntry->FileId.Unique));
1147 AFSDeleteDirEntry( ObjectInfoCB,
1153 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1155 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1156 AFS_TRACE_LEVEL_WARNING,
1157 "AFSVerifyDirectoryContent Different FIDs - removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1159 &pDirNode->NameInformation.FileName,
1160 pDirNode->ObjectInformation->FileId.Cell,
1161 pDirNode->ObjectInformation->FileId.Volume,
1162 pDirNode->ObjectInformation->FileId.Vnode,
1163 pDirNode->ObjectInformation->FileId.Unique,
1164 pCurrentDirEntry->FileId.Cell,
1165 pCurrentDirEntry->FileId.Volume,
1166 pCurrentDirEntry->FileId.Vnode,
1167 pCurrentDirEntry->FileId.Unique));
1169 AFSRemoveNameEntry( ObjectInfoCB,
1176 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1177 AFS_TRACE_LEVEL_VERBOSE,
1178 "AFSVerifyDirectoryContent New entry %wZ for parent FID %08lX-%08lX-%08lX-%08lX\n",
1180 ObjectInfoCB->FileId.Cell,
1181 ObjectInfoCB->FileId.Volume,
1182 ObjectInfoCB->FileId.Vnode,
1183 ObjectInfoCB->FileId.Unique));
1186 pDirNode = AFSInitDirEntry( ObjectInfoCB,
1190 (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1192 if( pDirNode == NULL)
1195 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
1200 AFSUpdateMetaData( pDirNode,
1203 if( pDirNode->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1206 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1207 AFS_TRACE_LEVEL_VERBOSE,
1208 "AFSVerifyDirectoryContent Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
1210 pDirNode->ObjectInformation->FileId.Cell,
1211 pDirNode->ObjectInformation->FileId.Volume,
1212 pDirNode->ObjectInformation->FileId.Vnode,
1213 pDirNode->ObjectInformation->FileId.Unique));
1215 AFSAcquireExcl( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1218 SetFlag( pDirNode->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1220 pDirNode->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1222 AFSReleaseResource( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1226 // Init the short name if we have one
1229 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1230 pCurrentDirEntry->ShortNameLength > 0)
1233 UNICODE_STRING uniShortName;
1235 pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
1237 RtlCopyMemory( pDirNode->NameInformation.ShortName,
1238 pCurrentDirEntry->ShortName,
1239 pDirNode->NameInformation.ShortNameLength);
1242 // Generate the short name index
1245 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1246 uniShortName.MaximumLength = uniShortName.Length;
1247 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1249 if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
1254 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1257 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1258 AFS_TRACE_LEVEL_VERBOSE,
1259 "AFSVerifyDirectoryContent Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1262 &pDirNode->NameInformation.FileName,
1263 pCurrentDirEntry->FileId.Cell,
1264 pCurrentDirEntry->FileId.Volume,
1265 pCurrentDirEntry->FileId.Vnode,
1266 pCurrentDirEntry->FileId.Unique));
1270 pDirNode->NameInformation.ShortNameLength = 0;
1272 RtlZeroMemory( pDirNode->NameInformation.ShortName,
1273 (12 * sizeof( WCHAR)));
1280 // No short name or short names have been disabled
1283 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
1287 // Insert the node into the name tree
1290 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
1292 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
1295 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
1297 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1298 AFS_TRACE_LEVEL_VERBOSE,
1299 "AFSVerifyDirectoryContent Insert DE %p to head of case sensitive tree for %wZ\n",
1301 &pDirNode->NameInformation.FileName));
1306 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1309 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1310 AFS_TRACE_LEVEL_VERBOSE,
1311 "AFSVerifyDirectoryContent Failed to insert DE %p to case sensitive tree for %wZ\n",
1313 &pDirNode->NameInformation.FileName));
1316 // Delete this dir entry and continue on
1319 AFSDeleteDirEntry( ObjectInfoCB,
1322 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1324 if( ulResultLen >= ulEntryLength)
1326 ulResultLen -= ulEntryLength;
1337 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1338 AFS_TRACE_LEVEL_VERBOSE,
1339 "AFSVerifyDirectoryContent Insert DE %p to case sensitive tree for %wZ\n",
1341 &pDirNode->NameInformation.FileName));
1345 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1347 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
1350 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
1352 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
1354 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1355 AFS_TRACE_LEVEL_VERBOSE,
1356 "AFSVerifyDirectoryContent Insert DE %p to head of case insensitive tree for %wZ\n",
1358 &pDirNode->NameInformation.FileName));
1363 AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1366 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1367 AFS_TRACE_LEVEL_VERBOSE,
1368 "AFSVerifyDirectoryContent Insert DE %p to case insensitive tree for %wZ\n",
1370 &pDirNode->NameInformation.FileName));
1373 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
1376 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
1381 (ObjectInfoCB->Specific.Directory.DirectoryNodeListTail)->ListEntry.fLink = pDirNode;
1383 pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
1386 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
1388 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
1390 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
1392 AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1393 AFS_TRACE_LEVEL_VERBOSE,
1394 "AFSVerifyDirectoryContent Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
1395 &pDirNode->NameInformation.FileName,
1396 ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
1397 ObjectInfoCB->FileId.Cell,
1398 ObjectInfoCB->FileId.Volume,
1399 ObjectInfoCB->FileId.Vnode,
1400 ObjectInfoCB->FileId.Unique));
1402 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
1406 // Insert the short name entry if we have a valid short name
1409 if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
1412 ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
1414 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1415 AFS_TRACE_LEVEL_VERBOSE,
1416 "AFSVerifyDirectoryContent Insert DE %p to head of shortname tree for %wZ\n",
1418 &pDirNode->NameInformation.FileName));
1420 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1425 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
1428 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1429 AFS_TRACE_LEVEL_VERBOSE,
1430 "AFSVerifyDirectoryContent Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
1432 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex,
1433 &pDirNode->NameInformation.FileName));
1437 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1439 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1440 AFS_TRACE_LEVEL_VERBOSE,
1441 "AFSVerifyDirectoryContent Insert DE %p to shortname tree for %wZ\n",
1443 &pDirNode->NameInformation.FileName));
1448 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
1454 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1456 if( ulResultLen >= ulEntryLength)
1458 ulResultLen -= ulEntryLength;
1466 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
1469 // Reset the information in the request buffer since it got trampled
1473 pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
1482 if( pBuffer != NULL)
1485 AFSExFreePoolWithTag( pBuffer, AFS_DIR_BUFFER_TAG);
1493 AFSNotifyFileCreate( IN GUID *AuthGroup,
1494 IN AFSObjectInfoCB *ParentObjectInfo,
1495 IN PLARGE_INTEGER FileSize,
1496 IN ULONG FileAttributes,
1497 IN UNICODE_STRING *FileName,
1498 OUT AFSDirectoryCB **DirNode)
1501 NTSTATUS ntStatus = STATUS_SUCCESS;
1502 AFSFileCreateCB stCreateCB;
1503 AFSFileCreateResultCB *pResultCB = NULL;
1504 ULONG ulResultLen = 0;
1505 UNICODE_STRING uniTargetName;
1506 AFSDirectoryCB *pDirNode = NULL;
1509 LARGE_INTEGER liOldDataVersion;
1510 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1511 BOOLEAN bReleaseParentTreeLock = FALSE;
1519 // Init the control block for the request
1522 RtlZeroMemory( &stCreateCB,
1523 sizeof( AFSFileCreateCB));
1525 stCreateCB.ParentId = ParentObjectInfo->FileId;
1527 stCreateCB.AllocationSize = *FileSize;
1529 stCreateCB.FileAttributes = FileAttributes;
1531 stCreateCB.EaSize = 0;
1533 liOldDataVersion = ParentObjectInfo->DataVersion;
1536 // Allocate our return buffer
1539 pResultCB = (AFSFileCreateResultCB *)AFSLibExAllocatePoolWithTag( PagedPool,
1541 AFS_GENERIC_MEMORY_1_TAG);
1543 if( pResultCB == NULL)
1546 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1549 RtlZeroMemory( pResultCB,
1552 ulResultLen = PAGE_SIZE;
1555 // Send the call to the service
1558 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_FILE,
1559 AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_HOLD_FID,
1566 sizeof( AFSFileCreateCB),
1570 if( ntStatus != STATUS_SUCCESS)
1573 if( NT_SUCCESS( ntStatus))
1576 ntStatus = STATUS_DEVICE_NOT_READY;
1579 try_return( ntStatus);
1583 // We may have raced with an invalidation call and a subsequent re-enumeration of this parent
1584 // and though we created the node, it is already in our list. If this is the case then
1585 // look up the entry rather than create a new entry
1586 // The check is to ensure the DV has been modified
1589 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1592 bReleaseParentTreeLock = TRUE;
1594 if( ParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
1597 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1598 AFS_TRACE_LEVEL_WARNING,
1599 "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",
1601 ParentObjectInfo->FileId.Cell,
1602 ParentObjectInfo->FileId.Volume,
1603 ParentObjectInfo->FileId.Vnode,
1604 ParentObjectInfo->FileId.Unique,
1605 ParentObjectInfo->DataVersion.HighPart,
1606 ParentObjectInfo->DataVersion.LowPart,
1607 pResultCB->ParentDataVersion.HighPart,
1608 pResultCB->ParentDataVersion.LowPart));
1611 // We raced so go and lookup the directory entry in the parent
1614 ulCRC = AFSGenerateCRC( FileName,
1617 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1621 if( pDirNode != NULL)
1624 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1625 AFS_TRACE_LEVEL_VERBOSE,
1626 "AFSNotifyFileCreate Located dir entry %p for file %wZ\n",
1630 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
1631 &pResultCB->DirEnum.FileId))
1634 *DirNode = pDirNode;
1636 try_return( ntStatus = STATUS_REPARSE);
1642 // We found an entry that matches the desired name but it is not the
1643 // same as the one that was created for us by the file server.
1646 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1647 AFS_TRACE_LEVEL_ERROR,
1648 "AFSNotifyFileCreate Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
1651 pDirNode->ObjectInformation->FileId.Cell,
1652 pDirNode->ObjectInformation->FileId.Volume,
1653 pDirNode->ObjectInformation->FileId.Vnode,
1654 pDirNode->ObjectInformation->FileId.Unique,
1655 pResultCB->DirEnum.FileId.Cell,
1656 pResultCB->DirEnum.FileId.Volume,
1657 pResultCB->DirEnum.FileId.Vnode,
1658 pResultCB->DirEnum.FileId.Unique));
1660 if( pDirNode->DirOpenReferenceCount <= 0 &&
1661 pDirNode->NameArrayReferenceCount <= 0)
1664 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1665 AFS_TRACE_LEVEL_VERBOSE,
1666 "AFSNotifyFileCreate Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1668 &pDirNode->NameInformation.FileName,
1669 pDirNode->ObjectInformation->FileId.Cell,
1670 pDirNode->ObjectInformation->FileId.Volume,
1671 pDirNode->ObjectInformation->FileId.Vnode,
1672 pDirNode->ObjectInformation->FileId.Unique,
1673 pResultCB->DirEnum.FileId.Cell,
1674 pResultCB->DirEnum.FileId.Volume,
1675 pResultCB->DirEnum.FileId.Vnode,
1676 pResultCB->DirEnum.FileId.Unique));
1678 AFSDeleteDirEntry( ParentObjectInfo,
1684 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1686 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1687 AFS_TRACE_LEVEL_VERBOSE,
1688 "AFSNotifyFileCreate Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1690 &pDirNode->NameInformation.FileName,
1691 pDirNode->ObjectInformation->FileId.Cell,
1692 pDirNode->ObjectInformation->FileId.Volume,
1693 pDirNode->ObjectInformation->FileId.Vnode,
1694 pDirNode->ObjectInformation->FileId.Unique,
1695 pResultCB->DirEnum.FileId.Cell,
1696 pResultCB->DirEnum.FileId.Volume,
1697 pResultCB->DirEnum.FileId.Vnode,
1698 pResultCB->DirEnum.FileId.Unique));
1700 AFSRemoveNameEntry( ParentObjectInfo,
1709 // We are unsure of our current data so set the verify flag. It may already be set
1710 // but no big deal to reset it
1713 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1715 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1718 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1719 AFS_TRACE_LEVEL_VERBOSE,
1720 "AFSNotifyFileCreate Creating new entry %wZ\n",
1724 // Initialize the directory entry
1727 uniTargetName.Length = (USHORT)pResultCB->DirEnum.TargetNameLength;
1729 uniTargetName.MaximumLength = uniTargetName.Length;
1731 uniTargetName.Buffer = (WCHAR *)((char *)&pResultCB->DirEnum + pResultCB->DirEnum.TargetNameOffset);
1733 pDirNode = AFSInitDirEntry( ParentObjectInfo,
1736 &pResultCB->DirEnum,
1737 (ULONG)InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1739 if( pDirNode == NULL)
1742 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1744 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1746 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1750 // Init the short name if we have one
1753 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1754 pResultCB->DirEnum.ShortNameLength > 0)
1757 UNICODE_STRING uniShortName;
1759 pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
1761 RtlCopyMemory( pDirNode->NameInformation.ShortName,
1762 pResultCB->DirEnum.ShortName,
1763 pDirNode->NameInformation.ShortNameLength);
1766 // Generate the short name index
1769 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1770 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1772 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1775 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1776 AFS_TRACE_LEVEL_VERBOSE,
1777 "AFSNotifyFileCreate Initialized short name %wZ for DE %p for %wZ\n",
1780 &pDirNode->NameInformation.FileName));
1785 // No short name or short names are disabled
1788 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
1791 if ( !BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1795 // Update the parent data version
1798 ParentObjectInfo->DataVersion = pResultCB->ParentDataVersion;
1800 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1801 AFS_TRACE_LEVEL_VERBOSE,
1802 "AFSNotifyFileCreate entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
1804 ParentObjectInfo->FileId.Cell,
1805 ParentObjectInfo->FileId.Volume,
1806 ParentObjectInfo->FileId.Vnode,
1807 ParentObjectInfo->FileId.Unique,
1808 ParentObjectInfo->DataVersion.QuadPart));
1812 // Return the directory node
1815 *DirNode = pDirNode;
1819 if ( *DirNode != NULL)
1822 lCount = InterlockedIncrement( &(*DirNode)->DirOpenReferenceCount);
1824 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1825 AFS_TRACE_LEVEL_VERBOSE,
1826 "AFSNotifyFileCreate Increment count on %wZ DE %p Cnt %d\n",
1827 &(*DirNode)->NameInformation.FileName,
1831 ASSERT( lCount >= 0);
1834 if ( bReleaseParentTreeLock)
1837 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1840 if( pResultCB != NULL)
1843 AFSExFreePoolWithTag( pResultCB, AFS_GENERIC_MEMORY_1_TAG);
1851 AFSUpdateFileInformation( IN AFSFileID *ParentFid,
1852 IN AFSObjectInfoCB *ObjectInfo,
1856 NTSTATUS ntStatus = STATUS_SUCCESS;
1857 AFSFileUpdateCB stUpdateCB;
1858 ULONG ulResultLen = 0;
1859 AFSFileUpdateResultCB *pUpdateResultCB = NULL;
1865 // Init the control block for the request
1868 RtlZeroMemory( &stUpdateCB,
1869 sizeof( AFSFileUpdateCB));
1871 stUpdateCB.AllocationSize = ObjectInfo->EndOfFile;
1873 stUpdateCB.FileAttributes = ObjectInfo->FileAttributes;
1875 stUpdateCB.EaSize = ObjectInfo->EaSize;
1877 stUpdateCB.ParentId = *ParentFid;
1879 stUpdateCB.LastAccessTime = ObjectInfo->LastAccessTime;
1881 stUpdateCB.CreateTime = ObjectInfo->CreationTime;
1883 stUpdateCB.ChangeTime = ObjectInfo->ChangeTime;
1885 stUpdateCB.LastWriteTime = ObjectInfo->LastWriteTime;
1887 pUpdateResultCB = (AFSFileUpdateResultCB *)AFSLibExAllocatePoolWithTag( PagedPool,
1889 AFS_UPDATE_RESULT_TAG);
1891 if( pUpdateResultCB == NULL)
1894 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1897 ulResultLen = PAGE_SIZE;
1899 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_UPDATE_FILE,
1900 AFS_REQUEST_FLAG_SYNCHRONOUS,
1903 &ObjectInfo->FileId,
1904 ObjectInfo->VolumeCB->VolumeInformation.Cell,
1905 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
1907 sizeof( AFSFileUpdateCB),
1911 if( ntStatus != STATUS_SUCCESS)
1914 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1915 AFS_TRACE_LEVEL_ERROR,
1916 "AFSUpdateFileInformation failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1917 ObjectInfo->FileId.Cell,
1918 ObjectInfo->FileId.Volume,
1919 ObjectInfo->FileId.Vnode,
1920 ObjectInfo->FileId.Unique,
1923 try_return( ntStatus);
1927 // Update the data version
1930 AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1933 if ( !BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1936 ObjectInfo->DataVersion = pUpdateResultCB->DirEnum.DataVersion;
1939 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1943 if( pUpdateResultCB != NULL)
1946 AFSExFreePoolWithTag( pUpdateResultCB, AFS_UPDATE_RESULT_TAG);
1954 AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
1956 IN BOOLEAN CheckOnly)
1958 NTSTATUS ntStatus = STATUS_SUCCESS;
1959 ULONG ulResultLen = 0;
1960 AFSFileDeleteCB stDelete;
1961 AFSFileDeleteResultCB stDeleteResult;
1962 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1963 AFSObjectInfoCB *pObjectInfo = NULL;
1964 AFSObjectInfoCB *pParentObjectInfo = NULL;
1969 pObjectInfo = DirectoryCB->ObjectInformation;
1971 pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
1972 &pObjectInfo->ParentFileId,
1975 stDelete.ParentId = pObjectInfo->ParentFileId;
1977 stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
1979 ulResultLen = sizeof( AFSFileDeleteResultCB);
1983 ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
1986 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
1989 &DirectoryCB->NameInformation.FileName,
1990 &pObjectInfo->FileId,
1991 pObjectInfo->VolumeCB->VolumeInformation.Cell,
1992 pObjectInfo->VolumeCB->VolumeInformation.CellLength,
1994 sizeof( AFSFileDeleteCB),
1998 if( ntStatus != STATUS_SUCCESS)
2001 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2002 AFS_TRACE_LEVEL_ERROR,
2003 "AFSNotifyDelete failed ParentFID %08lX-%08lX-%08lX-%08lX %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2004 stDelete.ParentId.Cell,
2005 stDelete.ParentId.Volume,
2006 stDelete.ParentId.Vnode,
2007 stDelete.ParentId.Unique,
2008 &DirectoryCB->NameInformation.FileName,
2009 pObjectInfo->FileId.Cell,
2010 pObjectInfo->FileId.Volume,
2011 pObjectInfo->FileId.Vnode,
2012 pObjectInfo->FileId.Unique,
2015 try_return( ntStatus);
2018 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2025 // Validate the parent data version
2028 if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
2031 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2033 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2040 // Update the parent data version
2043 if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart - 1)
2046 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2048 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2054 // TODO -- The entry must be removed from the directory at which point the
2055 // Directory data version number can be updated. Until then we must force
2058 // pParentObjectInfor->DataVersion.QuadPart = stDeleteResult.ParentDataVersion.QuadPart;
2061 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2063 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2067 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2071 if ( pParentObjectInfo)
2074 AFSReleaseObjectInfo( &pParentObjectInfo);
2083 AFSNotifyHardLink( IN AFSObjectInfoCB *ObjectInfo,
2085 IN AFSObjectInfoCB *ParentObjectInfo,
2086 IN AFSObjectInfoCB *TargetParentObjectInfo,
2087 IN AFSDirectoryCB *SourceDirectoryCB,
2088 IN UNICODE_STRING *TargetName,
2089 IN BOOLEAN bReplaceIfExists,
2090 OUT AFSDirectoryCB **TargetDirectoryCB)
2093 NTSTATUS ntStatus = STATUS_SUCCESS;
2094 AFSFileHardLinkCB *pHardLinkCB = NULL;
2095 AFSFileHardLinkResultCB *pResultCB = NULL;
2096 ULONG ulResultLen = 0;
2097 AFSDirectoryCB *pDirNode = NULL;
2099 BOOLEAN bReleaseParentLock = FALSE, bReleaseTargetParentLock = FALSE;
2100 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2107 // Init the control block for the request
2110 pHardLinkCB = (AFSFileHardLinkCB *)AFSLibExAllocatePoolWithTag( PagedPool,
2112 AFS_HARDLINK_REQUEST_TAG);
2114 if( pHardLinkCB == NULL)
2117 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2120 RtlZeroMemory( pHardLinkCB,
2123 pHardLinkCB->SourceParentId = ParentObjectInfo->FileId;
2125 pHardLinkCB->TargetParentId = TargetParentObjectInfo->FileId;
2127 pHardLinkCB->TargetNameLength = TargetName->Length;
2129 RtlCopyMemory( pHardLinkCB->TargetName,
2131 TargetName->Length);
2133 pHardLinkCB->bReplaceIfExists = bReplaceIfExists;
2136 // Use the same buffer for the result control block
2139 pResultCB = (AFSFileHardLinkResultCB *)pHardLinkCB;
2141 ulResultLen = PAGE_SIZE;
2143 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_HARDLINK_FILE,
2144 AFS_REQUEST_FLAG_SYNCHRONOUS,
2146 &SourceDirectoryCB->NameInformation.FileName,
2147 &ObjectInfo->FileId,
2148 ObjectInfo->VolumeCB->VolumeInformation.Cell,
2149 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2151 sizeof( AFSFileHardLinkCB) + TargetName->Length,
2155 if( ntStatus != STATUS_SUCCESS)
2158 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2159 AFS_TRACE_LEVEL_ERROR,
2160 "AFSNotifyHardLink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2161 ObjectInfo->FileId.Cell,
2162 ObjectInfo->FileId.Volume,
2163 ObjectInfo->FileId.Vnode,
2164 ObjectInfo->FileId.Unique,
2167 try_return( ntStatus);
2171 // Update the information from the returned data
2174 if ( ParentObjectInfo != TargetParentObjectInfo)
2177 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2180 bReleaseParentLock = TRUE;
2182 if ( ParentObjectInfo->DataVersion.QuadPart == pResultCB->SourceParentDataVersion.QuadPart - 1)
2185 ParentObjectInfo->DataVersion = pResultCB->SourceParentDataVersion;
2190 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2192 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2196 AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2199 bReleaseTargetParentLock = TRUE;
2201 if ( TargetParentObjectInfo->DataVersion.QuadPart == pResultCB->TargetParentDataVersion.QuadPart - 1)
2204 TargetParentObjectInfo->DataVersion = pResultCB->TargetParentDataVersion;
2209 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2210 AFS_TRACE_LEVEL_WARNING,
2211 "AFSNotifyHardLink Raced with an invalidate call and a re-enumeration for entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version (%08lX:%08lX != %08lX:%08lX - 1)\n",
2213 TargetParentObjectInfo->FileId.Cell,
2214 TargetParentObjectInfo->FileId.Volume,
2215 TargetParentObjectInfo->FileId.Vnode,
2216 TargetParentObjectInfo->FileId.Unique,
2217 TargetParentObjectInfo->DataVersion.HighPart,
2218 TargetParentObjectInfo->DataVersion.LowPart,
2219 pResultCB->TargetParentDataVersion.HighPart,
2220 pResultCB->TargetParentDataVersion.LowPart));
2223 // We raced so go and lookup the directory entry in the parent
2226 ulCRC = AFSGenerateCRC( TargetName,
2229 AFSLocateCaseSensitiveDirEntry( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2233 if( pDirNode != NULL)
2236 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2237 AFS_TRACE_LEVEL_VERBOSE,
2238 "AFSNotifyHardLink Located dir entry %p for file %wZ\n",
2242 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2243 &pResultCB->DirEnum.FileId))
2246 try_return( ntStatus = STATUS_REPARSE);
2252 // We found an entry that matches the desired name but it is not the
2253 // same as the one that was created for us by the file server.
2256 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2257 AFS_TRACE_LEVEL_ERROR,
2258 "AFSNotifyHardLink Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
2261 pDirNode->ObjectInformation->FileId.Cell,
2262 pDirNode->ObjectInformation->FileId.Volume,
2263 pDirNode->ObjectInformation->FileId.Vnode,
2264 pDirNode->ObjectInformation->FileId.Unique,
2265 pResultCB->DirEnum.FileId.Cell,
2266 pResultCB->DirEnum.FileId.Volume,
2267 pResultCB->DirEnum.FileId.Vnode,
2268 pResultCB->DirEnum.FileId.Unique));
2270 if( pDirNode->DirOpenReferenceCount <= 0 &&
2271 pDirNode->NameArrayReferenceCount <= 0)
2274 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2275 AFS_TRACE_LEVEL_VERBOSE,
2276 "AFSNotifyHardLink Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2278 &pDirNode->NameInformation.FileName,
2279 pDirNode->ObjectInformation->FileId.Cell,
2280 pDirNode->ObjectInformation->FileId.Volume,
2281 pDirNode->ObjectInformation->FileId.Vnode,
2282 pDirNode->ObjectInformation->FileId.Unique,
2283 pResultCB->DirEnum.FileId.Cell,
2284 pResultCB->DirEnum.FileId.Volume,
2285 pResultCB->DirEnum.FileId.Vnode,
2286 pResultCB->DirEnum.FileId.Unique));
2288 AFSDeleteDirEntry( TargetParentObjectInfo,
2294 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2296 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2297 AFS_TRACE_LEVEL_VERBOSE,
2298 "AFSNotifyHardLink Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2300 &pDirNode->NameInformation.FileName,
2301 pDirNode->ObjectInformation->FileId.Cell,
2302 pDirNode->ObjectInformation->FileId.Volume,
2303 pDirNode->ObjectInformation->FileId.Vnode,
2304 pDirNode->ObjectInformation->FileId.Unique,
2305 pResultCB->DirEnum.FileId.Cell,
2306 pResultCB->DirEnum.FileId.Volume,
2307 pResultCB->DirEnum.FileId.Vnode,
2308 pResultCB->DirEnum.FileId.Unique));
2310 AFSRemoveNameEntry( TargetParentObjectInfo,
2319 // We are unsure of our current data so set the verify flag. It may already be set
2320 // but no big deal to reset it
2323 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2325 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2329 // Create the hard link entry
2332 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2333 AFS_TRACE_LEVEL_VERBOSE,
2334 "AFSNotifyHardLink Creating new entry %wZ\n",
2338 // Initialize the directory entry
2341 pDirNode = AFSInitDirEntry( TargetParentObjectInfo,
2344 &pResultCB->DirEnum,
2345 (ULONG)InterlockedIncrement( &TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
2347 if( pDirNode == NULL)
2350 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2352 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2354 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2358 // Init the short name if we have one
2361 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2362 pResultCB->DirEnum.ShortNameLength > 0)
2365 UNICODE_STRING uniShortName;
2367 pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
2369 RtlCopyMemory( pDirNode->NameInformation.ShortName,
2370 pResultCB->DirEnum.ShortName,
2371 pDirNode->NameInformation.ShortNameLength);
2374 // Generate the short name index
2377 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
2378 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
2380 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
2383 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2384 AFS_TRACE_LEVEL_VERBOSE,
2385 "AFSNotifyHardLink Initialized short name %wZ for DE %p for %wZ\n",
2388 &pDirNode->NameInformation.FileName));
2393 // No short name or short names are disabled
2396 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2399 if ( !BooleanFlagOn( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2403 // Update the target parent data version
2406 TargetParentObjectInfo->DataVersion = pResultCB->TargetParentDataVersion;
2408 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2409 AFS_TRACE_LEVEL_VERBOSE,
2410 "AFSNotifyHardLink entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
2412 TargetParentObjectInfo->FileId.Cell,
2413 TargetParentObjectInfo->FileId.Volume,
2414 TargetParentObjectInfo->FileId.Vnode,
2415 TargetParentObjectInfo->FileId.Unique,
2416 TargetParentObjectInfo->DataVersion.QuadPart));
2421 if ( TargetDirectoryCB != NULL)
2424 if ( pDirNode != NULL)
2427 lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
2429 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2430 AFS_TRACE_LEVEL_VERBOSE,
2431 "AFSNotifyHardLink Increment count on %wZ DE %p Cnt %d\n",
2432 &pDirNode->NameInformation.FileName,
2436 ASSERT( lCount >= 0);
2439 *TargetDirectoryCB = pDirNode;
2442 if ( bReleaseTargetParentLock)
2445 AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2448 if ( bReleaseParentLock)
2451 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2454 if( pHardLinkCB != NULL)
2457 AFSExFreePoolWithTag( pHardLinkCB, AFS_HARDLINK_REQUEST_TAG);
2467 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
2469 IN AFSObjectInfoCB *ParentObjectInfo,
2470 IN AFSObjectInfoCB *TargetParentObjectInfo,
2471 IN AFSDirectoryCB *DirectoryCB,
2472 IN UNICODE_STRING *TargetName,
2473 OUT AFSFileID *UpdatedFID)
2476 NTSTATUS ntStatus = STATUS_SUCCESS;
2477 AFSFileRenameCB *pRenameCB = NULL;
2478 AFSFileRenameResultCB *pRenameResultCB = NULL;
2479 ULONG ulResultLen = 0;
2480 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2486 // Init the control block for the request
2489 pRenameCB = (AFSFileRenameCB *)AFSLibExAllocatePoolWithTag( PagedPool,
2491 AFS_RENAME_REQUEST_TAG);
2493 if( pRenameCB == NULL)
2496 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2499 RtlZeroMemory( pRenameCB,
2502 pRenameCB->SourceParentId = ParentObjectInfo->FileId;
2504 pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
2506 pRenameCB->TargetNameLength = TargetName->Length;
2508 RtlCopyMemory( pRenameCB->TargetName,
2510 TargetName->Length);
2513 // Use the same buffer for the result control block
2516 pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
2518 ulResultLen = PAGE_SIZE;
2520 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
2521 AFS_REQUEST_FLAG_SYNCHRONOUS,
2523 &DirectoryCB->NameInformation.FileName,
2524 &ObjectInfo->FileId,
2525 ObjectInfo->VolumeCB->VolumeInformation.Cell,
2526 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2528 sizeof( AFSFileRenameCB) + TargetName->Length,
2532 if( ntStatus != STATUS_SUCCESS)
2535 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2536 AFS_TRACE_LEVEL_ERROR,
2537 "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2538 ObjectInfo->FileId.Cell,
2539 ObjectInfo->FileId.Volume,
2540 ObjectInfo->FileId.Vnode,
2541 ObjectInfo->FileId.Unique,
2544 try_return( ntStatus);
2548 // Update the information from the returned data
2551 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2554 if ( ParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->SourceParentDataVersion.QuadPart - 1)
2557 ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
2562 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2564 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2567 if ( ParentObjectInfo != TargetParentObjectInfo)
2570 AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2573 if ( TargetParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->TargetParentDataVersion.QuadPart - 1)
2576 TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
2581 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2583 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2588 // Move over the short name
2591 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2593 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2594 DirectoryCB->NameInformation.ShortNameLength > 0)
2597 UNICODE_STRING uniShortName;
2599 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2600 uniShortName.MaximumLength = uniShortName.Length;
2601 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2603 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2604 AFS_TRACE_LEVEL_VERBOSE,
2605 "AFSNotifyRename Update old short name %wZ for DE %p for %wZ\n",
2608 &DirectoryCB->NameInformation.FileName));
2610 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2612 RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
2613 pRenameResultCB->DirEnum.ShortName,
2614 DirectoryCB->NameInformation.ShortNameLength);
2616 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2617 uniShortName.MaximumLength = uniShortName.Length;
2618 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2620 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2621 AFS_TRACE_LEVEL_VERBOSE,
2622 "AFSNotifyRename Initialized short name %wZ for DE %p for %wZ\n",
2625 &DirectoryCB->NameInformation.FileName));
2630 UNICODE_STRING uniShortName;
2632 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2633 uniShortName.MaximumLength = uniShortName.Length;
2634 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2636 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2637 AFS_TRACE_LEVEL_VERBOSE,
2638 "AFSNotifyRename Removing old short name %wZ for DE %p for %wZ\n",
2641 &DirectoryCB->NameInformation.FileName));
2643 DirectoryCB->NameInformation.ShortNameLength = 0;
2645 DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2648 if ( ParentObjectInfo != TargetParentObjectInfo)
2651 AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2654 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2656 if( UpdatedFID != NULL)
2658 *UpdatedFID = pRenameResultCB->DirEnum.FileId;
2663 if( pRenameCB != NULL)
2666 AFSExFreePoolWithTag( pRenameCB, AFS_RENAME_REQUEST_TAG);
2674 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
2676 IN BOOLEAN FastCall,
2677 OUT AFSDirEnumEntry **DirEnumEntry)
2680 NTSTATUS ntStatus = STATUS_SUCCESS;
2681 AFSEvalTargetCB stTargetID;
2682 ULONG ulResultBufferLength;
2683 AFSFileEvalResultCB *pEvalResultCB = NULL;
2684 AFSDirEnumEntry *pDirEnumCB = NULL;
2685 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
2686 AFSObjectInfoCB *pParentObjectInfo = NULL;
2691 RtlZeroMemory( &stTargetID,
2692 sizeof( AFSEvalTargetCB));
2694 if ( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2697 pParentObjectInfo = AFSFindObjectInfo( ObjectInfo->VolumeCB,
2698 &ObjectInfo->ParentFileId,
2701 stTargetID.ParentId = ObjectInfo->ParentFileId;
2705 // Allocate our response buffer
2708 pEvalResultCB = (AFSFileEvalResultCB *)AFSLibExAllocatePoolWithTag( PagedPool,
2710 AFS_GENERIC_MEMORY_30_TAG);
2712 if( pEvalResultCB == NULL)
2715 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2719 // Call to the service to evaluate the fid
2722 ulResultBufferLength = PAGE_SIZE;
2727 ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
2730 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
2734 &ObjectInfo->FileId,
2735 ObjectInfo->VolumeCB->VolumeInformation.Cell,
2736 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2738 sizeof( AFSEvalTargetCB),
2740 &ulResultBufferLength);
2742 if( ntStatus != STATUS_SUCCESS)
2746 // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
2750 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2753 if( pParentObjectInfo != NULL)
2756 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2759 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2761 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2763 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2767 try_return( ntStatus);
2771 // A BSOD can occur if the pEvalResultCB->FileType is FILE but the
2772 // ObjectInfo->FileType is something else. The same is true for
2773 // pDirEnumEntry->FileType is DIRECTORY. Perform a sanity check
2774 // to ensure consistency. An inconsistent pDirEnumEntry can be
2775 // produced as a result of invalid status info received from a file
2776 // server. If the types are inconsistent or if the type does not
2777 // match the implied type derived from the vnode (odd values are
2778 // directories and even values are other types), prevent the request
2779 // from completing successfully. This may prevent access to the file or
2780 // directory but will prevent a BSOD.
2783 if ( !AFSIsEqualFID( &ObjectInfo->FileId,
2784 &pEvalResultCB->DirEnum.FileId))
2787 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2790 switch ( pEvalResultCB->DirEnum.FileType)
2793 case AFS_FILE_TYPE_DIRECTORY:
2794 if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x1)
2797 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2800 if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
2801 ObjectInfo->FileType != AFS_FILE_TYPE_DIRECTORY)
2804 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2809 case AFS_FILE_TYPE_FILE:
2810 if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x0)
2813 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2816 if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
2817 ObjectInfo->FileType != AFS_FILE_TYPE_FILE)
2820 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2827 // Validate the parent data version
2830 if ( pParentObjectInfo != NULL)
2833 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2836 if ( pParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2839 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2841 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2844 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2848 // Pass back the dir enum entry
2851 if( DirEnumEntry != NULL)
2854 pDirEnumCB = (AFSDirEnumEntry *)AFSLibExAllocatePoolWithTag( PagedPool,
2856 AFS_GENERIC_MEMORY_2_TAG);
2858 if( pDirEnumCB == NULL)
2861 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2864 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2865 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2867 *DirEnumEntry = pDirEnumCB;
2872 if ( pParentObjectInfo != NULL)
2875 AFSReleaseObjectInfo( &pParentObjectInfo);
2878 if( pEvalResultCB != NULL)
2881 AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_30_TAG);
2884 if( !NT_SUCCESS( ntStatus))
2887 if( pDirEnumCB != NULL)
2890 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_2_TAG);
2893 *DirEnumEntry = NULL;
2901 AFSEvaluateTargetByName( IN GUID *AuthGroup,
2902 IN AFSObjectInfoCB *ParentObjectInfo,
2903 IN PUNICODE_STRING SourceName,
2905 OUT AFSDirEnumEntry **DirEnumEntry)
2908 NTSTATUS ntStatus = STATUS_SUCCESS;
2909 AFSEvalTargetCB stTargetID;
2910 ULONG ulResultBufferLength;
2911 AFSFileEvalResultCB *pEvalResultCB = NULL;
2912 AFSDirEnumEntry *pDirEnumCB = NULL;
2917 stTargetID.ParentId = ParentObjectInfo->FileId;
2920 // Allocate our response buffer
2923 pEvalResultCB = (AFSFileEvalResultCB *)AFSLibExAllocatePoolWithTag( PagedPool,
2925 AFS_GENERIC_MEMORY_31_TAG);
2927 if( pEvalResultCB == NULL)
2930 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2934 // Call to the service to evaluate the fid
2937 ulResultBufferLength = PAGE_SIZE;
2939 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
2940 AFS_REQUEST_FLAG_SYNCHRONOUS | Flags,
2944 ParentObjectInfo->VolumeCB->VolumeInformation.Cell,
2945 ParentObjectInfo->VolumeCB->VolumeInformation.CellLength,
2947 sizeof( AFSEvalTargetCB),
2949 &ulResultBufferLength);
2951 if( ntStatus != STATUS_SUCCESS)
2954 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2957 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2960 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2962 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2964 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2967 try_return( ntStatus);
2971 // Validate the parent data version
2974 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2977 if ( ParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2980 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2982 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2985 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2988 // Pass back the dir enum entry
2991 if( DirEnumEntry != NULL)
2994 pDirEnumCB = (AFSDirEnumEntry *)AFSLibExAllocatePoolWithTag( PagedPool,
2996 AFS_GENERIC_MEMORY_3_TAG);
2998 if( pDirEnumCB == NULL)
3001 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3004 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
3005 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
3007 *DirEnumEntry = pDirEnumCB;
3012 if( pEvalResultCB != NULL)
3015 AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_31_TAG);
3018 if( !NT_SUCCESS( ntStatus))
3021 if( pDirEnumCB != NULL)
3024 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_3_TAG);
3027 *DirEnumEntry = NULL;
3035 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
3036 IN AFSFileID *FileID,
3037 OUT AFSVolumeInfoCB *VolumeInformation)
3040 NTSTATUS ntStatus = STATUS_SUCCESS;
3041 ULONG ulResultLen = 0;
3046 ulResultLen = sizeof( AFSVolumeInfoCB);
3048 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
3049 AFS_REQUEST_FLAG_SYNCHRONOUS,
3060 if( ntStatus != STATUS_SUCCESS)
3063 try_return( ntStatus);
3075 AFSRetrieveVolumeSizeInformation( IN GUID *AuthGroup,
3076 IN AFSFileID *FileID,
3077 OUT AFSVolumeSizeInfoCB *VolumeSizeInformation)
3080 NTSTATUS ntStatus = STATUS_SUCCESS;
3081 ULONG ulResultLen = 0;
3086 ulResultLen = sizeof( AFSVolumeSizeInfoCB);
3088 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_SIZE_INFO,
3089 AFS_REQUEST_FLAG_SYNCHRONOUS,
3097 VolumeSizeInformation,
3100 if( ntStatus != STATUS_SUCCESS)
3103 try_return( ntStatus);
3115 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
3116 IN ULONG InputLength,
3117 IN ULONG OutputLength,
3118 IN void *InputDataBuffer,
3119 OUT void *OutputDataBuffer,
3120 OUT ULONG *BytesReturned)
3123 NTSTATUS ntStatus = STATUS_SUCCESS;
3124 ULONG ulResultLen = 0;
3125 MDL *pInputMdl = NULL, *pOutputMdl = NULL;
3126 void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
3127 AFSPipeIORequestCB *pIoRequest = NULL;
3133 // Map the user buffer to a system address
3136 pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
3140 if( pInputSystemBuffer == NULL)
3143 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3146 pIoRequest = (AFSPipeIORequestCB *)AFSLibExAllocatePoolWithTag( PagedPool,
3147 sizeof( AFSPipeIORequestCB) +
3149 AFS_GENERIC_MEMORY_4_TAG);
3151 if( pIoRequest == NULL)
3154 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3157 RtlZeroMemory( pIoRequest,
3158 sizeof( AFSPipeIORequestCB) + InputLength);
3160 pIoRequest->RequestId = Ccb->RequestID;
3162 pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3164 pIoRequest->BufferLength = InputLength;
3166 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
3170 pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
3174 if( pOutputSystemBuffer == NULL)
3177 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3181 // Send the call to the service
3184 ulResultLen = OutputLength;
3186 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
3187 AFS_REQUEST_FLAG_SYNCHRONOUS,
3189 &Ccb->DirectoryCB->NameInformation.FileName,
3194 sizeof( AFSPipeIORequestCB) + InputLength,
3195 pOutputSystemBuffer,
3198 if( ntStatus != STATUS_SUCCESS &&
3199 ntStatus != STATUS_BUFFER_OVERFLOW)
3202 if( NT_SUCCESS( ntStatus))
3205 ntStatus = STATUS_DEVICE_NOT_READY;
3208 try_return( ntStatus);
3212 // Return the bytes processed
3215 *BytesReturned = ulResultLen;
3219 if( pInputMdl != NULL)
3222 MmUnlockPages( pInputMdl);
3224 IoFreeMdl( pInputMdl);
3227 if( pOutputMdl != NULL)
3230 MmUnlockPages( pOutputMdl);
3232 IoFreeMdl( pOutputMdl);
3235 if( pIoRequest != NULL)
3238 AFSLibExFreePoolWithTag( pIoRequest,
3239 AFS_GENERIC_MEMORY_4_TAG);
3247 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
3248 IN ULONG InformationClass,
3249 IN ULONG InputLength,
3250 IN void *DataBuffer)
3253 NTSTATUS ntStatus = STATUS_SUCCESS;
3254 AFSPipeInfoRequestCB *pInfoRequest = NULL;
3259 pInfoRequest = (AFSPipeInfoRequestCB *)AFSLibExAllocatePoolWithTag( PagedPool,
3260 sizeof( AFSPipeInfoRequestCB) +
3262 AFS_GENERIC_MEMORY_5_TAG);
3264 if( pInfoRequest == NULL)
3267 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3270 RtlZeroMemory( pInfoRequest,
3271 sizeof( AFSPipeInfoRequestCB) + InputLength);
3273 pInfoRequest->RequestId = Ccb->RequestID;
3275 pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3277 pInfoRequest->BufferLength = InputLength;
3279 pInfoRequest->InformationClass = InformationClass;
3281 RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
3286 // Send the call to the service
3289 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
3290 AFS_REQUEST_FLAG_SYNCHRONOUS,
3292 &Ccb->DirectoryCB->NameInformation.FileName,
3297 sizeof( AFSPipeInfoRequestCB) + InputLength,
3301 if( ntStatus != STATUS_SUCCESS)
3304 if( NT_SUCCESS( ntStatus))
3307 ntStatus = STATUS_DEVICE_NOT_READY;
3310 try_return( ntStatus);
3315 if( pInfoRequest != NULL)
3318 AFSExFreePoolWithTag( pInfoRequest, AFS_GENERIC_MEMORY_5_TAG);
3326 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
3327 IN ULONG InformationClass,
3328 IN ULONG OutputLength,
3329 IN void *DataBuffer,
3330 OUT ULONG *BytesReturned)
3333 NTSTATUS ntStatus = STATUS_SUCCESS;
3334 AFSPipeInfoRequestCB stInfoRequest;
3335 ULONG ulBytesProcessed = 0;
3340 RtlZeroMemory( &stInfoRequest,
3341 sizeof( AFSPipeInfoRequestCB));
3343 stInfoRequest.RequestId = Ccb->RequestID;
3345 stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3347 stInfoRequest.BufferLength = OutputLength;
3349 stInfoRequest.InformationClass = InformationClass;
3351 ulBytesProcessed = OutputLength;
3354 // Send the call to the service
3357 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
3358 AFS_REQUEST_FLAG_SYNCHRONOUS,
3360 &Ccb->DirectoryCB->NameInformation.FileName,
3365 sizeof( AFSPipeInfoRequestCB),
3369 if( ntStatus != STATUS_SUCCESS)
3372 if( NT_SUCCESS( ntStatus))
3375 ntStatus = STATUS_DEVICE_NOT_READY;
3378 try_return( ntStatus);
3381 *BytesReturned = ulBytesProcessed;
3392 AFSReleaseFid( IN AFSFileID *FileId)
3395 NTSTATUS ntStatus = STATUS_SUCCESS;
3400 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
3417 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
3418 IN LARGE_INTEGER *ExtentOffset,
3422 BOOLEAN bRequestQueued = FALSE;
3423 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3424 AFSCommSrvcCB *pCommSrvc = NULL;
3425 AFSPoolEntry *pPoolEntry = NULL;
3426 AFSRequestExtentsCB *pRequestExtents = NULL;
3432 pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
3434 AFSAcquireShared( &pCommSrvc->IrpPoolLock,
3437 pPoolEntry = pCommSrvc->RequestPoolHead;
3439 while( pPoolEntry != NULL)
3442 if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
3445 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
3448 pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
3450 if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
3451 pRequestExtents->Length == Length)
3454 bRequestQueued = TRUE;
3459 pPoolEntry = pPoolEntry->fLink;
3462 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
3465 return bRequestQueued;
3469 AFSCreateSymlink( IN GUID *AuthGroup,
3470 IN AFSObjectInfoCB *ParentObjectInfo,
3471 IN UNICODE_STRING *FileName,
3472 IN AFSObjectInfoCB *ObjectInfo,
3473 IN UNICODE_STRING *TargetName)
3476 NTSTATUS ntStatus = STATUS_SUCCESS;
3477 AFSCreateSymlinkCB *pSymlinkCreate = NULL;
3478 ULONG ulResultLen = 0;
3479 AFSCreateSymlinkResultCB *pSymlinkResult = NULL;
3485 // Allocate our request and result structures
3488 pSymlinkCreate = (AFSCreateSymlinkCB *)AFSLibExAllocatePoolWithTag( PagedPool,
3489 sizeof( AFSCreateSymlinkCB) +
3491 AFS_SYMLINK_REQUEST_TAG);
3493 if( pSymlinkCreate == NULL)
3496 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3499 RtlZeroMemory( pSymlinkCreate,
3500 sizeof( AFSCreateSymlinkCB) +
3501 TargetName->Length);
3503 pSymlinkResult = (AFSCreateSymlinkResultCB *)AFSLibExAllocatePoolWithTag( PagedPool,
3505 AFS_SYMLINK_REQUEST_TAG);
3507 if( pSymlinkResult == NULL)
3510 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3513 RtlZeroMemory( pSymlinkResult,
3517 // Populate the request buffer
3520 RtlCopyMemory( &pSymlinkCreate->ParentId,
3521 &ObjectInfo->ParentFileId,
3522 sizeof( AFSFileID));
3524 pSymlinkCreate->TargetNameLength = TargetName->Length;
3526 RtlCopyMemory( pSymlinkCreate->TargetName,
3528 TargetName->Length);
3530 ulResultLen = PAGE_SIZE;
3533 // Call the service to create the symlink entry
3536 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_SYMLINK,
3537 AFS_REQUEST_FLAG_SYNCHRONOUS,
3540 &ObjectInfo->FileId,
3541 ObjectInfo->VolumeCB->VolumeInformation.Cell,
3542 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
3544 sizeof( AFSCreateSymlinkCB) +
3549 if ( ntStatus == STATUS_FILE_DELETED )
3552 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3553 AFS_TRACE_LEVEL_ERROR,
3554 "AFSCreateSymlink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3555 ObjectInfo->FileId.Cell,
3556 ObjectInfo->FileId.Volume,
3557 ObjectInfo->FileId.Vnode,
3558 ObjectInfo->FileId.Unique,
3561 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3563 ClearFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
3565 SetFlag( ObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
3567 try_return( ntStatus = STATUS_ACCESS_DENIED);
3569 else if( ntStatus != STATUS_SUCCESS)
3572 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3573 AFS_TRACE_LEVEL_ERROR,
3574 "AFSCreateSymlink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3575 ObjectInfo->FileId.Cell,
3576 ObjectInfo->FileId.Volume,
3577 ObjectInfo->FileId.Vnode,
3578 ObjectInfo->FileId.Unique,
3581 try_return( ntStatus);
3585 // After successful creation the open object has been deleted and replaced by
3586 // the actual symlink.
3589 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3591 ClearFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
3593 SetFlag( ObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
3597 if( pSymlinkCreate != NULL)
3600 AFSExFreePoolWithTag( pSymlinkCreate, AFS_SYMLINK_REQUEST_TAG);
3603 if( pSymlinkResult != NULL)
3606 AFSExFreePoolWithTag( pSymlinkResult, AFS_SYMLINK_REQUEST_TAG);