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 if( pCurrentDirEntry->ShortNameLength > 0 &&
1021 pDirNode->NameInformation.ShortNameLength > 0)
1023 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1024 AFS_TRACE_LEVEL_VERBOSE,
1025 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name %S New short name %S\n",
1027 &pDirNode->NameInformation.FileName,
1028 ObjectInfoCB->FileId.Cell,
1029 ObjectInfoCB->FileId.Volume,
1030 ObjectInfoCB->FileId.Vnode,
1031 ObjectInfoCB->FileId.Unique,
1032 pDirNode->NameInformation.ShortName,
1033 pCurrentDirEntry->ShortName));
1035 else if( pCurrentDirEntry->ShortNameLength == 0 &&
1036 pDirNode->NameInformation.ShortNameLength > 0)
1039 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1040 AFS_TRACE_LEVEL_VERBOSE,
1041 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name %S New short name NULL\n",
1043 &pDirNode->NameInformation.FileName,
1044 ObjectInfoCB->FileId.Cell,
1045 ObjectInfoCB->FileId.Volume,
1046 ObjectInfoCB->FileId.Vnode,
1047 ObjectInfoCB->FileId.Unique,
1048 pDirNode->NameInformation.ShortName));
1050 else if( pCurrentDirEntry->ShortNameLength > 0 &&
1051 pDirNode->NameInformation.ShortNameLength == 0)
1053 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1054 AFS_TRACE_LEVEL_VERBOSE,
1055 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name %S\n",
1057 &pDirNode->NameInformation.FileName,
1058 ObjectInfoCB->FileId.Cell,
1059 ObjectInfoCB->FileId.Volume,
1060 ObjectInfoCB->FileId.Vnode,
1061 ObjectInfoCB->FileId.Unique,
1062 pCurrentDirEntry->ShortName));
1066 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1067 AFS_TRACE_LEVEL_VERBOSE,
1068 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name NULL\n",
1070 &pDirNode->NameInformation.FileName,
1071 ObjectInfoCB->FileId.Cell,
1072 ObjectInfoCB->FileId.Volume,
1073 ObjectInfoCB->FileId.Vnode,
1074 ObjectInfoCB->FileId.Unique));
1078 // Update the metadata for the entry
1081 if( pObjectInfo->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
1084 AFSUpdateMetaData( pDirNode,
1092 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1094 if( ulResultLen >= ulEntryLength)
1096 ulResultLen -= ulEntryLength;
1110 // File name matches but FileID does not.
1113 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1114 AFS_TRACE_LEVEL_VERBOSE,
1115 "AFSVerifyDirectoryContent Processing dir entry %p %wZ with different FID, same name in parent FID %08lX-%08lX-%08lX-%08lX\n",
1117 &pDirNode->NameInformation.FileName,
1118 ObjectInfoCB->FileId.Cell,
1119 ObjectInfoCB->FileId.Volume,
1120 ObjectInfoCB->FileId.Vnode,
1121 ObjectInfoCB->FileId.Unique));
1124 // Need to tear down this entry and rebuild it below
1127 if( pDirNode->DirOpenReferenceCount <= 0 &&
1128 pDirNode->NameArrayReferenceCount <= 0)
1131 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1132 AFS_TRACE_LEVEL_VERBOSE,
1133 "AFSVerifyDirectoryContent Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1135 &pDirNode->NameInformation.FileName,
1136 pDirNode->ObjectInformation->FileId.Cell,
1137 pDirNode->ObjectInformation->FileId.Volume,
1138 pDirNode->ObjectInformation->FileId.Vnode,
1139 pDirNode->ObjectInformation->FileId.Unique,
1140 pCurrentDirEntry->FileId.Cell,
1141 pCurrentDirEntry->FileId.Volume,
1142 pCurrentDirEntry->FileId.Vnode,
1143 pCurrentDirEntry->FileId.Unique));
1145 AFSDeleteDirEntry( ObjectInfoCB,
1151 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1153 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1154 AFS_TRACE_LEVEL_WARNING,
1155 "AFSVerifyDirectoryContent Different FIDs - removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1157 &pDirNode->NameInformation.FileName,
1158 pDirNode->ObjectInformation->FileId.Cell,
1159 pDirNode->ObjectInformation->FileId.Volume,
1160 pDirNode->ObjectInformation->FileId.Vnode,
1161 pDirNode->ObjectInformation->FileId.Unique,
1162 pCurrentDirEntry->FileId.Cell,
1163 pCurrentDirEntry->FileId.Volume,
1164 pCurrentDirEntry->FileId.Vnode,
1165 pCurrentDirEntry->FileId.Unique));
1167 AFSRemoveNameEntry( ObjectInfoCB,
1174 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1175 AFS_TRACE_LEVEL_VERBOSE,
1176 "AFSVerifyDirectoryContent New entry %wZ for parent FID %08lX-%08lX-%08lX-%08lX\n",
1178 ObjectInfoCB->FileId.Cell,
1179 ObjectInfoCB->FileId.Volume,
1180 ObjectInfoCB->FileId.Vnode,
1181 ObjectInfoCB->FileId.Unique));
1184 pDirNode = AFSInitDirEntry( ObjectInfoCB,
1188 (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1190 if( pDirNode == NULL)
1193 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
1198 AFSUpdateMetaData( pDirNode,
1201 if( pDirNode->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1204 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1205 AFS_TRACE_LEVEL_VERBOSE,
1206 "AFSVerifyDirectoryContent Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
1208 pDirNode->ObjectInformation->FileId.Cell,
1209 pDirNode->ObjectInformation->FileId.Volume,
1210 pDirNode->ObjectInformation->FileId.Vnode,
1211 pDirNode->ObjectInformation->FileId.Unique));
1213 AFSAcquireExcl( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1216 SetFlag( pDirNode->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1218 pDirNode->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1220 AFSReleaseResource( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1224 // Init the short name if we have one
1227 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1228 pCurrentDirEntry->ShortNameLength > 0)
1231 UNICODE_STRING uniShortName;
1233 pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
1235 RtlCopyMemory( pDirNode->NameInformation.ShortName,
1236 pCurrentDirEntry->ShortName,
1237 pDirNode->NameInformation.ShortNameLength);
1240 // Generate the short name index
1243 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1244 uniShortName.MaximumLength = uniShortName.Length;
1245 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1247 if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
1252 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1255 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1256 AFS_TRACE_LEVEL_VERBOSE,
1257 "AFSVerifyDirectoryContent Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1260 &pDirNode->NameInformation.FileName,
1261 pCurrentDirEntry->FileId.Cell,
1262 pCurrentDirEntry->FileId.Volume,
1263 pCurrentDirEntry->FileId.Vnode,
1264 pCurrentDirEntry->FileId.Unique));
1268 pDirNode->NameInformation.ShortNameLength = 0;
1270 RtlZeroMemory( pDirNode->NameInformation.ShortName,
1271 (12 * sizeof( WCHAR)));
1278 // No short name or short names have been disabled
1281 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
1285 // Insert the node into the name tree
1288 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
1290 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
1293 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
1295 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1296 AFS_TRACE_LEVEL_VERBOSE,
1297 "AFSVerifyDirectoryContent Insert DE %p to head of case sensitive tree for %wZ\n",
1299 &pDirNode->NameInformation.FileName));
1304 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1307 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1308 AFS_TRACE_LEVEL_VERBOSE,
1309 "AFSVerifyDirectoryContent Failed to insert DE %p to case sensitive tree for %wZ\n",
1311 &pDirNode->NameInformation.FileName));
1314 // Delete this dir entry and continue on
1317 AFSDeleteDirEntry( ObjectInfoCB,
1320 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1322 if( ulResultLen >= ulEntryLength)
1324 ulResultLen -= ulEntryLength;
1335 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1336 AFS_TRACE_LEVEL_VERBOSE,
1337 "AFSVerifyDirectoryContent Insert DE %p to case sensitive tree for %wZ\n",
1339 &pDirNode->NameInformation.FileName));
1343 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1345 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
1348 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
1350 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
1352 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1353 AFS_TRACE_LEVEL_VERBOSE,
1354 "AFSVerifyDirectoryContent Insert DE %p to head of case insensitive tree for %wZ\n",
1356 &pDirNode->NameInformation.FileName));
1361 AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1364 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1365 AFS_TRACE_LEVEL_VERBOSE,
1366 "AFSVerifyDirectoryContent Insert DE %p to case insensitive tree for %wZ\n",
1368 &pDirNode->NameInformation.FileName));
1371 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
1374 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
1379 (ObjectInfoCB->Specific.Directory.DirectoryNodeListTail)->ListEntry.fLink = pDirNode;
1381 pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
1384 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
1386 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
1388 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
1390 AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1391 AFS_TRACE_LEVEL_VERBOSE,
1392 "AFSVerifyDirectoryContent Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
1393 &pDirNode->NameInformation.FileName,
1394 ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
1395 ObjectInfoCB->FileId.Cell,
1396 ObjectInfoCB->FileId.Volume,
1397 ObjectInfoCB->FileId.Vnode,
1398 ObjectInfoCB->FileId.Unique));
1400 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
1404 // Insert the short name entry if we have a valid short name
1407 if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
1410 ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
1412 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1413 AFS_TRACE_LEVEL_VERBOSE,
1414 "AFSVerifyDirectoryContent Insert DE %p to head of shortname tree for %wZ\n",
1416 &pDirNode->NameInformation.FileName));
1418 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1423 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
1426 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1427 AFS_TRACE_LEVEL_VERBOSE,
1428 "AFSVerifyDirectoryContent Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
1430 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex,
1431 &pDirNode->NameInformation.FileName));
1435 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1437 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1438 AFS_TRACE_LEVEL_VERBOSE,
1439 "AFSVerifyDirectoryContent Insert DE %p to shortname tree for %wZ\n",
1441 &pDirNode->NameInformation.FileName));
1446 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
1452 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1454 if( ulResultLen >= ulEntryLength)
1456 ulResultLen -= ulEntryLength;
1464 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
1467 // Reset the information in the request buffer since it got trampled
1471 pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
1480 if( pBuffer != NULL)
1483 AFSExFreePoolWithTag( pBuffer, AFS_DIR_BUFFER_TAG);
1491 AFSNotifyFileCreate( IN GUID *AuthGroup,
1492 IN AFSObjectInfoCB *ParentObjectInfo,
1493 IN PLARGE_INTEGER FileSize,
1494 IN ULONG FileAttributes,
1495 IN UNICODE_STRING *FileName,
1496 OUT AFSDirectoryCB **DirNode)
1499 NTSTATUS ntStatus = STATUS_SUCCESS;
1500 AFSFileCreateCB stCreateCB;
1501 AFSFileCreateResultCB *pResultCB = NULL;
1502 ULONG ulResultLen = 0;
1503 UNICODE_STRING uniTargetName;
1504 AFSDirectoryCB *pDirNode = NULL;
1507 LARGE_INTEGER liOldDataVersion;
1508 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1509 BOOLEAN bReleaseParentTreeLock = FALSE;
1517 // Init the control block for the request
1520 RtlZeroMemory( &stCreateCB,
1521 sizeof( AFSFileCreateCB));
1523 stCreateCB.ParentId = ParentObjectInfo->FileId;
1525 stCreateCB.AllocationSize = *FileSize;
1527 stCreateCB.FileAttributes = FileAttributes;
1529 stCreateCB.EaSize = 0;
1531 liOldDataVersion = ParentObjectInfo->DataVersion;
1534 // Allocate our return buffer
1537 pResultCB = (AFSFileCreateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1539 AFS_GENERIC_MEMORY_1_TAG);
1541 if( pResultCB == NULL)
1544 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1547 RtlZeroMemory( pResultCB,
1550 ulResultLen = PAGE_SIZE;
1553 // Send the call to the service
1556 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_FILE,
1557 AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_HOLD_FID,
1564 sizeof( AFSFileCreateCB),
1568 if( ntStatus != STATUS_SUCCESS)
1571 if( NT_SUCCESS( ntStatus))
1574 ntStatus = STATUS_DEVICE_NOT_READY;
1577 try_return( ntStatus);
1581 // We may have raced with an invalidation call and a subsequent re-enumeration of this parent
1582 // and though we created the node, it is already in our list. If this is the case then
1583 // look up the entry rather than create a new entry
1584 // The check is to ensure the DV has been modified
1587 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1590 bReleaseParentTreeLock = TRUE;
1592 if( ParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
1595 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1596 AFS_TRACE_LEVEL_WARNING,
1597 "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",
1599 ParentObjectInfo->FileId.Cell,
1600 ParentObjectInfo->FileId.Volume,
1601 ParentObjectInfo->FileId.Vnode,
1602 ParentObjectInfo->FileId.Unique,
1603 ParentObjectInfo->DataVersion.HighPart,
1604 ParentObjectInfo->DataVersion.LowPart,
1605 pResultCB->ParentDataVersion.HighPart,
1606 pResultCB->ParentDataVersion.LowPart));
1609 // We raced so go and lookup the directory entry in the parent
1612 ulCRC = AFSGenerateCRC( FileName,
1615 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1619 if( pDirNode != NULL)
1622 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1623 AFS_TRACE_LEVEL_VERBOSE,
1624 "AFSNotifyFileCreate Located dir entry %p for file %wZ\n",
1628 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
1629 &pResultCB->DirEnum.FileId))
1632 *DirNode = pDirNode;
1634 try_return( ntStatus = STATUS_REPARSE);
1640 // We found an entry that matches the desired name but it is not the
1641 // same as the one that was created for us by the file server.
1644 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1645 AFS_TRACE_LEVEL_ERROR,
1646 "AFSNotifyFileCreate Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
1649 pDirNode->ObjectInformation->FileId.Cell,
1650 pDirNode->ObjectInformation->FileId.Volume,
1651 pDirNode->ObjectInformation->FileId.Vnode,
1652 pDirNode->ObjectInformation->FileId.Unique,
1653 pResultCB->DirEnum.FileId.Cell,
1654 pResultCB->DirEnum.FileId.Volume,
1655 pResultCB->DirEnum.FileId.Vnode,
1656 pResultCB->DirEnum.FileId.Unique));
1658 if( pDirNode->DirOpenReferenceCount <= 0 &&
1659 pDirNode->NameArrayReferenceCount <= 0)
1662 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1663 AFS_TRACE_LEVEL_VERBOSE,
1664 "AFSNotifyFileCreate Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1666 &pDirNode->NameInformation.FileName,
1667 pDirNode->ObjectInformation->FileId.Cell,
1668 pDirNode->ObjectInformation->FileId.Volume,
1669 pDirNode->ObjectInformation->FileId.Vnode,
1670 pDirNode->ObjectInformation->FileId.Unique,
1671 pResultCB->DirEnum.FileId.Cell,
1672 pResultCB->DirEnum.FileId.Volume,
1673 pResultCB->DirEnum.FileId.Vnode,
1674 pResultCB->DirEnum.FileId.Unique));
1676 AFSDeleteDirEntry( ParentObjectInfo,
1682 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1684 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1685 AFS_TRACE_LEVEL_VERBOSE,
1686 "AFSNotifyFileCreate Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1688 &pDirNode->NameInformation.FileName,
1689 pDirNode->ObjectInformation->FileId.Cell,
1690 pDirNode->ObjectInformation->FileId.Volume,
1691 pDirNode->ObjectInformation->FileId.Vnode,
1692 pDirNode->ObjectInformation->FileId.Unique,
1693 pResultCB->DirEnum.FileId.Cell,
1694 pResultCB->DirEnum.FileId.Volume,
1695 pResultCB->DirEnum.FileId.Vnode,
1696 pResultCB->DirEnum.FileId.Unique));
1698 AFSRemoveNameEntry( ParentObjectInfo,
1707 // We are unsure of our current data so set the verify flag. It may already be set
1708 // but no big deal to reset it
1711 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1713 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1716 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1717 AFS_TRACE_LEVEL_VERBOSE,
1718 "AFSNotifyFileCreate Creating new entry %wZ\n",
1722 // Initialize the directory entry
1725 uniTargetName.Length = (USHORT)pResultCB->DirEnum.TargetNameLength;
1727 uniTargetName.MaximumLength = uniTargetName.Length;
1729 uniTargetName.Buffer = (WCHAR *)((char *)&pResultCB->DirEnum + pResultCB->DirEnum.TargetNameOffset);
1731 pDirNode = AFSInitDirEntry( ParentObjectInfo,
1734 &pResultCB->DirEnum,
1735 (ULONG)InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1737 if( pDirNode == NULL)
1740 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1742 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1744 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1748 // Init the short name if we have one
1751 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1752 pResultCB->DirEnum.ShortNameLength > 0)
1755 UNICODE_STRING uniShortName;
1757 pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
1759 RtlCopyMemory( pDirNode->NameInformation.ShortName,
1760 pResultCB->DirEnum.ShortName,
1761 pDirNode->NameInformation.ShortNameLength);
1764 // Generate the short name index
1767 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1768 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1770 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1773 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1774 AFS_TRACE_LEVEL_VERBOSE,
1775 "AFSNotifyFileCreate Initialized short name %wZ for DE %p for %wZ\n",
1778 &pDirNode->NameInformation.FileName));
1783 // No short name or short names are disabled
1786 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
1789 if ( !BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1793 // Update the parent data version
1796 ParentObjectInfo->DataVersion = pResultCB->ParentDataVersion;
1798 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1799 AFS_TRACE_LEVEL_VERBOSE,
1800 "AFSNotifyFileCreate entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
1802 ParentObjectInfo->FileId.Cell,
1803 ParentObjectInfo->FileId.Volume,
1804 ParentObjectInfo->FileId.Vnode,
1805 ParentObjectInfo->FileId.Unique,
1806 ParentObjectInfo->DataVersion.QuadPart));
1810 // Return the directory node
1813 *DirNode = pDirNode;
1817 if ( *DirNode != NULL)
1820 lCount = InterlockedIncrement( &(*DirNode)->DirOpenReferenceCount);
1822 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1823 AFS_TRACE_LEVEL_VERBOSE,
1824 "AFSNotifyFileCreate Increment count on %wZ DE %p Cnt %d\n",
1825 &(*DirNode)->NameInformation.FileName,
1829 ASSERT( lCount >= 0);
1832 if ( bReleaseParentTreeLock)
1835 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1838 if( pResultCB != NULL)
1841 AFSExFreePoolWithTag( pResultCB, AFS_GENERIC_MEMORY_1_TAG);
1849 AFSUpdateFileInformation( IN AFSFileID *ParentFid,
1850 IN AFSObjectInfoCB *ObjectInfo,
1854 NTSTATUS ntStatus = STATUS_SUCCESS;
1855 AFSFileUpdateCB stUpdateCB;
1856 ULONG ulResultLen = 0;
1857 AFSFileUpdateResultCB *pUpdateResultCB = NULL;
1863 // Init the control block for the request
1866 RtlZeroMemory( &stUpdateCB,
1867 sizeof( AFSFileUpdateCB));
1869 stUpdateCB.AllocationSize = ObjectInfo->EndOfFile;
1871 stUpdateCB.FileAttributes = ObjectInfo->FileAttributes;
1873 stUpdateCB.EaSize = ObjectInfo->EaSize;
1875 stUpdateCB.ParentId = *ParentFid;
1877 stUpdateCB.LastAccessTime = ObjectInfo->LastAccessTime;
1879 stUpdateCB.CreateTime = ObjectInfo->CreationTime;
1881 stUpdateCB.ChangeTime = ObjectInfo->ChangeTime;
1883 stUpdateCB.LastWriteTime = ObjectInfo->LastWriteTime;
1885 pUpdateResultCB = (AFSFileUpdateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1887 AFS_UPDATE_RESULT_TAG);
1889 if( pUpdateResultCB == NULL)
1892 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1895 ulResultLen = PAGE_SIZE;
1897 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_UPDATE_FILE,
1898 AFS_REQUEST_FLAG_SYNCHRONOUS,
1901 &ObjectInfo->FileId,
1902 ObjectInfo->VolumeCB->VolumeInformation.Cell,
1903 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
1905 sizeof( AFSFileUpdateCB),
1909 if( ntStatus != STATUS_SUCCESS)
1912 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1913 AFS_TRACE_LEVEL_ERROR,
1914 "AFSUpdateFileInformation failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1915 ObjectInfo->FileId.Cell,
1916 ObjectInfo->FileId.Volume,
1917 ObjectInfo->FileId.Vnode,
1918 ObjectInfo->FileId.Unique,
1921 try_return( ntStatus);
1925 // Update the data version
1928 AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1931 if ( !BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1934 ObjectInfo->DataVersion = pUpdateResultCB->DirEnum.DataVersion;
1937 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1941 if( pUpdateResultCB != NULL)
1944 AFSExFreePoolWithTag( pUpdateResultCB, AFS_UPDATE_RESULT_TAG);
1952 AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
1954 IN BOOLEAN CheckOnly)
1956 NTSTATUS ntStatus = STATUS_SUCCESS;
1957 ULONG ulResultLen = 0;
1958 AFSFileDeleteCB stDelete;
1959 AFSFileDeleteResultCB stDeleteResult;
1960 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1961 AFSObjectInfoCB *pObjectInfo = NULL;
1962 AFSObjectInfoCB *pParentObjectInfo = NULL;
1967 pObjectInfo = DirectoryCB->ObjectInformation;
1969 pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
1970 &pObjectInfo->ParentFileId,
1973 stDelete.ParentId = pObjectInfo->ParentFileId;
1975 stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
1977 ulResultLen = sizeof( AFSFileDeleteResultCB);
1981 ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
1984 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
1987 &DirectoryCB->NameInformation.FileName,
1988 &pObjectInfo->FileId,
1989 pObjectInfo->VolumeCB->VolumeInformation.Cell,
1990 pObjectInfo->VolumeCB->VolumeInformation.CellLength,
1992 sizeof( AFSFileDeleteCB),
1996 if( ntStatus != STATUS_SUCCESS)
1999 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2000 AFS_TRACE_LEVEL_ERROR,
2001 "AFSNotifyDelete failed ParentFID %08lX-%08lX-%08lX-%08lX %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2002 stDelete.ParentId.Cell,
2003 stDelete.ParentId.Volume,
2004 stDelete.ParentId.Vnode,
2005 stDelete.ParentId.Unique,
2006 &DirectoryCB->NameInformation.FileName,
2007 pObjectInfo->FileId.Cell,
2008 pObjectInfo->FileId.Volume,
2009 pObjectInfo->FileId.Vnode,
2010 pObjectInfo->FileId.Unique,
2013 try_return( ntStatus);
2016 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2023 // Validate the parent data version
2026 if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
2029 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2031 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2038 // Update the parent data version
2041 if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart - 1)
2044 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2046 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2052 // TODO -- The entry must be removed from the directory at which point the
2053 // Directory data version number can be updated. Until then we must force
2056 // pParentObjectInfor->DataVersion.QuadPart = stDeleteResult.ParentDataVersion.QuadPart;
2059 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2061 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2065 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2069 if ( pParentObjectInfo)
2072 AFSReleaseObjectInfo( &pParentObjectInfo);
2081 AFSNotifyHardLink( IN AFSObjectInfoCB *ObjectInfo,
2083 IN AFSObjectInfoCB *ParentObjectInfo,
2084 IN AFSObjectInfoCB *TargetParentObjectInfo,
2085 IN AFSDirectoryCB *SourceDirectoryCB,
2086 IN UNICODE_STRING *TargetName,
2087 IN BOOLEAN bReplaceIfExists,
2088 OUT AFSDirectoryCB **TargetDirectoryCB)
2091 NTSTATUS ntStatus = STATUS_SUCCESS;
2092 AFSFileHardLinkCB *pHardLinkCB = NULL;
2093 AFSFileHardLinkResultCB *pResultCB = NULL;
2094 ULONG ulResultLen = 0;
2095 AFSDirectoryCB *pDirNode = NULL;
2097 BOOLEAN bReleaseParentLock = FALSE, bReleaseTargetParentLock = FALSE;
2098 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2105 // Init the control block for the request
2108 pHardLinkCB = (AFSFileHardLinkCB *)AFSExAllocatePoolWithTag( PagedPool,
2110 AFS_HARDLINK_REQUEST_TAG);
2112 if( pHardLinkCB == NULL)
2115 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2118 RtlZeroMemory( pHardLinkCB,
2121 pHardLinkCB->SourceParentId = ParentObjectInfo->FileId;
2123 pHardLinkCB->TargetParentId = TargetParentObjectInfo->FileId;
2125 pHardLinkCB->TargetNameLength = TargetName->Length;
2127 RtlCopyMemory( pHardLinkCB->TargetName,
2129 TargetName->Length);
2131 pHardLinkCB->bReplaceIfExists = bReplaceIfExists;
2134 // Use the same buffer for the result control block
2137 pResultCB = (AFSFileHardLinkResultCB *)pHardLinkCB;
2139 ulResultLen = PAGE_SIZE;
2141 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_HARDLINK_FILE,
2142 AFS_REQUEST_FLAG_SYNCHRONOUS,
2144 &SourceDirectoryCB->NameInformation.FileName,
2145 &ObjectInfo->FileId,
2146 ObjectInfo->VolumeCB->VolumeInformation.Cell,
2147 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2149 sizeof( AFSFileHardLinkCB) + TargetName->Length,
2153 if( ntStatus != STATUS_SUCCESS)
2156 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2157 AFS_TRACE_LEVEL_ERROR,
2158 "AFSNotifyHardLink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2159 ObjectInfo->FileId.Cell,
2160 ObjectInfo->FileId.Volume,
2161 ObjectInfo->FileId.Vnode,
2162 ObjectInfo->FileId.Unique,
2165 try_return( ntStatus);
2169 // Update the information from the returned data
2172 if ( ParentObjectInfo != TargetParentObjectInfo)
2175 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2178 bReleaseParentLock = TRUE;
2180 if ( ParentObjectInfo->DataVersion.QuadPart == pResultCB->SourceParentDataVersion.QuadPart - 1)
2183 ParentObjectInfo->DataVersion = pResultCB->SourceParentDataVersion;
2188 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2190 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2194 AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2197 bReleaseTargetParentLock = TRUE;
2199 if ( TargetParentObjectInfo->DataVersion.QuadPart == pResultCB->TargetParentDataVersion.QuadPart - 1)
2202 TargetParentObjectInfo->DataVersion = pResultCB->TargetParentDataVersion;
2207 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2208 AFS_TRACE_LEVEL_WARNING,
2209 "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",
2211 TargetParentObjectInfo->FileId.Cell,
2212 TargetParentObjectInfo->FileId.Volume,
2213 TargetParentObjectInfo->FileId.Vnode,
2214 TargetParentObjectInfo->FileId.Unique,
2215 TargetParentObjectInfo->DataVersion.HighPart,
2216 TargetParentObjectInfo->DataVersion.LowPart,
2217 pResultCB->TargetParentDataVersion.HighPart,
2218 pResultCB->TargetParentDataVersion.LowPart));
2221 // We raced so go and lookup the directory entry in the parent
2224 ulCRC = AFSGenerateCRC( TargetName,
2227 AFSLocateCaseSensitiveDirEntry( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2231 if( pDirNode != NULL)
2234 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2235 AFS_TRACE_LEVEL_VERBOSE,
2236 "AFSNotifyHardLink Located dir entry %p for file %wZ\n",
2240 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2241 &pResultCB->DirEnum.FileId))
2244 try_return( ntStatus = STATUS_REPARSE);
2250 // We found an entry that matches the desired name but it is not the
2251 // same as the one that was created for us by the file server.
2254 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2255 AFS_TRACE_LEVEL_ERROR,
2256 "AFSNotifyHardLink Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
2259 pDirNode->ObjectInformation->FileId.Cell,
2260 pDirNode->ObjectInformation->FileId.Volume,
2261 pDirNode->ObjectInformation->FileId.Vnode,
2262 pDirNode->ObjectInformation->FileId.Unique,
2263 pResultCB->DirEnum.FileId.Cell,
2264 pResultCB->DirEnum.FileId.Volume,
2265 pResultCB->DirEnum.FileId.Vnode,
2266 pResultCB->DirEnum.FileId.Unique));
2268 if( pDirNode->DirOpenReferenceCount <= 0 &&
2269 pDirNode->NameArrayReferenceCount <= 0)
2272 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2273 AFS_TRACE_LEVEL_VERBOSE,
2274 "AFSNotifyHardLink Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2276 &pDirNode->NameInformation.FileName,
2277 pDirNode->ObjectInformation->FileId.Cell,
2278 pDirNode->ObjectInformation->FileId.Volume,
2279 pDirNode->ObjectInformation->FileId.Vnode,
2280 pDirNode->ObjectInformation->FileId.Unique,
2281 pResultCB->DirEnum.FileId.Cell,
2282 pResultCB->DirEnum.FileId.Volume,
2283 pResultCB->DirEnum.FileId.Vnode,
2284 pResultCB->DirEnum.FileId.Unique));
2286 AFSDeleteDirEntry( TargetParentObjectInfo,
2292 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2294 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2295 AFS_TRACE_LEVEL_VERBOSE,
2296 "AFSNotifyHardLink Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2298 &pDirNode->NameInformation.FileName,
2299 pDirNode->ObjectInformation->FileId.Cell,
2300 pDirNode->ObjectInformation->FileId.Volume,
2301 pDirNode->ObjectInformation->FileId.Vnode,
2302 pDirNode->ObjectInformation->FileId.Unique,
2303 pResultCB->DirEnum.FileId.Cell,
2304 pResultCB->DirEnum.FileId.Volume,
2305 pResultCB->DirEnum.FileId.Vnode,
2306 pResultCB->DirEnum.FileId.Unique));
2308 AFSRemoveNameEntry( TargetParentObjectInfo,
2317 // We are unsure of our current data so set the verify flag. It may already be set
2318 // but no big deal to reset it
2321 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2323 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2327 // Create the hard link entry
2330 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2331 AFS_TRACE_LEVEL_VERBOSE,
2332 "AFSNotifyHardLink Creating new entry %wZ\n",
2336 // Initialize the directory entry
2339 pDirNode = AFSInitDirEntry( TargetParentObjectInfo,
2342 &pResultCB->DirEnum,
2343 (ULONG)InterlockedIncrement( &TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
2345 if( pDirNode == NULL)
2348 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2350 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2352 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2356 // Init the short name if we have one
2359 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2360 pResultCB->DirEnum.ShortNameLength > 0)
2363 UNICODE_STRING uniShortName;
2365 pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
2367 RtlCopyMemory( pDirNode->NameInformation.ShortName,
2368 pResultCB->DirEnum.ShortName,
2369 pDirNode->NameInformation.ShortNameLength);
2372 // Generate the short name index
2375 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
2376 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
2378 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
2381 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2382 AFS_TRACE_LEVEL_VERBOSE,
2383 "AFSNotifyHardLink Initialized short name %wZ for DE %p for %wZ\n",
2386 &pDirNode->NameInformation.FileName));
2391 // No short name or short names are disabled
2394 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2397 if ( !BooleanFlagOn( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2401 // Update the target parent data version
2404 TargetParentObjectInfo->DataVersion = pResultCB->TargetParentDataVersion;
2406 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2407 AFS_TRACE_LEVEL_VERBOSE,
2408 "AFSNotifyHardLink entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
2410 TargetParentObjectInfo->FileId.Cell,
2411 TargetParentObjectInfo->FileId.Volume,
2412 TargetParentObjectInfo->FileId.Vnode,
2413 TargetParentObjectInfo->FileId.Unique,
2414 TargetParentObjectInfo->DataVersion.QuadPart));
2419 if ( TargetDirectoryCB != NULL)
2422 lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
2424 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2425 AFS_TRACE_LEVEL_VERBOSE,
2426 "AFSNotifyHardLink Increment count on %wZ DE %p Cnt %d\n",
2427 &pDirNode->NameInformation.FileName,
2431 ASSERT( lCount >= 0);
2433 *TargetDirectoryCB = pDirNode;
2436 if ( bReleaseTargetParentLock)
2439 AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2442 if ( bReleaseParentLock)
2445 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2448 if( pHardLinkCB != NULL)
2451 AFSExFreePoolWithTag( pHardLinkCB, AFS_HARDLINK_REQUEST_TAG);
2461 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
2463 IN AFSObjectInfoCB *ParentObjectInfo,
2464 IN AFSObjectInfoCB *TargetParentObjectInfo,
2465 IN AFSDirectoryCB *DirectoryCB,
2466 IN UNICODE_STRING *TargetName,
2467 OUT AFSFileID *UpdatedFID)
2470 NTSTATUS ntStatus = STATUS_SUCCESS;
2471 AFSFileRenameCB *pRenameCB = NULL;
2472 AFSFileRenameResultCB *pRenameResultCB = NULL;
2473 ULONG ulResultLen = 0;
2474 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2480 // Init the control block for the request
2483 pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
2485 AFS_RENAME_REQUEST_TAG);
2487 if( pRenameCB == NULL)
2490 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2493 RtlZeroMemory( pRenameCB,
2496 pRenameCB->SourceParentId = ParentObjectInfo->FileId;
2498 pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
2500 pRenameCB->TargetNameLength = TargetName->Length;
2502 RtlCopyMemory( pRenameCB->TargetName,
2504 TargetName->Length);
2507 // Use the same buffer for the result control block
2510 pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
2512 ulResultLen = PAGE_SIZE;
2514 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
2515 AFS_REQUEST_FLAG_SYNCHRONOUS,
2517 &DirectoryCB->NameInformation.FileName,
2518 &ObjectInfo->FileId,
2519 ObjectInfo->VolumeCB->VolumeInformation.Cell,
2520 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2522 sizeof( AFSFileRenameCB) + TargetName->Length,
2526 if( ntStatus != STATUS_SUCCESS)
2529 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2530 AFS_TRACE_LEVEL_ERROR,
2531 "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2532 ObjectInfo->FileId.Cell,
2533 ObjectInfo->FileId.Volume,
2534 ObjectInfo->FileId.Vnode,
2535 ObjectInfo->FileId.Unique,
2538 try_return( ntStatus);
2542 // Update the information from the returned data
2545 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2548 if ( ParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->SourceParentDataVersion.QuadPart - 1)
2551 ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
2556 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2558 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2561 if ( ParentObjectInfo != TargetParentObjectInfo)
2564 AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2567 if ( TargetParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->TargetParentDataVersion.QuadPart - 1)
2570 TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
2575 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2577 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2582 // Move over the short name
2585 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2587 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2588 DirectoryCB->NameInformation.ShortNameLength > 0)
2591 UNICODE_STRING uniShortName;
2593 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2594 uniShortName.MaximumLength = uniShortName.Length;
2595 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2597 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2598 AFS_TRACE_LEVEL_VERBOSE,
2599 "AFSNotifyRename Update old short name %wZ for DE %p for %wZ\n",
2602 &DirectoryCB->NameInformation.FileName));
2604 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2606 RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
2607 pRenameResultCB->DirEnum.ShortName,
2608 DirectoryCB->NameInformation.ShortNameLength);
2610 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2611 uniShortName.MaximumLength = uniShortName.Length;
2612 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2614 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2615 AFS_TRACE_LEVEL_VERBOSE,
2616 "AFSNotifyRename Initialized short name %wZ for DE %p for %wZ\n",
2619 &DirectoryCB->NameInformation.FileName));
2624 UNICODE_STRING uniShortName;
2626 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2627 uniShortName.MaximumLength = uniShortName.Length;
2628 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2630 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2631 AFS_TRACE_LEVEL_VERBOSE,
2632 "AFSNotifyRename Removing old short name %wZ for DE %p for %wZ\n",
2635 &DirectoryCB->NameInformation.FileName));
2637 DirectoryCB->NameInformation.ShortNameLength = 0;
2639 DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2642 if ( ParentObjectInfo != TargetParentObjectInfo)
2645 AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2648 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2650 if( UpdatedFID != NULL)
2652 *UpdatedFID = pRenameResultCB->DirEnum.FileId;
2657 if( pRenameCB != NULL)
2660 AFSExFreePoolWithTag( pRenameCB, AFS_RENAME_REQUEST_TAG);
2668 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
2670 IN BOOLEAN FastCall,
2671 OUT AFSDirEnumEntry **DirEnumEntry)
2674 NTSTATUS ntStatus = STATUS_SUCCESS;
2675 AFSEvalTargetCB stTargetID;
2676 ULONG ulResultBufferLength;
2677 AFSFileEvalResultCB *pEvalResultCB = NULL;
2678 AFSDirEnumEntry *pDirEnumCB = NULL;
2679 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
2680 AFSObjectInfoCB *pParentObjectInfo = NULL;
2685 RtlZeroMemory( &stTargetID,
2686 sizeof( AFSEvalTargetCB));
2688 if ( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2691 pParentObjectInfo = AFSFindObjectInfo( ObjectInfo->VolumeCB,
2692 &ObjectInfo->ParentFileId,
2695 stTargetID.ParentId = ObjectInfo->ParentFileId;
2699 // Allocate our response buffer
2702 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2704 AFS_GENERIC_MEMORY_30_TAG);
2706 if( pEvalResultCB == NULL)
2709 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2713 // Call to the service to evaluate the fid
2716 ulResultBufferLength = PAGE_SIZE;
2721 ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
2724 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
2728 &ObjectInfo->FileId,
2729 ObjectInfo->VolumeCB->VolumeInformation.Cell,
2730 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2732 sizeof( AFSEvalTargetCB),
2734 &ulResultBufferLength);
2736 if( ntStatus != STATUS_SUCCESS)
2740 // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
2744 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2747 if( pParentObjectInfo != NULL)
2750 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2753 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2755 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2757 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2761 try_return( ntStatus);
2765 // A BSOD can occur if the pEvalResultCB->FileType is FILE but the
2766 // ObjectInfo->FileType is something else. The same is true for
2767 // pDirEnumEntry->FileType is DIRECTORY. Perform a sanity check
2768 // to ensure consistency. An inconsistent pDirEnumEntry can be
2769 // produced as a result of invalid status info received from a file
2770 // server. If the types are inconsistent or if the type does not
2771 // match the implied type derived from the vnode (odd values are
2772 // directories and even values are other types), prevent the request
2773 // from completing successfully. This may prevent access to the file or
2774 // directory but will prevent a BSOD.
2777 if ( !AFSIsEqualFID( &ObjectInfo->FileId,
2778 &pEvalResultCB->DirEnum.FileId))
2781 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2784 switch ( pEvalResultCB->DirEnum.FileType)
2787 case AFS_FILE_TYPE_DIRECTORY:
2788 if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x1)
2791 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2794 if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
2795 ObjectInfo->FileType != AFS_FILE_TYPE_DIRECTORY)
2798 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2803 case AFS_FILE_TYPE_FILE:
2804 if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x0)
2807 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2810 if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
2811 ObjectInfo->FileType != AFS_FILE_TYPE_FILE)
2814 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2821 // Validate the parent data version
2824 if ( pParentObjectInfo != NULL)
2827 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2830 if ( pParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2833 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2835 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2838 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2842 // Pass back the dir enum entry
2845 if( DirEnumEntry != NULL)
2848 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2850 AFS_GENERIC_MEMORY_2_TAG);
2852 if( pDirEnumCB == NULL)
2855 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2858 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2859 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2861 *DirEnumEntry = pDirEnumCB;
2866 if ( pParentObjectInfo != NULL)
2869 AFSReleaseObjectInfo( &pParentObjectInfo);
2872 if( pEvalResultCB != NULL)
2875 AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_30_TAG);
2878 if( !NT_SUCCESS( ntStatus))
2881 if( pDirEnumCB != NULL)
2884 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_2_TAG);
2887 *DirEnumEntry = NULL;
2895 AFSEvaluateTargetByName( IN GUID *AuthGroup,
2896 IN AFSObjectInfoCB *ParentObjectInfo,
2897 IN PUNICODE_STRING SourceName,
2899 OUT AFSDirEnumEntry **DirEnumEntry)
2902 NTSTATUS ntStatus = STATUS_SUCCESS;
2903 AFSEvalTargetCB stTargetID;
2904 ULONG ulResultBufferLength;
2905 AFSFileEvalResultCB *pEvalResultCB = NULL;
2906 AFSDirEnumEntry *pDirEnumCB = NULL;
2911 stTargetID.ParentId = ParentObjectInfo->FileId;
2914 // Allocate our response buffer
2917 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2919 AFS_GENERIC_MEMORY_31_TAG);
2921 if( pEvalResultCB == NULL)
2924 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2928 // Call to the service to evaluate the fid
2931 ulResultBufferLength = PAGE_SIZE;
2933 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
2934 AFS_REQUEST_FLAG_SYNCHRONOUS | Flags,
2938 ParentObjectInfo->VolumeCB->VolumeInformation.Cell,
2939 ParentObjectInfo->VolumeCB->VolumeInformation.CellLength,
2941 sizeof( AFSEvalTargetCB),
2943 &ulResultBufferLength);
2945 if( ntStatus != STATUS_SUCCESS)
2948 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2951 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2954 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2956 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2958 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2961 try_return( ntStatus);
2965 // Validate the parent data version
2968 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2971 if ( ParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2974 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2976 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2979 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2982 // Pass back the dir enum entry
2985 if( DirEnumEntry != NULL)
2988 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2990 AFS_GENERIC_MEMORY_3_TAG);
2992 if( pDirEnumCB == NULL)
2995 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2998 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2999 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
3001 *DirEnumEntry = pDirEnumCB;
3006 if( pEvalResultCB != NULL)
3009 AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_31_TAG);
3012 if( !NT_SUCCESS( ntStatus))
3015 if( pDirEnumCB != NULL)
3018 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_3_TAG);
3021 *DirEnumEntry = NULL;
3029 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
3030 IN AFSFileID *FileID,
3031 OUT AFSVolumeInfoCB *VolumeInformation)
3034 NTSTATUS ntStatus = STATUS_SUCCESS;
3035 ULONG ulResultLen = 0;
3040 ulResultLen = sizeof( AFSVolumeInfoCB);
3042 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
3043 AFS_REQUEST_FLAG_SYNCHRONOUS,
3054 if( ntStatus != STATUS_SUCCESS)
3057 try_return( ntStatus);
3069 AFSRetrieveVolumeSizeInformation( IN GUID *AuthGroup,
3070 IN AFSFileID *FileID,
3071 OUT AFSVolumeSizeInfoCB *VolumeSizeInformation)
3074 NTSTATUS ntStatus = STATUS_SUCCESS;
3075 ULONG ulResultLen = 0;
3080 ulResultLen = sizeof( AFSVolumeSizeInfoCB);
3082 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_SIZE_INFO,
3083 AFS_REQUEST_FLAG_SYNCHRONOUS,
3091 VolumeSizeInformation,
3094 if( ntStatus != STATUS_SUCCESS)
3097 try_return( ntStatus);
3109 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
3110 IN ULONG InputLength,
3111 IN ULONG OutputLength,
3112 IN void *InputDataBuffer,
3113 OUT void *OutputDataBuffer,
3114 OUT ULONG *BytesReturned)
3117 NTSTATUS ntStatus = STATUS_SUCCESS;
3118 ULONG ulResultLen = 0;
3119 MDL *pInputMdl = NULL, *pOutputMdl = NULL;
3120 void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
3121 AFSPipeIORequestCB *pIoRequest = NULL;
3127 // Map the user buffer to a system address
3130 pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
3134 if( pInputSystemBuffer == NULL)
3137 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3140 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
3141 sizeof( AFSPipeIORequestCB) +
3143 AFS_GENERIC_MEMORY_4_TAG);
3145 if( pIoRequest == NULL)
3148 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3151 RtlZeroMemory( pIoRequest,
3152 sizeof( AFSPipeIORequestCB) + InputLength);
3154 pIoRequest->RequestId = Ccb->RequestID;
3156 pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3158 pIoRequest->BufferLength = InputLength;
3160 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
3164 pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
3168 if( pOutputSystemBuffer == NULL)
3171 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3175 // Send the call to the service
3178 ulResultLen = OutputLength;
3180 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
3181 AFS_REQUEST_FLAG_SYNCHRONOUS,
3183 &Ccb->DirectoryCB->NameInformation.FileName,
3188 sizeof( AFSPipeIORequestCB) + InputLength,
3189 pOutputSystemBuffer,
3192 if( ntStatus != STATUS_SUCCESS &&
3193 ntStatus != STATUS_BUFFER_OVERFLOW)
3196 if( NT_SUCCESS( ntStatus))
3199 ntStatus = STATUS_DEVICE_NOT_READY;
3202 try_return( ntStatus);
3206 // Return the bytes processed
3209 *BytesReturned = ulResultLen;
3213 if( pInputMdl != NULL)
3216 MmUnlockPages( pInputMdl);
3218 IoFreeMdl( pInputMdl);
3221 if( pOutputMdl != NULL)
3224 MmUnlockPages( pOutputMdl);
3226 IoFreeMdl( pOutputMdl);
3229 if( pIoRequest != NULL)
3232 AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_4_TAG);
3240 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
3241 IN ULONG InformationClass,
3242 IN ULONG InputLength,
3243 IN void *DataBuffer)
3246 NTSTATUS ntStatus = STATUS_SUCCESS;
3247 AFSPipeInfoRequestCB *pInfoRequest = NULL;
3252 pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
3253 sizeof( AFSPipeInfoRequestCB) +
3255 AFS_GENERIC_MEMORY_5_TAG);
3257 if( pInfoRequest == NULL)
3260 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3263 RtlZeroMemory( pInfoRequest,
3264 sizeof( AFSPipeInfoRequestCB) + InputLength);
3266 pInfoRequest->RequestId = Ccb->RequestID;
3268 pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3270 pInfoRequest->BufferLength = InputLength;
3272 pInfoRequest->InformationClass = InformationClass;
3274 RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
3279 // Send the call to the service
3282 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
3283 AFS_REQUEST_FLAG_SYNCHRONOUS,
3285 &Ccb->DirectoryCB->NameInformation.FileName,
3290 sizeof( AFSPipeInfoRequestCB) + InputLength,
3294 if( ntStatus != STATUS_SUCCESS)
3297 if( NT_SUCCESS( ntStatus))
3300 ntStatus = STATUS_DEVICE_NOT_READY;
3303 try_return( ntStatus);
3308 if( pInfoRequest != NULL)
3311 AFSExFreePoolWithTag( pInfoRequest, AFS_GENERIC_MEMORY_5_TAG);
3319 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
3320 IN ULONG InformationClass,
3321 IN ULONG OutputLength,
3322 IN void *DataBuffer,
3323 OUT ULONG *BytesReturned)
3326 NTSTATUS ntStatus = STATUS_SUCCESS;
3327 AFSPipeInfoRequestCB stInfoRequest;
3328 ULONG ulBytesProcessed = 0;
3333 RtlZeroMemory( &stInfoRequest,
3334 sizeof( AFSPipeInfoRequestCB));
3336 stInfoRequest.RequestId = Ccb->RequestID;
3338 stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3340 stInfoRequest.BufferLength = OutputLength;
3342 stInfoRequest.InformationClass = InformationClass;
3344 ulBytesProcessed = OutputLength;
3347 // Send the call to the service
3350 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
3351 AFS_REQUEST_FLAG_SYNCHRONOUS,
3353 &Ccb->DirectoryCB->NameInformation.FileName,
3358 sizeof( AFSPipeInfoRequestCB),
3362 if( ntStatus != STATUS_SUCCESS)
3365 if( NT_SUCCESS( ntStatus))
3368 ntStatus = STATUS_DEVICE_NOT_READY;
3371 try_return( ntStatus);
3374 *BytesReturned = ulBytesProcessed;
3385 AFSReleaseFid( IN AFSFileID *FileId)
3388 NTSTATUS ntStatus = STATUS_SUCCESS;
3393 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
3410 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
3411 IN LARGE_INTEGER *ExtentOffset,
3415 BOOLEAN bRequestQueued = FALSE;
3416 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3417 AFSCommSrvcCB *pCommSrvc = NULL;
3418 AFSPoolEntry *pPoolEntry = NULL;
3419 AFSRequestExtentsCB *pRequestExtents = NULL;
3425 pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
3427 AFSAcquireShared( &pCommSrvc->IrpPoolLock,
3430 pPoolEntry = pCommSrvc->RequestPoolHead;
3432 while( pPoolEntry != NULL)
3435 if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
3438 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
3441 pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
3443 if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
3444 pRequestExtents->Length == Length)
3447 bRequestQueued = TRUE;
3452 pPoolEntry = pPoolEntry->fLink;
3455 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
3458 return bRequestQueued;
3462 AFSCreateSymlink( IN GUID *AuthGroup,
3463 IN AFSObjectInfoCB *ParentObjectInfo,
3464 IN UNICODE_STRING *FileName,
3465 IN AFSObjectInfoCB *ObjectInfo,
3466 IN UNICODE_STRING *TargetName)
3469 NTSTATUS ntStatus = STATUS_SUCCESS;
3470 AFSCreateSymlinkCB *pSymlinkCreate = NULL;
3471 ULONG ulResultLen = 0;
3472 AFSCreateSymlinkResultCB *pSymlinkResult = NULL;
3478 // Allocate our request and result structures
3481 pSymlinkCreate = (AFSCreateSymlinkCB *)ExAllocatePoolWithTag( PagedPool,
3482 sizeof( AFSCreateSymlinkCB) +
3484 AFS_SYMLINK_REQUEST_TAG);
3486 if( pSymlinkCreate == NULL)
3489 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3492 RtlZeroMemory( pSymlinkCreate,
3493 sizeof( AFSCreateSymlinkCB) +
3494 TargetName->Length);
3496 pSymlinkResult = (AFSCreateSymlinkResultCB *)ExAllocatePoolWithTag( PagedPool,
3498 AFS_SYMLINK_REQUEST_TAG);
3500 if( pSymlinkResult == NULL)
3503 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3506 RtlZeroMemory( pSymlinkResult,
3510 // Populate the request buffer
3513 RtlCopyMemory( &pSymlinkCreate->ParentId,
3514 &ObjectInfo->ParentFileId,
3515 sizeof( AFSFileID));
3517 pSymlinkCreate->TargetNameLength = TargetName->Length;
3519 RtlCopyMemory( pSymlinkCreate->TargetName,
3521 TargetName->Length);
3523 ulResultLen = PAGE_SIZE;
3526 // Call the service to create the symlink entry
3529 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_SYMLINK,
3530 AFS_REQUEST_FLAG_SYNCHRONOUS,
3533 &ObjectInfo->FileId,
3534 ObjectInfo->VolumeCB->VolumeInformation.Cell,
3535 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
3537 sizeof( AFSCreateSymlinkCB) +
3542 if ( ntStatus == STATUS_FILE_DELETED )
3545 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3546 AFS_TRACE_LEVEL_ERROR,
3547 "AFSCreateSymlink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3548 ObjectInfo->FileId.Cell,
3549 ObjectInfo->FileId.Volume,
3550 ObjectInfo->FileId.Vnode,
3551 ObjectInfo->FileId.Unique,
3554 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3556 ClearFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
3558 SetFlag( ObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
3560 try_return( ntStatus = STATUS_ACCESS_DENIED);
3562 else if( ntStatus != STATUS_SUCCESS)
3565 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3566 AFS_TRACE_LEVEL_ERROR,
3567 "AFSCreateSymlink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3568 ObjectInfo->FileId.Cell,
3569 ObjectInfo->FileId.Volume,
3570 ObjectInfo->FileId.Vnode,
3571 ObjectInfo->FileId.Unique,
3574 try_return( ntStatus);
3578 // After successful creation the open object has been deleted and replaced by
3579 // the actual symlink.
3582 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3584 ClearFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
3586 SetFlag( ObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
3590 if( pSymlinkCreate != NULL)
3593 AFSExFreePoolWithTag( pSymlinkCreate, AFS_SYMLINK_REQUEST_TAG);
3596 if( pSymlinkResult != NULL)
3599 AFSExFreePoolWithTag( pSymlinkResult, AFS_SYMLINK_REQUEST_TAG);