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 = AFSExAllocatePoolWithTag( 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 = AFSExAllocatePoolWithTag( 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 *)AFSExAllocatePoolWithTag( 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 *)AFSExAllocatePoolWithTag( 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 *)AFSExAllocatePoolWithTag( 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 lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
2426 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2427 AFS_TRACE_LEVEL_VERBOSE,
2428 "AFSNotifyHardLink Increment count on %wZ DE %p Cnt %d\n",
2429 &pDirNode->NameInformation.FileName,
2433 ASSERT( lCount >= 0);
2435 *TargetDirectoryCB = pDirNode;
2438 if ( bReleaseTargetParentLock)
2441 AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2444 if ( bReleaseParentLock)
2447 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2450 if( pHardLinkCB != NULL)
2453 AFSExFreePoolWithTag( pHardLinkCB, AFS_HARDLINK_REQUEST_TAG);
2463 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
2465 IN AFSObjectInfoCB *ParentObjectInfo,
2466 IN AFSObjectInfoCB *TargetParentObjectInfo,
2467 IN AFSDirectoryCB *DirectoryCB,
2468 IN UNICODE_STRING *TargetName,
2469 OUT AFSFileID *UpdatedFID)
2472 NTSTATUS ntStatus = STATUS_SUCCESS;
2473 AFSFileRenameCB *pRenameCB = NULL;
2474 AFSFileRenameResultCB *pRenameResultCB = NULL;
2475 ULONG ulResultLen = 0;
2476 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2482 // Init the control block for the request
2485 pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
2487 AFS_RENAME_REQUEST_TAG);
2489 if( pRenameCB == NULL)
2492 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2495 RtlZeroMemory( pRenameCB,
2498 pRenameCB->SourceParentId = ParentObjectInfo->FileId;
2500 pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
2502 pRenameCB->TargetNameLength = TargetName->Length;
2504 RtlCopyMemory( pRenameCB->TargetName,
2506 TargetName->Length);
2509 // Use the same buffer for the result control block
2512 pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
2514 ulResultLen = PAGE_SIZE;
2516 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
2517 AFS_REQUEST_FLAG_SYNCHRONOUS,
2519 &DirectoryCB->NameInformation.FileName,
2520 &ObjectInfo->FileId,
2521 ObjectInfo->VolumeCB->VolumeInformation.Cell,
2522 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2524 sizeof( AFSFileRenameCB) + TargetName->Length,
2528 if( ntStatus != STATUS_SUCCESS)
2531 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2532 AFS_TRACE_LEVEL_ERROR,
2533 "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2534 ObjectInfo->FileId.Cell,
2535 ObjectInfo->FileId.Volume,
2536 ObjectInfo->FileId.Vnode,
2537 ObjectInfo->FileId.Unique,
2540 try_return( ntStatus);
2544 // Update the information from the returned data
2547 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2550 if ( ParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->SourceParentDataVersion.QuadPart - 1)
2553 ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
2558 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2560 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2563 if ( ParentObjectInfo != TargetParentObjectInfo)
2566 AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2569 if ( TargetParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->TargetParentDataVersion.QuadPart - 1)
2572 TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
2577 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2579 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2584 // Move over the short name
2587 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2589 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2590 DirectoryCB->NameInformation.ShortNameLength > 0)
2593 UNICODE_STRING uniShortName;
2595 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2596 uniShortName.MaximumLength = uniShortName.Length;
2597 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2599 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2600 AFS_TRACE_LEVEL_VERBOSE,
2601 "AFSNotifyRename Update old short name %wZ for DE %p for %wZ\n",
2604 &DirectoryCB->NameInformation.FileName));
2606 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2608 RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
2609 pRenameResultCB->DirEnum.ShortName,
2610 DirectoryCB->NameInformation.ShortNameLength);
2612 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2613 uniShortName.MaximumLength = uniShortName.Length;
2614 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2616 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2617 AFS_TRACE_LEVEL_VERBOSE,
2618 "AFSNotifyRename Initialized short name %wZ for DE %p for %wZ\n",
2621 &DirectoryCB->NameInformation.FileName));
2626 UNICODE_STRING uniShortName;
2628 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2629 uniShortName.MaximumLength = uniShortName.Length;
2630 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2632 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2633 AFS_TRACE_LEVEL_VERBOSE,
2634 "AFSNotifyRename Removing old short name %wZ for DE %p for %wZ\n",
2637 &DirectoryCB->NameInformation.FileName));
2639 DirectoryCB->NameInformation.ShortNameLength = 0;
2641 DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2644 if ( ParentObjectInfo != TargetParentObjectInfo)
2647 AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2650 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2652 if( UpdatedFID != NULL)
2654 *UpdatedFID = pRenameResultCB->DirEnum.FileId;
2659 if( pRenameCB != NULL)
2662 AFSExFreePoolWithTag( pRenameCB, AFS_RENAME_REQUEST_TAG);
2670 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
2672 IN BOOLEAN FastCall,
2673 OUT AFSDirEnumEntry **DirEnumEntry)
2676 NTSTATUS ntStatus = STATUS_SUCCESS;
2677 AFSEvalTargetCB stTargetID;
2678 ULONG ulResultBufferLength;
2679 AFSFileEvalResultCB *pEvalResultCB = NULL;
2680 AFSDirEnumEntry *pDirEnumCB = NULL;
2681 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
2682 AFSObjectInfoCB *pParentObjectInfo = NULL;
2687 RtlZeroMemory( &stTargetID,
2688 sizeof( AFSEvalTargetCB));
2690 if ( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2693 pParentObjectInfo = AFSFindObjectInfo( ObjectInfo->VolumeCB,
2694 &ObjectInfo->ParentFileId,
2697 stTargetID.ParentId = ObjectInfo->ParentFileId;
2701 // Allocate our response buffer
2704 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2706 AFS_GENERIC_MEMORY_30_TAG);
2708 if( pEvalResultCB == NULL)
2711 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2715 // Call to the service to evaluate the fid
2718 ulResultBufferLength = PAGE_SIZE;
2723 ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
2726 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
2730 &ObjectInfo->FileId,
2731 ObjectInfo->VolumeCB->VolumeInformation.Cell,
2732 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2734 sizeof( AFSEvalTargetCB),
2736 &ulResultBufferLength);
2738 if( ntStatus != STATUS_SUCCESS)
2742 // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
2746 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2749 if( pParentObjectInfo != NULL)
2752 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2755 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2757 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2759 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2763 try_return( ntStatus);
2767 // A BSOD can occur if the pEvalResultCB->FileType is FILE but the
2768 // ObjectInfo->FileType is something else. The same is true for
2769 // pDirEnumEntry->FileType is DIRECTORY. Perform a sanity check
2770 // to ensure consistency. An inconsistent pDirEnumEntry can be
2771 // produced as a result of invalid status info received from a file
2772 // server. If the types are inconsistent or if the type does not
2773 // match the implied type derived from the vnode (odd values are
2774 // directories and even values are other types), prevent the request
2775 // from completing successfully. This may prevent access to the file or
2776 // directory but will prevent a BSOD.
2779 if ( !AFSIsEqualFID( &ObjectInfo->FileId,
2780 &pEvalResultCB->DirEnum.FileId))
2783 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2786 switch ( pEvalResultCB->DirEnum.FileType)
2789 case AFS_FILE_TYPE_DIRECTORY:
2790 if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x1)
2793 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2796 if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
2797 ObjectInfo->FileType != AFS_FILE_TYPE_DIRECTORY)
2800 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2805 case AFS_FILE_TYPE_FILE:
2806 if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x0)
2809 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2812 if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
2813 ObjectInfo->FileType != AFS_FILE_TYPE_FILE)
2816 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2823 // Validate the parent data version
2826 if ( pParentObjectInfo != NULL)
2829 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2832 if ( pParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2835 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2837 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2840 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2844 // Pass back the dir enum entry
2847 if( DirEnumEntry != NULL)
2850 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2852 AFS_GENERIC_MEMORY_2_TAG);
2854 if( pDirEnumCB == NULL)
2857 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2860 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2861 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2863 *DirEnumEntry = pDirEnumCB;
2868 if ( pParentObjectInfo != NULL)
2871 AFSReleaseObjectInfo( &pParentObjectInfo);
2874 if( pEvalResultCB != NULL)
2877 AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_30_TAG);
2880 if( !NT_SUCCESS( ntStatus))
2883 if( pDirEnumCB != NULL)
2886 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_2_TAG);
2889 *DirEnumEntry = NULL;
2897 AFSEvaluateTargetByName( IN GUID *AuthGroup,
2898 IN AFSObjectInfoCB *ParentObjectInfo,
2899 IN PUNICODE_STRING SourceName,
2901 OUT AFSDirEnumEntry **DirEnumEntry)
2904 NTSTATUS ntStatus = STATUS_SUCCESS;
2905 AFSEvalTargetCB stTargetID;
2906 ULONG ulResultBufferLength;
2907 AFSFileEvalResultCB *pEvalResultCB = NULL;
2908 AFSDirEnumEntry *pDirEnumCB = NULL;
2913 stTargetID.ParentId = ParentObjectInfo->FileId;
2916 // Allocate our response buffer
2919 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2921 AFS_GENERIC_MEMORY_31_TAG);
2923 if( pEvalResultCB == NULL)
2926 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2930 // Call to the service to evaluate the fid
2933 ulResultBufferLength = PAGE_SIZE;
2935 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
2936 AFS_REQUEST_FLAG_SYNCHRONOUS | Flags,
2940 ParentObjectInfo->VolumeCB->VolumeInformation.Cell,
2941 ParentObjectInfo->VolumeCB->VolumeInformation.CellLength,
2943 sizeof( AFSEvalTargetCB),
2945 &ulResultBufferLength);
2947 if( ntStatus != STATUS_SUCCESS)
2950 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2953 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2956 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2958 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2960 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2963 try_return( ntStatus);
2967 // Validate the parent data version
2970 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2973 if ( ParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2976 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2978 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2981 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2984 // Pass back the dir enum entry
2987 if( DirEnumEntry != NULL)
2990 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2992 AFS_GENERIC_MEMORY_3_TAG);
2994 if( pDirEnumCB == NULL)
2997 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3000 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
3001 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
3003 *DirEnumEntry = pDirEnumCB;
3008 if( pEvalResultCB != NULL)
3011 AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_31_TAG);
3014 if( !NT_SUCCESS( ntStatus))
3017 if( pDirEnumCB != NULL)
3020 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_3_TAG);
3023 *DirEnumEntry = NULL;
3031 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
3032 IN AFSFileID *FileID,
3033 OUT AFSVolumeInfoCB *VolumeInformation)
3036 NTSTATUS ntStatus = STATUS_SUCCESS;
3037 ULONG ulResultLen = 0;
3042 ulResultLen = sizeof( AFSVolumeInfoCB);
3044 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
3045 AFS_REQUEST_FLAG_SYNCHRONOUS,
3056 if( ntStatus != STATUS_SUCCESS)
3059 try_return( ntStatus);
3071 AFSRetrieveVolumeSizeInformation( IN GUID *AuthGroup,
3072 IN AFSFileID *FileID,
3073 OUT AFSVolumeSizeInfoCB *VolumeSizeInformation)
3076 NTSTATUS ntStatus = STATUS_SUCCESS;
3077 ULONG ulResultLen = 0;
3082 ulResultLen = sizeof( AFSVolumeSizeInfoCB);
3084 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_SIZE_INFO,
3085 AFS_REQUEST_FLAG_SYNCHRONOUS,
3093 VolumeSizeInformation,
3096 if( ntStatus != STATUS_SUCCESS)
3099 try_return( ntStatus);
3111 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
3112 IN ULONG InputLength,
3113 IN ULONG OutputLength,
3114 IN void *InputDataBuffer,
3115 OUT void *OutputDataBuffer,
3116 OUT ULONG *BytesReturned)
3119 NTSTATUS ntStatus = STATUS_SUCCESS;
3120 ULONG ulResultLen = 0;
3121 MDL *pInputMdl = NULL, *pOutputMdl = NULL;
3122 void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
3123 AFSPipeIORequestCB *pIoRequest = NULL;
3129 // Map the user buffer to a system address
3132 pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
3136 if( pInputSystemBuffer == NULL)
3139 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3142 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
3143 sizeof( AFSPipeIORequestCB) +
3145 AFS_GENERIC_MEMORY_4_TAG);
3147 if( pIoRequest == NULL)
3150 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3153 RtlZeroMemory( pIoRequest,
3154 sizeof( AFSPipeIORequestCB) + InputLength);
3156 pIoRequest->RequestId = Ccb->RequestID;
3158 pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3160 pIoRequest->BufferLength = InputLength;
3162 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
3166 pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
3170 if( pOutputSystemBuffer == NULL)
3173 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3177 // Send the call to the service
3180 ulResultLen = OutputLength;
3182 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
3183 AFS_REQUEST_FLAG_SYNCHRONOUS,
3185 &Ccb->DirectoryCB->NameInformation.FileName,
3190 sizeof( AFSPipeIORequestCB) + InputLength,
3191 pOutputSystemBuffer,
3194 if( ntStatus != STATUS_SUCCESS &&
3195 ntStatus != STATUS_BUFFER_OVERFLOW)
3198 if( NT_SUCCESS( ntStatus))
3201 ntStatus = STATUS_DEVICE_NOT_READY;
3204 try_return( ntStatus);
3208 // Return the bytes processed
3211 *BytesReturned = ulResultLen;
3215 if( pInputMdl != NULL)
3218 MmUnlockPages( pInputMdl);
3220 IoFreeMdl( pInputMdl);
3223 if( pOutputMdl != NULL)
3226 MmUnlockPages( pOutputMdl);
3228 IoFreeMdl( pOutputMdl);
3231 if( pIoRequest != NULL)
3234 AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_4_TAG);
3242 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
3243 IN ULONG InformationClass,
3244 IN ULONG InputLength,
3245 IN void *DataBuffer)
3248 NTSTATUS ntStatus = STATUS_SUCCESS;
3249 AFSPipeInfoRequestCB *pInfoRequest = NULL;
3254 pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
3255 sizeof( AFSPipeInfoRequestCB) +
3257 AFS_GENERIC_MEMORY_5_TAG);
3259 if( pInfoRequest == NULL)
3262 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3265 RtlZeroMemory( pInfoRequest,
3266 sizeof( AFSPipeInfoRequestCB) + InputLength);
3268 pInfoRequest->RequestId = Ccb->RequestID;
3270 pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3272 pInfoRequest->BufferLength = InputLength;
3274 pInfoRequest->InformationClass = InformationClass;
3276 RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
3281 // Send the call to the service
3284 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
3285 AFS_REQUEST_FLAG_SYNCHRONOUS,
3287 &Ccb->DirectoryCB->NameInformation.FileName,
3292 sizeof( AFSPipeInfoRequestCB) + InputLength,
3296 if( ntStatus != STATUS_SUCCESS)
3299 if( NT_SUCCESS( ntStatus))
3302 ntStatus = STATUS_DEVICE_NOT_READY;
3305 try_return( ntStatus);
3310 if( pInfoRequest != NULL)
3313 AFSExFreePoolWithTag( pInfoRequest, AFS_GENERIC_MEMORY_5_TAG);
3321 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
3322 IN ULONG InformationClass,
3323 IN ULONG OutputLength,
3324 IN void *DataBuffer,
3325 OUT ULONG *BytesReturned)
3328 NTSTATUS ntStatus = STATUS_SUCCESS;
3329 AFSPipeInfoRequestCB stInfoRequest;
3330 ULONG ulBytesProcessed = 0;
3335 RtlZeroMemory( &stInfoRequest,
3336 sizeof( AFSPipeInfoRequestCB));
3338 stInfoRequest.RequestId = Ccb->RequestID;
3340 stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3342 stInfoRequest.BufferLength = OutputLength;
3344 stInfoRequest.InformationClass = InformationClass;
3346 ulBytesProcessed = OutputLength;
3349 // Send the call to the service
3352 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
3353 AFS_REQUEST_FLAG_SYNCHRONOUS,
3355 &Ccb->DirectoryCB->NameInformation.FileName,
3360 sizeof( AFSPipeInfoRequestCB),
3364 if( ntStatus != STATUS_SUCCESS)
3367 if( NT_SUCCESS( ntStatus))
3370 ntStatus = STATUS_DEVICE_NOT_READY;
3373 try_return( ntStatus);
3376 *BytesReturned = ulBytesProcessed;
3387 AFSReleaseFid( IN AFSFileID *FileId)
3390 NTSTATUS ntStatus = STATUS_SUCCESS;
3395 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
3412 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
3413 IN LARGE_INTEGER *ExtentOffset,
3417 BOOLEAN bRequestQueued = FALSE;
3418 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3419 AFSCommSrvcCB *pCommSrvc = NULL;
3420 AFSPoolEntry *pPoolEntry = NULL;
3421 AFSRequestExtentsCB *pRequestExtents = NULL;
3427 pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
3429 AFSAcquireShared( &pCommSrvc->IrpPoolLock,
3432 pPoolEntry = pCommSrvc->RequestPoolHead;
3434 while( pPoolEntry != NULL)
3437 if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
3440 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
3443 pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
3445 if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
3446 pRequestExtents->Length == Length)
3449 bRequestQueued = TRUE;
3454 pPoolEntry = pPoolEntry->fLink;
3457 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
3460 return bRequestQueued;
3464 AFSCreateSymlink( IN GUID *AuthGroup,
3465 IN AFSObjectInfoCB *ParentObjectInfo,
3466 IN UNICODE_STRING *FileName,
3467 IN AFSObjectInfoCB *ObjectInfo,
3468 IN UNICODE_STRING *TargetName)
3471 NTSTATUS ntStatus = STATUS_SUCCESS;
3472 AFSCreateSymlinkCB *pSymlinkCreate = NULL;
3473 ULONG ulResultLen = 0;
3474 AFSCreateSymlinkResultCB *pSymlinkResult = NULL;
3480 // Allocate our request and result structures
3483 pSymlinkCreate = (AFSCreateSymlinkCB *)ExAllocatePoolWithTag( PagedPool,
3484 sizeof( AFSCreateSymlinkCB) +
3486 AFS_SYMLINK_REQUEST_TAG);
3488 if( pSymlinkCreate == NULL)
3491 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3494 RtlZeroMemory( pSymlinkCreate,
3495 sizeof( AFSCreateSymlinkCB) +
3496 TargetName->Length);
3498 pSymlinkResult = (AFSCreateSymlinkResultCB *)ExAllocatePoolWithTag( PagedPool,
3500 AFS_SYMLINK_REQUEST_TAG);
3502 if( pSymlinkResult == NULL)
3505 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3508 RtlZeroMemory( pSymlinkResult,
3512 // Populate the request buffer
3515 RtlCopyMemory( &pSymlinkCreate->ParentId,
3516 &ObjectInfo->ParentFileId,
3517 sizeof( AFSFileID));
3519 pSymlinkCreate->TargetNameLength = TargetName->Length;
3521 RtlCopyMemory( pSymlinkCreate->TargetName,
3523 TargetName->Length);
3525 ulResultLen = PAGE_SIZE;
3528 // Call the service to create the symlink entry
3531 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_SYMLINK,
3532 AFS_REQUEST_FLAG_SYNCHRONOUS,
3535 &ObjectInfo->FileId,
3536 ObjectInfo->VolumeCB->VolumeInformation.Cell,
3537 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
3539 sizeof( AFSCreateSymlinkCB) +
3544 if ( ntStatus == STATUS_FILE_DELETED )
3547 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3548 AFS_TRACE_LEVEL_ERROR,
3549 "AFSCreateSymlink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3550 ObjectInfo->FileId.Cell,
3551 ObjectInfo->FileId.Volume,
3552 ObjectInfo->FileId.Vnode,
3553 ObjectInfo->FileId.Unique,
3556 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3558 ClearFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
3560 SetFlag( ObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
3562 try_return( ntStatus = STATUS_ACCESS_DENIED);
3564 else if( ntStatus != STATUS_SUCCESS)
3567 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3568 AFS_TRACE_LEVEL_ERROR,
3569 "AFSCreateSymlink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3570 ObjectInfo->FileId.Cell,
3571 ObjectInfo->FileId.Volume,
3572 ObjectInfo->FileId.Vnode,
3573 ObjectInfo->FileId.Unique,
3576 try_return( ntStatus);
3580 // After successful creation the open object has been deleted and replaced by
3581 // the actual symlink.
3584 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3586 ClearFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
3588 SetFlag( ObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
3592 if( pSymlinkCreate != NULL)
3595 AFSExFreePoolWithTag( pSymlinkCreate, AFS_SYMLINK_REQUEST_TAG);
3598 if( pSymlinkResult != NULL)
3601 AFSExFreePoolWithTag( pSymlinkResult, AFS_SYMLINK_REQUEST_TAG);