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);
1972 stDelete.ParentId = pObjectInfo->ParentFileId;
1974 stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
1976 ulResultLen = sizeof( AFSFileDeleteResultCB);
1980 ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
1983 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
1986 &DirectoryCB->NameInformation.FileName,
1987 &pObjectInfo->FileId,
1988 pObjectInfo->VolumeCB->VolumeInformation.Cell,
1989 pObjectInfo->VolumeCB->VolumeInformation.CellLength,
1991 sizeof( AFSFileDeleteCB),
1995 if( ntStatus != STATUS_SUCCESS)
1998 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1999 AFS_TRACE_LEVEL_ERROR,
2000 "AFSNotifyDelete failed ParentFID %08lX-%08lX-%08lX-%08lX %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2001 stDelete.ParentId.Cell,
2002 stDelete.ParentId.Volume,
2003 stDelete.ParentId.Vnode,
2004 stDelete.ParentId.Unique,
2005 &DirectoryCB->NameInformation.FileName,
2006 pObjectInfo->FileId.Cell,
2007 pObjectInfo->FileId.Volume,
2008 pObjectInfo->FileId.Vnode,
2009 pObjectInfo->FileId.Unique,
2012 try_return( ntStatus);
2015 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2022 // Validate the parent data version
2025 if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
2028 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2030 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2037 // Update the parent data version
2040 if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart - 1)
2043 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2045 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2051 // TODO -- The entry must be removed from the directory at which point the
2052 // Directory data version number can be updated. Until then we must force
2055 // pParentObjectInfor->DataVersion.QuadPart = stDeleteResult.ParentDataVersion.QuadPart;
2058 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2060 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2064 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2068 if ( pParentObjectInfo)
2071 AFSReleaseObjectInfo( &pParentObjectInfo);
2080 AFSNotifyHardLink( IN AFSObjectInfoCB *ObjectInfo,
2082 IN AFSObjectInfoCB *ParentObjectInfo,
2083 IN AFSObjectInfoCB *TargetParentObjectInfo,
2084 IN AFSDirectoryCB *SourceDirectoryCB,
2085 IN UNICODE_STRING *TargetName,
2086 IN BOOLEAN bReplaceIfExists,
2087 OUT AFSDirectoryCB **TargetDirectoryCB)
2090 NTSTATUS ntStatus = STATUS_SUCCESS;
2091 AFSFileHardLinkCB *pHardLinkCB = NULL;
2092 AFSFileHardLinkResultCB *pResultCB = NULL;
2093 ULONG ulResultLen = 0;
2094 AFSDirectoryCB *pDirNode = NULL;
2096 BOOLEAN bReleaseParentLock = FALSE, bReleaseTargetParentLock = FALSE;
2097 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2104 // Init the control block for the request
2107 pHardLinkCB = (AFSFileHardLinkCB *)AFSExAllocatePoolWithTag( PagedPool,
2109 AFS_HARDLINK_REQUEST_TAG);
2111 if( pHardLinkCB == NULL)
2114 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2117 RtlZeroMemory( pHardLinkCB,
2120 pHardLinkCB->SourceParentId = ParentObjectInfo->FileId;
2122 pHardLinkCB->TargetParentId = TargetParentObjectInfo->FileId;
2124 pHardLinkCB->TargetNameLength = TargetName->Length;
2126 RtlCopyMemory( pHardLinkCB->TargetName,
2128 TargetName->Length);
2130 pHardLinkCB->bReplaceIfExists = bReplaceIfExists;
2133 // Use the same buffer for the result control block
2136 pResultCB = (AFSFileHardLinkResultCB *)pHardLinkCB;
2138 ulResultLen = PAGE_SIZE;
2140 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_HARDLINK_FILE,
2141 AFS_REQUEST_FLAG_SYNCHRONOUS,
2143 &SourceDirectoryCB->NameInformation.FileName,
2144 &ObjectInfo->FileId,
2145 ObjectInfo->VolumeCB->VolumeInformation.Cell,
2146 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2148 sizeof( AFSFileHardLinkCB) + TargetName->Length,
2152 if( ntStatus != STATUS_SUCCESS)
2155 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2156 AFS_TRACE_LEVEL_ERROR,
2157 "AFSNotifyHardLink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2158 ObjectInfo->FileId.Cell,
2159 ObjectInfo->FileId.Volume,
2160 ObjectInfo->FileId.Vnode,
2161 ObjectInfo->FileId.Unique,
2164 try_return( ntStatus);
2168 // Update the information from the returned data
2171 if ( ParentObjectInfo != TargetParentObjectInfo)
2174 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2177 bReleaseParentLock = TRUE;
2179 if ( ParentObjectInfo->DataVersion.QuadPart == pResultCB->SourceParentDataVersion.QuadPart - 1)
2182 ParentObjectInfo->DataVersion = pResultCB->SourceParentDataVersion;
2187 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2189 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2193 AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2196 bReleaseTargetParentLock = TRUE;
2198 if ( TargetParentObjectInfo->DataVersion.QuadPart == pResultCB->TargetParentDataVersion.QuadPart - 1)
2201 TargetParentObjectInfo->DataVersion = pResultCB->TargetParentDataVersion;
2206 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2207 AFS_TRACE_LEVEL_WARNING,
2208 "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",
2210 TargetParentObjectInfo->FileId.Cell,
2211 TargetParentObjectInfo->FileId.Volume,
2212 TargetParentObjectInfo->FileId.Vnode,
2213 TargetParentObjectInfo->FileId.Unique,
2214 TargetParentObjectInfo->DataVersion.HighPart,
2215 TargetParentObjectInfo->DataVersion.LowPart,
2216 pResultCB->TargetParentDataVersion.HighPart,
2217 pResultCB->TargetParentDataVersion.LowPart));
2220 // We raced so go and lookup the directory entry in the parent
2223 ulCRC = AFSGenerateCRC( TargetName,
2226 AFSLocateCaseSensitiveDirEntry( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2230 if( pDirNode != NULL)
2233 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2234 AFS_TRACE_LEVEL_VERBOSE,
2235 "AFSNotifyHardLink Located dir entry %p for file %wZ\n",
2239 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2240 &pResultCB->DirEnum.FileId))
2243 try_return( ntStatus = STATUS_REPARSE);
2249 // We found an entry that matches the desired name but it is not the
2250 // same as the one that was created for us by the file server.
2253 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2254 AFS_TRACE_LEVEL_ERROR,
2255 "AFSNotifyHardLink Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
2258 pDirNode->ObjectInformation->FileId.Cell,
2259 pDirNode->ObjectInformation->FileId.Volume,
2260 pDirNode->ObjectInformation->FileId.Vnode,
2261 pDirNode->ObjectInformation->FileId.Unique,
2262 pResultCB->DirEnum.FileId.Cell,
2263 pResultCB->DirEnum.FileId.Volume,
2264 pResultCB->DirEnum.FileId.Vnode,
2265 pResultCB->DirEnum.FileId.Unique));
2267 if( pDirNode->DirOpenReferenceCount <= 0 &&
2268 pDirNode->NameArrayReferenceCount <= 0)
2271 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2272 AFS_TRACE_LEVEL_VERBOSE,
2273 "AFSNotifyHardLink Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2275 &pDirNode->NameInformation.FileName,
2276 pDirNode->ObjectInformation->FileId.Cell,
2277 pDirNode->ObjectInformation->FileId.Volume,
2278 pDirNode->ObjectInformation->FileId.Vnode,
2279 pDirNode->ObjectInformation->FileId.Unique,
2280 pResultCB->DirEnum.FileId.Cell,
2281 pResultCB->DirEnum.FileId.Volume,
2282 pResultCB->DirEnum.FileId.Vnode,
2283 pResultCB->DirEnum.FileId.Unique));
2285 AFSDeleteDirEntry( TargetParentObjectInfo,
2291 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2293 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2294 AFS_TRACE_LEVEL_VERBOSE,
2295 "AFSNotifyHardLink Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2297 &pDirNode->NameInformation.FileName,
2298 pDirNode->ObjectInformation->FileId.Cell,
2299 pDirNode->ObjectInformation->FileId.Volume,
2300 pDirNode->ObjectInformation->FileId.Vnode,
2301 pDirNode->ObjectInformation->FileId.Unique,
2302 pResultCB->DirEnum.FileId.Cell,
2303 pResultCB->DirEnum.FileId.Volume,
2304 pResultCB->DirEnum.FileId.Vnode,
2305 pResultCB->DirEnum.FileId.Unique));
2307 AFSRemoveNameEntry( TargetParentObjectInfo,
2316 // We are unsure of our current data so set the verify flag. It may already be set
2317 // but no big deal to reset it
2320 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2322 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2326 // Create the hard link entry
2329 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2330 AFS_TRACE_LEVEL_VERBOSE,
2331 "AFSNotifyHardLink Creating new entry %wZ\n",
2335 // Initialize the directory entry
2338 pDirNode = AFSInitDirEntry( TargetParentObjectInfo,
2341 &pResultCB->DirEnum,
2342 (ULONG)InterlockedIncrement( &TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
2344 if( pDirNode == NULL)
2347 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2349 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2351 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2355 // Init the short name if we have one
2358 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2359 pResultCB->DirEnum.ShortNameLength > 0)
2362 UNICODE_STRING uniShortName;
2364 pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
2366 RtlCopyMemory( pDirNode->NameInformation.ShortName,
2367 pResultCB->DirEnum.ShortName,
2368 pDirNode->NameInformation.ShortNameLength);
2371 // Generate the short name index
2374 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
2375 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
2377 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
2380 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2381 AFS_TRACE_LEVEL_VERBOSE,
2382 "AFSNotifyHardLink Initialized short name %wZ for DE %p for %wZ\n",
2385 &pDirNode->NameInformation.FileName));
2390 // No short name or short names are disabled
2393 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2396 if ( !BooleanFlagOn( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2400 // Update the target parent data version
2403 TargetParentObjectInfo->DataVersion = pResultCB->TargetParentDataVersion;
2405 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2406 AFS_TRACE_LEVEL_VERBOSE,
2407 "AFSNotifyHardLink entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
2409 TargetParentObjectInfo->FileId.Cell,
2410 TargetParentObjectInfo->FileId.Volume,
2411 TargetParentObjectInfo->FileId.Vnode,
2412 TargetParentObjectInfo->FileId.Unique,
2413 TargetParentObjectInfo->DataVersion.QuadPart));
2418 if ( TargetDirectoryCB != NULL)
2421 lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
2423 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2424 AFS_TRACE_LEVEL_VERBOSE,
2425 "AFSNotifyHardLink Increment count on %wZ DE %p Cnt %d\n",
2426 &pDirNode->NameInformation.FileName,
2430 ASSERT( lCount >= 0);
2432 *TargetDirectoryCB = pDirNode;
2435 if ( bReleaseTargetParentLock)
2438 AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2441 if ( bReleaseParentLock)
2444 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2447 if( pHardLinkCB != NULL)
2450 AFSExFreePoolWithTag( pHardLinkCB, AFS_HARDLINK_REQUEST_TAG);
2460 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
2462 IN AFSObjectInfoCB *ParentObjectInfo,
2463 IN AFSObjectInfoCB *TargetParentObjectInfo,
2464 IN AFSDirectoryCB *DirectoryCB,
2465 IN UNICODE_STRING *TargetName,
2466 OUT AFSFileID *UpdatedFID)
2469 NTSTATUS ntStatus = STATUS_SUCCESS;
2470 AFSFileRenameCB *pRenameCB = NULL;
2471 AFSFileRenameResultCB *pRenameResultCB = NULL;
2472 ULONG ulResultLen = 0;
2473 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2479 // Init the control block for the request
2482 pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
2484 AFS_RENAME_REQUEST_TAG);
2486 if( pRenameCB == NULL)
2489 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2492 RtlZeroMemory( pRenameCB,
2495 pRenameCB->SourceParentId = ParentObjectInfo->FileId;
2497 pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
2499 pRenameCB->TargetNameLength = TargetName->Length;
2501 RtlCopyMemory( pRenameCB->TargetName,
2503 TargetName->Length);
2506 // Use the same buffer for the result control block
2509 pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
2511 ulResultLen = PAGE_SIZE;
2513 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
2514 AFS_REQUEST_FLAG_SYNCHRONOUS,
2516 &DirectoryCB->NameInformation.FileName,
2517 &ObjectInfo->FileId,
2518 ObjectInfo->VolumeCB->VolumeInformation.Cell,
2519 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2521 sizeof( AFSFileRenameCB) + TargetName->Length,
2525 if( ntStatus != STATUS_SUCCESS)
2528 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2529 AFS_TRACE_LEVEL_ERROR,
2530 "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2531 ObjectInfo->FileId.Cell,
2532 ObjectInfo->FileId.Volume,
2533 ObjectInfo->FileId.Vnode,
2534 ObjectInfo->FileId.Unique,
2537 try_return( ntStatus);
2541 // Update the information from the returned data
2544 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2547 if ( ParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->SourceParentDataVersion.QuadPart - 1)
2550 ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
2555 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2557 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2560 if ( ParentObjectInfo != TargetParentObjectInfo)
2563 AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2566 if ( TargetParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->TargetParentDataVersion.QuadPart - 1)
2569 TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
2574 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2576 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2581 // Move over the short name
2584 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2586 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2587 DirectoryCB->NameInformation.ShortNameLength > 0)
2590 UNICODE_STRING uniShortName;
2592 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2593 uniShortName.MaximumLength = uniShortName.Length;
2594 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2596 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2597 AFS_TRACE_LEVEL_VERBOSE,
2598 "AFSNotifyRename Update old short name %wZ for DE %p for %wZ\n",
2601 &DirectoryCB->NameInformation.FileName));
2603 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2605 RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
2606 pRenameResultCB->DirEnum.ShortName,
2607 DirectoryCB->NameInformation.ShortNameLength);
2609 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2610 uniShortName.MaximumLength = uniShortName.Length;
2611 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2613 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2614 AFS_TRACE_LEVEL_VERBOSE,
2615 "AFSNotifyRename Initialized short name %wZ for DE %p for %wZ\n",
2618 &DirectoryCB->NameInformation.FileName));
2623 UNICODE_STRING uniShortName;
2625 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2626 uniShortName.MaximumLength = uniShortName.Length;
2627 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2629 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2630 AFS_TRACE_LEVEL_VERBOSE,
2631 "AFSNotifyRename Removing old short name %wZ for DE %p for %wZ\n",
2634 &DirectoryCB->NameInformation.FileName));
2636 DirectoryCB->NameInformation.ShortNameLength = 0;
2638 DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2641 if ( ParentObjectInfo != TargetParentObjectInfo)
2644 AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2647 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2649 if( UpdatedFID != NULL)
2651 *UpdatedFID = pRenameResultCB->DirEnum.FileId;
2656 if( pRenameCB != NULL)
2659 AFSExFreePoolWithTag( pRenameCB, AFS_RENAME_REQUEST_TAG);
2667 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
2669 IN BOOLEAN FastCall,
2670 OUT AFSDirEnumEntry **DirEnumEntry)
2673 NTSTATUS ntStatus = STATUS_SUCCESS;
2674 AFSEvalTargetCB stTargetID;
2675 ULONG ulResultBufferLength;
2676 AFSFileEvalResultCB *pEvalResultCB = NULL;
2677 AFSDirEnumEntry *pDirEnumCB = NULL;
2678 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
2679 AFSObjectInfoCB *pParentObjectInfo = NULL;
2684 RtlZeroMemory( &stTargetID,
2685 sizeof( AFSEvalTargetCB));
2687 if ( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2690 pParentObjectInfo = AFSFindObjectInfo( ObjectInfo->VolumeCB,
2691 &ObjectInfo->ParentFileId);
2693 stTargetID.ParentId = ObjectInfo->ParentFileId;
2697 // Allocate our response buffer
2700 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2702 AFS_GENERIC_MEMORY_30_TAG);
2704 if( pEvalResultCB == NULL)
2707 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2711 // Call to the service to evaluate the fid
2714 ulResultBufferLength = PAGE_SIZE;
2719 ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
2722 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
2726 &ObjectInfo->FileId,
2727 ObjectInfo->VolumeCB->VolumeInformation.Cell,
2728 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2730 sizeof( AFSEvalTargetCB),
2732 &ulResultBufferLength);
2734 if( ntStatus != STATUS_SUCCESS)
2738 // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
2742 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2745 if( pParentObjectInfo != NULL)
2748 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2751 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2753 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2755 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2759 try_return( ntStatus);
2763 // A BSOD can occur if the pEvalResultCB->FileType is FILE but the
2764 // ObjectInfo->FileType is something else. The same is true for
2765 // pDirEnumEntry->FileType is DIRECTORY. Perform a sanity check
2766 // to ensure consistency. An inconsistent pDirEnumEntry can be
2767 // produced as a result of invalid status info received from a file
2768 // server. If the types are inconsistent or if the type does not
2769 // match the implied type derived from the vnode (odd values are
2770 // directories and even values are other types), prevent the request
2771 // from completing successfully. This may prevent access to the file or
2772 // directory but will prevent a BSOD.
2775 if ( !AFSIsEqualFID( &ObjectInfo->FileId,
2776 &pEvalResultCB->DirEnum.FileId))
2779 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2782 switch ( pEvalResultCB->DirEnum.FileType)
2785 case AFS_FILE_TYPE_DIRECTORY:
2786 if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x1)
2789 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2792 if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
2793 ObjectInfo->FileType != AFS_FILE_TYPE_DIRECTORY)
2796 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2801 case AFS_FILE_TYPE_FILE:
2802 if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x0)
2805 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2808 if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
2809 ObjectInfo->FileType != AFS_FILE_TYPE_FILE)
2812 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2819 // Validate the parent data version
2822 if ( pParentObjectInfo != NULL)
2825 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2828 if ( pParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2831 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2833 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2836 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2840 // Pass back the dir enum entry
2843 if( DirEnumEntry != NULL)
2846 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2848 AFS_GENERIC_MEMORY_2_TAG);
2850 if( pDirEnumCB == NULL)
2853 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2856 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2857 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2859 *DirEnumEntry = pDirEnumCB;
2864 if ( pParentObjectInfo != NULL)
2867 AFSReleaseObjectInfo( &pParentObjectInfo);
2870 if( pEvalResultCB != NULL)
2873 AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_30_TAG);
2876 if( !NT_SUCCESS( ntStatus))
2879 if( pDirEnumCB != NULL)
2882 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_2_TAG);
2885 *DirEnumEntry = NULL;
2893 AFSEvaluateTargetByName( IN GUID *AuthGroup,
2894 IN AFSObjectInfoCB *ParentObjectInfo,
2895 IN PUNICODE_STRING SourceName,
2897 OUT AFSDirEnumEntry **DirEnumEntry)
2900 NTSTATUS ntStatus = STATUS_SUCCESS;
2901 AFSEvalTargetCB stTargetID;
2902 ULONG ulResultBufferLength;
2903 AFSFileEvalResultCB *pEvalResultCB = NULL;
2904 AFSDirEnumEntry *pDirEnumCB = NULL;
2909 stTargetID.ParentId = ParentObjectInfo->FileId;
2912 // Allocate our response buffer
2915 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2917 AFS_GENERIC_MEMORY_31_TAG);
2919 if( pEvalResultCB == NULL)
2922 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2926 // Call to the service to evaluate the fid
2929 ulResultBufferLength = PAGE_SIZE;
2931 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
2932 AFS_REQUEST_FLAG_SYNCHRONOUS | Flags,
2936 ParentObjectInfo->VolumeCB->VolumeInformation.Cell,
2937 ParentObjectInfo->VolumeCB->VolumeInformation.CellLength,
2939 sizeof( AFSEvalTargetCB),
2941 &ulResultBufferLength);
2943 if( ntStatus != STATUS_SUCCESS)
2946 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2949 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2952 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2954 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2956 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2959 try_return( ntStatus);
2963 // Validate the parent data version
2966 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2969 if ( ParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2972 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2974 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2977 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2980 // Pass back the dir enum entry
2983 if( DirEnumEntry != NULL)
2986 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2988 AFS_GENERIC_MEMORY_3_TAG);
2990 if( pDirEnumCB == NULL)
2993 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2996 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2997 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2999 *DirEnumEntry = pDirEnumCB;
3004 if( pEvalResultCB != NULL)
3007 AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_31_TAG);
3010 if( !NT_SUCCESS( ntStatus))
3013 if( pDirEnumCB != NULL)
3016 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_3_TAG);
3019 *DirEnumEntry = NULL;
3027 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
3028 IN AFSFileID *FileID,
3029 OUT AFSVolumeInfoCB *VolumeInformation)
3032 NTSTATUS ntStatus = STATUS_SUCCESS;
3033 ULONG ulResultLen = 0;
3038 ulResultLen = sizeof( AFSVolumeInfoCB);
3040 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
3041 AFS_REQUEST_FLAG_SYNCHRONOUS,
3052 if( ntStatus != STATUS_SUCCESS)
3055 try_return( ntStatus);
3067 AFSRetrieveVolumeSizeInformation( IN GUID *AuthGroup,
3068 IN AFSFileID *FileID,
3069 OUT AFSVolumeSizeInfoCB *VolumeSizeInformation)
3072 NTSTATUS ntStatus = STATUS_SUCCESS;
3073 ULONG ulResultLen = 0;
3078 ulResultLen = sizeof( AFSVolumeSizeInfoCB);
3080 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_SIZE_INFO,
3081 AFS_REQUEST_FLAG_SYNCHRONOUS,
3089 VolumeSizeInformation,
3092 if( ntStatus != STATUS_SUCCESS)
3095 try_return( ntStatus);
3107 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
3108 IN ULONG InputLength,
3109 IN ULONG OutputLength,
3110 IN void *InputDataBuffer,
3111 OUT void *OutputDataBuffer,
3112 OUT ULONG *BytesReturned)
3115 NTSTATUS ntStatus = STATUS_SUCCESS;
3116 ULONG ulResultLen = 0;
3117 MDL *pInputMdl = NULL, *pOutputMdl = NULL;
3118 void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
3119 AFSPipeIORequestCB *pIoRequest = NULL;
3125 // Map the user buffer to a system address
3128 pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
3132 if( pInputSystemBuffer == NULL)
3135 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3138 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
3139 sizeof( AFSPipeIORequestCB) +
3141 AFS_GENERIC_MEMORY_4_TAG);
3143 if( pIoRequest == NULL)
3146 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3149 RtlZeroMemory( pIoRequest,
3150 sizeof( AFSPipeIORequestCB) + InputLength);
3152 pIoRequest->RequestId = Ccb->RequestID;
3154 pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3156 pIoRequest->BufferLength = InputLength;
3158 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
3162 pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
3166 if( pOutputSystemBuffer == NULL)
3169 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3173 // Send the call to the service
3176 ulResultLen = OutputLength;
3178 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
3179 AFS_REQUEST_FLAG_SYNCHRONOUS,
3181 &Ccb->DirectoryCB->NameInformation.FileName,
3186 sizeof( AFSPipeIORequestCB) + InputLength,
3187 pOutputSystemBuffer,
3190 if( ntStatus != STATUS_SUCCESS &&
3191 ntStatus != STATUS_BUFFER_OVERFLOW)
3194 if( NT_SUCCESS( ntStatus))
3197 ntStatus = STATUS_DEVICE_NOT_READY;
3200 try_return( ntStatus);
3204 // Return the bytes processed
3207 *BytesReturned = ulResultLen;
3211 if( pInputMdl != NULL)
3214 MmUnlockPages( pInputMdl);
3216 IoFreeMdl( pInputMdl);
3219 if( pOutputMdl != NULL)
3222 MmUnlockPages( pOutputMdl);
3224 IoFreeMdl( pOutputMdl);
3227 if( pIoRequest != NULL)
3230 AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_4_TAG);
3238 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
3239 IN ULONG InformationClass,
3240 IN ULONG InputLength,
3241 IN void *DataBuffer)
3244 NTSTATUS ntStatus = STATUS_SUCCESS;
3245 AFSPipeInfoRequestCB *pInfoRequest = NULL;
3250 pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
3251 sizeof( AFSPipeInfoRequestCB) +
3253 AFS_GENERIC_MEMORY_5_TAG);
3255 if( pInfoRequest == NULL)
3258 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3261 RtlZeroMemory( pInfoRequest,
3262 sizeof( AFSPipeInfoRequestCB) + InputLength);
3264 pInfoRequest->RequestId = Ccb->RequestID;
3266 pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3268 pInfoRequest->BufferLength = InputLength;
3270 pInfoRequest->InformationClass = InformationClass;
3272 RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
3277 // Send the call to the service
3280 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
3281 AFS_REQUEST_FLAG_SYNCHRONOUS,
3283 &Ccb->DirectoryCB->NameInformation.FileName,
3288 sizeof( AFSPipeInfoRequestCB) + InputLength,
3292 if( ntStatus != STATUS_SUCCESS)
3295 if( NT_SUCCESS( ntStatus))
3298 ntStatus = STATUS_DEVICE_NOT_READY;
3301 try_return( ntStatus);
3306 if( pInfoRequest != NULL)
3309 AFSExFreePoolWithTag( pInfoRequest, AFS_GENERIC_MEMORY_5_TAG);
3317 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
3318 IN ULONG InformationClass,
3319 IN ULONG OutputLength,
3320 IN void *DataBuffer,
3321 OUT ULONG *BytesReturned)
3324 NTSTATUS ntStatus = STATUS_SUCCESS;
3325 AFSPipeInfoRequestCB stInfoRequest;
3326 ULONG ulBytesProcessed = 0;
3331 RtlZeroMemory( &stInfoRequest,
3332 sizeof( AFSPipeInfoRequestCB));
3334 stInfoRequest.RequestId = Ccb->RequestID;
3336 stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3338 stInfoRequest.BufferLength = OutputLength;
3340 stInfoRequest.InformationClass = InformationClass;
3342 ulBytesProcessed = OutputLength;
3345 // Send the call to the service
3348 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
3349 AFS_REQUEST_FLAG_SYNCHRONOUS,
3351 &Ccb->DirectoryCB->NameInformation.FileName,
3356 sizeof( AFSPipeInfoRequestCB),
3360 if( ntStatus != STATUS_SUCCESS)
3363 if( NT_SUCCESS( ntStatus))
3366 ntStatus = STATUS_DEVICE_NOT_READY;
3369 try_return( ntStatus);
3372 *BytesReturned = ulBytesProcessed;
3383 AFSReleaseFid( IN AFSFileID *FileId)
3386 NTSTATUS ntStatus = STATUS_SUCCESS;
3391 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
3408 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
3409 IN LARGE_INTEGER *ExtentOffset,
3413 BOOLEAN bRequestQueued = FALSE;
3414 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3415 AFSCommSrvcCB *pCommSrvc = NULL;
3416 AFSPoolEntry *pPoolEntry = NULL;
3417 AFSRequestExtentsCB *pRequestExtents = NULL;
3423 pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
3425 AFSAcquireShared( &pCommSrvc->IrpPoolLock,
3428 pPoolEntry = pCommSrvc->RequestPoolHead;
3430 while( pPoolEntry != NULL)
3433 if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
3436 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
3439 pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
3441 if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
3442 pRequestExtents->Length == Length)
3445 bRequestQueued = TRUE;
3450 pPoolEntry = pPoolEntry->fLink;
3453 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
3456 return bRequestQueued;
3460 AFSCreateSymlink( IN GUID *AuthGroup,
3461 IN AFSObjectInfoCB *ParentObjectInfo,
3462 IN UNICODE_STRING *FileName,
3463 IN AFSObjectInfoCB *ObjectInfo,
3464 IN UNICODE_STRING *TargetName)
3467 NTSTATUS ntStatus = STATUS_SUCCESS;
3468 AFSCreateSymlinkCB *pSymlinkCreate = NULL;
3469 ULONG ulResultLen = 0;
3470 AFSCreateSymlinkResultCB *pSymlinkResult = NULL;
3476 // Allocate our request and result structures
3479 pSymlinkCreate = (AFSCreateSymlinkCB *)ExAllocatePoolWithTag( PagedPool,
3480 sizeof( AFSCreateSymlinkCB) +
3482 AFS_SYMLINK_REQUEST_TAG);
3484 if( pSymlinkCreate == NULL)
3487 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3490 RtlZeroMemory( pSymlinkCreate,
3491 sizeof( AFSCreateSymlinkCB) +
3492 TargetName->Length);
3494 pSymlinkResult = (AFSCreateSymlinkResultCB *)ExAllocatePoolWithTag( PagedPool,
3496 AFS_SYMLINK_REQUEST_TAG);
3498 if( pSymlinkResult == NULL)
3501 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3504 RtlZeroMemory( pSymlinkResult,
3508 // Populate the request buffer
3511 RtlCopyMemory( &pSymlinkCreate->ParentId,
3512 &ObjectInfo->ParentFileId,
3513 sizeof( AFSFileID));
3515 pSymlinkCreate->TargetNameLength = TargetName->Length;
3517 RtlCopyMemory( pSymlinkCreate->TargetName,
3519 TargetName->Length);
3521 ulResultLen = PAGE_SIZE;
3524 // Call the service to create the symlink entry
3527 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_SYMLINK,
3528 AFS_REQUEST_FLAG_SYNCHRONOUS,
3531 &ObjectInfo->FileId,
3532 ObjectInfo->VolumeCB->VolumeInformation.Cell,
3533 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
3535 sizeof( AFSCreateSymlinkCB) +
3540 if ( ntStatus == STATUS_FILE_DELETED )
3543 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3544 AFS_TRACE_LEVEL_ERROR,
3545 "AFSCreateSymlink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3546 ObjectInfo->FileId.Cell,
3547 ObjectInfo->FileId.Volume,
3548 ObjectInfo->FileId.Vnode,
3549 ObjectInfo->FileId.Unique,
3552 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3554 ClearFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
3556 SetFlag( ObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
3558 try_return( ntStatus = STATUS_ACCESS_DENIED);
3560 else if( ntStatus != STATUS_SUCCESS)
3563 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3564 AFS_TRACE_LEVEL_ERROR,
3565 "AFSCreateSymlink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3566 ObjectInfo->FileId.Cell,
3567 ObjectInfo->FileId.Volume,
3568 ObjectInfo->FileId.Vnode,
3569 ObjectInfo->FileId.Unique,
3572 try_return( ntStatus);
3576 // After successful creation the open object has been deleted and replaced by
3577 // the actual symlink.
3580 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3582 ClearFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
3584 SetFlag( ObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
3588 if( pSymlinkCreate != NULL)
3591 AFSExFreePoolWithTag( pSymlinkCreate, AFS_SYMLINK_REQUEST_TAG);
3594 if( pSymlinkResult != NULL)
3597 AFSExFreePoolWithTag( pSymlinkResult, AFS_SYMLINK_REQUEST_TAG);