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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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)
314 AFSObjectInfoCB *pObjectInfo = pDirNode->ObjectInformation;
317 // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
320 lCount = AFSObjectInfoIncrement( pObjectInfo,
321 AFS_OBJECT_REFERENCE_INVALIDATION);
323 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
324 AFS_TRACE_LEVEL_VERBOSE,
325 "AFSEnumerateDirectory calling AFSPerformObjectInvalidate Increment count on object %p Cnt %d\n",
329 AFSPerformObjectInvalidate( pObjectInfo,
330 AFS_INVALIDATE_DATA_VERSION);
335 AFSUpdateMetaData( pDirNode,
345 // Need to tear down this entry and rebuild it below
348 if( pDirNode->DirOpenReferenceCount <= 0 &&
349 pDirNode->NameArrayReferenceCount <= 0)
352 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
353 AFS_TRACE_LEVEL_VERBOSE,
354 "AFSEnumerateDirectory Different FIDs - Deleting 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 AFSDeleteDirEntry( ObjectInfoCB,
372 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
374 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
375 AFS_TRACE_LEVEL_VERBOSE,
376 "AFSEnumerateDirectory Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
378 &pDirNode->NameInformation.FileName,
379 pDirNode->ObjectInformation->FileId.Cell,
380 pDirNode->ObjectInformation->FileId.Volume,
381 pDirNode->ObjectInformation->FileId.Vnode,
382 pDirNode->ObjectInformation->FileId.Unique,
383 pCurrentDirEntry->FileId.Cell,
384 pCurrentDirEntry->FileId.Volume,
385 pCurrentDirEntry->FileId.Vnode,
386 pCurrentDirEntry->FileId.Unique);
388 AFSRemoveNameEntry( ObjectInfoCB,
396 pDirNode = AFSInitDirEntry( ObjectInfoCB,
400 (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
402 if( pDirNode == NULL)
405 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
410 AFSUpdateMetaData( pDirNode,
413 if( pDirNode->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
416 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
417 AFS_TRACE_LEVEL_VERBOSE,
418 "AFSEnumerateDirectory Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
420 pDirNode->ObjectInformation->FileId.Cell,
421 pDirNode->ObjectInformation->FileId.Volume,
422 pDirNode->ObjectInformation->FileId.Vnode,
423 pDirNode->ObjectInformation->FileId.Unique);
425 AFSAcquireExcl( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
428 SetFlag( pDirNode->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
430 pDirNode->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
432 AFSReleaseResource( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
436 // Set up the entry length
439 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
440 pCurrentDirEntry->FileNameLength +
441 pCurrentDirEntry->TargetNameLength);
444 // Init the short name if we have one
447 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
448 pCurrentDirEntry->ShortNameLength > 0)
451 UNICODE_STRING uniShortName;
453 pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
455 RtlCopyMemory( pDirNode->NameInformation.ShortName,
456 pCurrentDirEntry->ShortName,
457 pDirNode->NameInformation.ShortNameLength);
460 // Generate the short name index
463 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
464 uniShortName.MaximumLength = uniShortName.Length;
465 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
467 if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
472 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
475 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
476 AFS_TRACE_LEVEL_VERBOSE,
477 "AFSEnumerateDirectory Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
480 &pDirNode->NameInformation.FileName,
481 pCurrentDirEntry->FileId.Cell,
482 pCurrentDirEntry->FileId.Volume,
483 pCurrentDirEntry->FileId.Vnode,
484 pCurrentDirEntry->FileId.Unique);
488 pDirNode->NameInformation.ShortNameLength = 0;
490 RtlZeroMemory( pDirNode->NameInformation.ShortName,
491 (12 * sizeof( WCHAR)));
498 // No short name or short names are disabled
501 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
505 // Insert the node into the name tree
508 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
511 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
513 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
514 AFS_TRACE_LEVEL_VERBOSE,
515 "AFSEnumerateDirectory Insert DE %p to head of case sensitive tree for %wZ\n",
517 &pDirNode->NameInformation.FileName);
522 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
523 AFS_TRACE_LEVEL_VERBOSE,
524 "AFSEnumerateDirectory Insert DE %p to case sensitive tree for %wZ\n",
526 &pDirNode->NameInformation.FileName);
528 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
533 // Delete this dir entry and continue on
536 AFSDeleteDirEntry( ObjectInfoCB,
539 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
541 if( ulResultLen >= ulEntryLength)
543 ulResultLen -= ulEntryLength;
554 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
556 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
559 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
560 AFS_TRACE_LEVEL_VERBOSE,
561 "AFSEnumerateDirectory Insert DE %p to head of case insensitive tree for %wZ\n",
563 &pDirNode->NameInformation.FileName);
565 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
567 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
572 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
573 AFS_TRACE_LEVEL_VERBOSE,
574 "AFSEnumerateDirectory Insert DE %p to case insensitive tree for %wZ\n",
576 &pDirNode->NameInformation.FileName);
578 AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
582 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
585 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
590 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
592 pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
595 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
597 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
599 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
601 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
602 AFS_TRACE_LEVEL_VERBOSE,
603 "AFSEnumerateDirectory Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
604 &pDirNode->NameInformation.FileName,
605 ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
606 ObjectInfoCB->FileId.Cell,
607 ObjectInfoCB->FileId.Volume,
608 ObjectInfoCB->FileId.Vnode,
609 ObjectInfoCB->FileId.Unique);
611 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
615 // Insert the short name entry if we have a valid short name
618 if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
621 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
622 AFS_TRACE_LEVEL_VERBOSE,
623 "AFSEnumerateDirectory Insert DE %p to head of shortname tree for %wZ\n",
625 &pDirNode->NameInformation.FileName);
627 ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
629 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
634 if( NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
637 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
639 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
640 AFS_TRACE_LEVEL_VERBOSE,
641 "AFSEnumerateDirectory Insert DE %p to shortname tree for %wZ\n",
643 &pDirNode->NameInformation.FileName);
652 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
654 if( ulResultLen >= ulEntryLength)
656 ulResultLen -= ulEntryLength;
664 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
667 // Reset the information in the request buffer since it got trampled
671 pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
673 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
674 AFS_TRACE_LEVEL_VERBOSE,
675 "AFSEnumerateDirectory EnumHandle %08lX\n",
676 pDirQueryCB->EnumHandle);
688 AFSExFreePoolWithTag( pBuffer, AFS_DIR_BUFFER_TAG);
691 if ( NT_SUCCESS( ntStatus))
694 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
700 // If the processing failed then we should reset the directory
701 // content in the event it is re-enumerated
704 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
705 AFS_TRACE_LEVEL_ERROR,
706 "AFSEnumerateDirectory Resetting content for FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
707 ObjectInfoCB->FileId.Cell,
708 ObjectInfoCB->FileId.Volume,
709 ObjectInfoCB->FileId.Vnode,
710 ObjectInfoCB->FileId.Unique,
713 AFSResetDirectoryContent( ObjectInfoCB);
721 AFSEnumerateDirectoryNoResponse( IN GUID *AuthGroup,
722 IN AFSFileID *FileId)
725 NTSTATUS ntStatus = STATUS_SUCCESS;
726 AFSDirQueryCB stDirQueryCB;
727 ULONG ulRequestFlags = 0;
733 // Use the payload buffer for information we will pass to the service
736 stDirQueryCB.EnumHandle = 0;
738 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
745 (void *)&stDirQueryCB,
746 sizeof( AFSDirQueryCB),
750 if( ntStatus != STATUS_SUCCESS)
753 if( ntStatus == STATUS_NO_MORE_FILES ||
754 ntStatus == STATUS_NO_MORE_ENTRIES)
757 ntStatus = STATUS_SUCCESS;
762 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
763 AFS_TRACE_LEVEL_ERROR,
764 "AFSEnumerateDirectoryNoResponse Failed to enumerate directory Status %08lX\n",
774 AFSVerifyDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB,
778 NTSTATUS ntStatus = STATUS_SUCCESS;
779 void *pBuffer = NULL;
780 ULONG ulResultLen = 0;
781 AFSDirQueryCB *pDirQueryCB;
782 AFSDirEnumEntry *pCurrentDirEntry = NULL;
783 AFSDirectoryCB *pDirNode = NULL;
784 ULONG ulEntryLength = 0;
785 AFSDirEnumResp *pDirEnumResponse = NULL;
786 UNICODE_STRING uniDirName, uniTargetName;
787 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_FAST_REQUEST;
789 AFSObjectInfoCB *pObjectInfo = NULL;
790 ULONGLONG ullIndex = 0;
791 UNICODE_STRING uniGUID;
793 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
798 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
801 uniGUID.MaximumLength = 0;
802 uniGUID.Buffer = NULL;
804 if( AuthGroup != NULL)
806 RtlStringFromGUID( *AuthGroup,
810 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
811 AFS_TRACE_LEVEL_VERBOSE,
812 "AFSVerifyDirectoryContent Verifying content for FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
813 ObjectInfoCB->FileId.Cell,
814 ObjectInfoCB->FileId.Volume,
815 ObjectInfoCB->FileId.Vnode,
816 ObjectInfoCB->FileId.Unique,
819 if( AuthGroup != NULL)
821 RtlFreeUnicodeString( &uniGUID);
825 // Initialize the directory enumeration buffer for the directory
828 pBuffer = AFSExAllocatePoolWithTag( PagedPool,
829 AFS_DIR_ENUM_BUFFER_LEN,
835 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
838 RtlZeroMemory( pBuffer,
839 AFS_DIR_ENUM_BUFFER_LEN);
841 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
844 // Use the payload buffer for information we will pass to the service
847 pDirQueryCB = (AFSDirQueryCB *)pBuffer;
849 pDirQueryCB->EnumHandle = 0;
852 // Loop on the information
859 // If the enumeration handle is -1 then we are done
862 if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
865 ntStatus = STATUS_NO_MORE_ENTRIES;
871 // Go and retrieve the directory contents
874 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
878 &ObjectInfoCB->FileId,
879 ObjectInfoCB->VolumeCB->VolumeInformation.Cell,
880 ObjectInfoCB->VolumeCB->VolumeInformation.CellLength,
882 sizeof( AFSDirQueryCB),
887 if( ntStatus != STATUS_SUCCESS ||
891 if( ntStatus == STATUS_NO_MORE_FILES ||
892 ntStatus == STATUS_NO_MORE_ENTRIES)
895 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
897 AFSAcquireExcl( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock,
900 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
901 AFS_TRACE_LEVEL_VERBOSE,
902 "AFSVerifyDirectoryContent Directory Complete FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX Status %08lX\n",
903 ObjectInfoCB->FileId.Cell,
904 ObjectInfoCB->FileId.Volume,
905 ObjectInfoCB->FileId.Vnode,
906 ObjectInfoCB->FileId.Unique,
907 pDirEnumResponse->SnapshotDataVersion.HighPart,
908 pDirEnumResponse->SnapshotDataVersion.LowPart,
909 pDirEnumResponse->CurrentDataVersion.HighPart,
910 pDirEnumResponse->CurrentDataVersion.LowPart,
913 ntStatus = STATUS_SUCCESS;
915 if ( pDirEnumResponse->SnapshotDataVersion.QuadPart != pDirEnumResponse->CurrentDataVersion.QuadPart )
918 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
920 ObjectInfoCB->DataVersion.QuadPart = (ULONGLONG)-1;
922 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
923 AFS_TRACE_LEVEL_VERBOSE,
924 "AFSVerifyDirectoryContent Force Verify due to DV change during enumeration FID %08lX-%08lX-%08lX-%08lX\n",
925 ObjectInfoCB->FileId.Cell,
926 ObjectInfoCB->FileId.Volume,
927 ObjectInfoCB->FileId.Vnode,
928 ObjectInfoCB->FileId.Unique);
933 ObjectInfoCB->DataVersion = pDirEnumResponse->SnapshotDataVersion;
936 AFSReleaseResource( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock);
941 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
942 AFS_TRACE_LEVEL_ERROR,
943 "AFSVerifyDirectoryContent Failed to enumerate directory FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ Status %08lX\n",
944 ObjectInfoCB->FileId.Cell,
945 ObjectInfoCB->FileId.Volume,
946 ObjectInfoCB->FileId.Vnode,
947 ObjectInfoCB->FileId.Unique,
955 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
957 pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
959 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
960 AFS_TRACE_LEVEL_VERBOSE,
961 "AFSVerifyDirectoryContent EnumResponse FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX\n",
962 ObjectInfoCB->FileId.Cell,
963 ObjectInfoCB->FileId.Volume,
964 ObjectInfoCB->FileId.Vnode,
965 ObjectInfoCB->FileId.Unique,
966 pDirEnumResponse->SnapshotDataVersion.HighPart,
967 pDirEnumResponse->SnapshotDataVersion.LowPart,
968 pDirEnumResponse->CurrentDataVersion.HighPart,
969 pDirEnumResponse->CurrentDataVersion.LowPart);
972 // Remove the leading header from the processed length
975 ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
977 while( ulResultLen > 0)
980 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
982 uniDirName.MaximumLength = uniDirName.Length;
984 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
986 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
988 uniTargetName.MaximumLength = uniTargetName.Length;
990 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
993 // Does this entry already exist in the directory?
996 ulCRC = AFSGenerateCRC( &uniDirName,
999 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1005 // Set up the entry length
1008 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
1009 pCurrentDirEntry->FileNameLength +
1010 pCurrentDirEntry->TargetNameLength);
1013 AFSIsEqualFID( &pCurrentDirEntry->FileId,
1014 &pDirNode->ObjectInformation->FileId))
1018 // Found matching directory entry by name and FileID
1021 AFSAcquireShared( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock,
1024 ullIndex = AFSCreateLowIndex( &pCurrentDirEntry->FileId);
1026 ntStatus = AFSLocateHashEntry( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeHead,
1028 (AFSBTreeEntry **)&pObjectInfo);
1030 AFSReleaseResource( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock);
1032 if( NT_SUCCESS( ntStatus) &&
1033 pObjectInfo != NULL)
1037 // Indicate this is a valid entry
1040 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
1042 if( pCurrentDirEntry->ShortNameLength > 0 &&
1043 pDirNode->NameInformation.ShortNameLength > 0)
1045 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1046 AFS_TRACE_LEVEL_VERBOSE,
1047 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name %S New short name %S\n",
1049 &pDirNode->NameInformation.FileName,
1050 ObjectInfoCB->FileId.Cell,
1051 ObjectInfoCB->FileId.Volume,
1052 ObjectInfoCB->FileId.Vnode,
1053 ObjectInfoCB->FileId.Unique,
1054 pDirNode->NameInformation.ShortName,
1055 pCurrentDirEntry->ShortName);
1057 else if( pCurrentDirEntry->ShortNameLength == 0 &&
1058 pDirNode->NameInformation.ShortNameLength > 0)
1061 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1062 AFS_TRACE_LEVEL_VERBOSE,
1063 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name %S New short name NULL\n",
1065 &pDirNode->NameInformation.FileName,
1066 ObjectInfoCB->FileId.Cell,
1067 ObjectInfoCB->FileId.Volume,
1068 ObjectInfoCB->FileId.Vnode,
1069 ObjectInfoCB->FileId.Unique,
1070 pDirNode->NameInformation.ShortName);
1072 else if( pCurrentDirEntry->ShortNameLength > 0 &&
1073 pDirNode->NameInformation.ShortNameLength == 0)
1075 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1076 AFS_TRACE_LEVEL_VERBOSE,
1077 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name %S\n",
1079 &pDirNode->NameInformation.FileName,
1080 ObjectInfoCB->FileId.Cell,
1081 ObjectInfoCB->FileId.Volume,
1082 ObjectInfoCB->FileId.Vnode,
1083 ObjectInfoCB->FileId.Unique,
1084 pCurrentDirEntry->ShortName);
1088 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1089 AFS_TRACE_LEVEL_VERBOSE,
1090 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name NULL\n",
1092 &pDirNode->NameInformation.FileName,
1093 ObjectInfoCB->FileId.Cell,
1094 ObjectInfoCB->FileId.Volume,
1095 ObjectInfoCB->FileId.Vnode,
1096 ObjectInfoCB->FileId.Unique);
1100 // Update the metadata for the entry
1103 if( pObjectInfo->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
1107 // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
1108 // if successfully queued. Cannot call AFSPerformObjectInvalidate directly
1109 // because ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock is
1110 // held during the sequence AFSVerifyEntry->AFSValidateDirectoryCache->
1111 // AFSVerifyDirectoryContent and AFSPerformObjectInvalidate requires the
1112 // Fcb->NPFcb->Resource which must be held prior to the TreeLock in the
1116 lCount = AFSObjectInfoIncrement( pObjectInfo,
1117 AFS_OBJECT_REFERENCE_INVALIDATION);
1119 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1120 AFS_TRACE_LEVEL_VERBOSE,
1121 "AFSVerifyDirectoryContent calling AFSQueueInvalidateObject Increment count on object %p Cnt %d\n",
1125 if ( !NT_SUCCESS( AFSQueueInvalidateObject( pObjectInfo,
1126 AFS_INVALIDATE_DATA_VERSION)))
1129 lCount = AFSObjectInfoDecrement( pObjectInfo,
1130 AFS_OBJECT_REFERENCE_INVALIDATION);
1132 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1133 AFS_TRACE_LEVEL_VERBOSE,
1134 "AFSVerifyDirectoryContent AFSQueueInvalidateObject failed Decrement count on object %p Cnt %d\n",
1142 AFSUpdateMetaData( pDirNode,
1150 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1152 if( ulResultLen >= ulEntryLength)
1154 ulResultLen -= ulEntryLength;
1168 // File name matches but FileID does not.
1171 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1172 AFS_TRACE_LEVEL_VERBOSE,
1173 "AFSVerifyDirectoryContent Processing dir entry %p %wZ with different FID, same name in parent FID %08lX-%08lX-%08lX-%08lX\n",
1175 &pDirNode->NameInformation.FileName,
1176 ObjectInfoCB->FileId.Cell,
1177 ObjectInfoCB->FileId.Volume,
1178 ObjectInfoCB->FileId.Vnode,
1179 ObjectInfoCB->FileId.Unique);
1182 // Need to tear down this entry and rebuild it below
1185 if( pDirNode->DirOpenReferenceCount <= 0 &&
1186 pDirNode->NameArrayReferenceCount <= 0)
1189 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1190 AFS_TRACE_LEVEL_VERBOSE,
1191 "AFSVerifyDirectoryContent Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1193 &pDirNode->NameInformation.FileName,
1194 pDirNode->ObjectInformation->FileId.Cell,
1195 pDirNode->ObjectInformation->FileId.Volume,
1196 pDirNode->ObjectInformation->FileId.Vnode,
1197 pDirNode->ObjectInformation->FileId.Unique,
1198 pCurrentDirEntry->FileId.Cell,
1199 pCurrentDirEntry->FileId.Volume,
1200 pCurrentDirEntry->FileId.Vnode,
1201 pCurrentDirEntry->FileId.Unique);
1203 AFSDeleteDirEntry( ObjectInfoCB,
1209 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1211 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1212 AFS_TRACE_LEVEL_WARNING,
1213 "AFSVerifyDirectoryContent Different FIDs - removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1215 &pDirNode->NameInformation.FileName,
1216 pDirNode->ObjectInformation->FileId.Cell,
1217 pDirNode->ObjectInformation->FileId.Volume,
1218 pDirNode->ObjectInformation->FileId.Vnode,
1219 pDirNode->ObjectInformation->FileId.Unique,
1220 pCurrentDirEntry->FileId.Cell,
1221 pCurrentDirEntry->FileId.Volume,
1222 pCurrentDirEntry->FileId.Vnode,
1223 pCurrentDirEntry->FileId.Unique);
1225 AFSRemoveNameEntry( ObjectInfoCB,
1232 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1233 AFS_TRACE_LEVEL_VERBOSE,
1234 "AFSVerifyDirectoryContent New entry %wZ for parent FID %08lX-%08lX-%08lX-%08lX\n",
1236 ObjectInfoCB->FileId.Cell,
1237 ObjectInfoCB->FileId.Volume,
1238 ObjectInfoCB->FileId.Vnode,
1239 ObjectInfoCB->FileId.Unique);
1242 pDirNode = AFSInitDirEntry( ObjectInfoCB,
1246 (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1248 if( pDirNode == NULL)
1251 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
1256 AFSUpdateMetaData( pDirNode,
1259 if( pDirNode->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1262 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1263 AFS_TRACE_LEVEL_VERBOSE,
1264 "AFSVerifyDirectoryContent Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
1266 pDirNode->ObjectInformation->FileId.Cell,
1267 pDirNode->ObjectInformation->FileId.Volume,
1268 pDirNode->ObjectInformation->FileId.Vnode,
1269 pDirNode->ObjectInformation->FileId.Unique);
1271 AFSAcquireExcl( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1274 SetFlag( pDirNode->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1276 pDirNode->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1278 AFSReleaseResource( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1282 // Init the short name if we have one
1285 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1286 pCurrentDirEntry->ShortNameLength > 0)
1289 UNICODE_STRING uniShortName;
1291 pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
1293 RtlCopyMemory( pDirNode->NameInformation.ShortName,
1294 pCurrentDirEntry->ShortName,
1295 pDirNode->NameInformation.ShortNameLength);
1298 // Generate the short name index
1301 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1302 uniShortName.MaximumLength = uniShortName.Length;
1303 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1305 if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
1310 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1313 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1314 AFS_TRACE_LEVEL_VERBOSE,
1315 "AFSVerifyDirectoryContent Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1318 &pDirNode->NameInformation.FileName,
1319 pCurrentDirEntry->FileId.Cell,
1320 pCurrentDirEntry->FileId.Volume,
1321 pCurrentDirEntry->FileId.Vnode,
1322 pCurrentDirEntry->FileId.Unique);
1326 pDirNode->NameInformation.ShortNameLength = 0;
1328 RtlZeroMemory( pDirNode->NameInformation.ShortName,
1329 (12 * sizeof( WCHAR)));
1336 // No short name or short names have been disabled
1339 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
1343 // Insert the node into the name tree
1346 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
1348 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
1351 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
1353 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1354 AFS_TRACE_LEVEL_VERBOSE,
1355 "AFSVerifyDirectoryContent Insert DE %p to head of case sensitive tree for %wZ\n",
1357 &pDirNode->NameInformation.FileName);
1362 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1365 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1366 AFS_TRACE_LEVEL_VERBOSE,
1367 "AFSVerifyDirectoryContent Failed to insert DE %p to case sensitive tree for %wZ\n",
1369 &pDirNode->NameInformation.FileName);
1372 // Delete this dir entry and continue on
1375 AFSDeleteDirEntry( ObjectInfoCB,
1378 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1380 if( ulResultLen >= ulEntryLength)
1382 ulResultLen -= ulEntryLength;
1393 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1394 AFS_TRACE_LEVEL_VERBOSE,
1395 "AFSVerifyDirectoryContent Insert DE %p to case sensitive tree for %wZ\n",
1397 &pDirNode->NameInformation.FileName);
1401 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1403 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
1406 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
1408 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
1410 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1411 AFS_TRACE_LEVEL_VERBOSE,
1412 "AFSVerifyDirectoryContent Insert DE %p to head of case insensitive tree for %wZ\n",
1414 &pDirNode->NameInformation.FileName);
1419 AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1422 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1423 AFS_TRACE_LEVEL_VERBOSE,
1424 "AFSVerifyDirectoryContent Insert DE %p to case insensitive tree for %wZ\n",
1426 &pDirNode->NameInformation.FileName);
1429 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
1432 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
1437 (ObjectInfoCB->Specific.Directory.DirectoryNodeListTail)->ListEntry.fLink = pDirNode;
1439 pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
1442 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
1444 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
1446 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
1448 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1449 AFS_TRACE_LEVEL_VERBOSE,
1450 "AFSVerifyDirectoryContent Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
1451 &pDirNode->NameInformation.FileName,
1452 ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
1453 ObjectInfoCB->FileId.Cell,
1454 ObjectInfoCB->FileId.Volume,
1455 ObjectInfoCB->FileId.Vnode,
1456 ObjectInfoCB->FileId.Unique);
1458 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
1462 // Insert the short name entry if we have a valid short name
1465 if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
1468 ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
1470 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1471 AFS_TRACE_LEVEL_VERBOSE,
1472 "AFSVerifyDirectoryContent Insert DE %p to head of shortname tree for %wZ\n",
1474 &pDirNode->NameInformation.FileName);
1476 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1481 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
1484 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1485 AFS_TRACE_LEVEL_VERBOSE,
1486 "AFSVerifyDirectoryContent Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
1488 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex,
1489 &pDirNode->NameInformation.FileName);
1493 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1495 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1496 AFS_TRACE_LEVEL_VERBOSE,
1497 "AFSVerifyDirectoryContent Insert DE %p to shortname tree for %wZ\n",
1499 &pDirNode->NameInformation.FileName);
1504 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
1510 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1512 if( ulResultLen >= ulEntryLength)
1514 ulResultLen -= ulEntryLength;
1522 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
1525 // Reset the information in the request buffer since it got trampled
1529 pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
1538 if( pBuffer != NULL)
1541 AFSExFreePoolWithTag( pBuffer, AFS_DIR_BUFFER_TAG);
1549 AFSNotifyFileCreate( IN GUID *AuthGroup,
1550 IN AFSObjectInfoCB *ParentObjectInfo,
1551 IN PLARGE_INTEGER FileSize,
1552 IN ULONG FileAttributes,
1553 IN UNICODE_STRING *FileName,
1554 OUT AFSDirectoryCB **DirNode)
1557 NTSTATUS ntStatus = STATUS_SUCCESS;
1558 AFSFileCreateCB stCreateCB;
1559 AFSFileCreateResultCB *pResultCB = NULL;
1560 ULONG ulResultLen = 0;
1561 UNICODE_STRING uniTargetName;
1562 AFSDirectoryCB *pDirNode = NULL;
1565 LARGE_INTEGER liOldDataVersion;
1566 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1567 BOOLEAN bReleaseParentTreeLock = FALSE;
1575 // Init the control block for the request
1578 RtlZeroMemory( &stCreateCB,
1579 sizeof( AFSFileCreateCB));
1581 stCreateCB.ParentId = ParentObjectInfo->FileId;
1583 stCreateCB.AllocationSize = *FileSize;
1585 stCreateCB.FileAttributes = FileAttributes;
1587 stCreateCB.EaSize = 0;
1589 liOldDataVersion = ParentObjectInfo->DataVersion;
1592 // Allocate our return buffer
1595 pResultCB = (AFSFileCreateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1597 AFS_GENERIC_MEMORY_1_TAG);
1599 if( pResultCB == NULL)
1602 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1605 RtlZeroMemory( pResultCB,
1608 ulResultLen = PAGE_SIZE;
1611 // Send the call to the service
1614 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_FILE,
1615 AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_HOLD_FID,
1622 sizeof( AFSFileCreateCB),
1626 if( ntStatus != STATUS_SUCCESS)
1629 if( NT_SUCCESS( ntStatus))
1632 ntStatus = STATUS_DEVICE_NOT_READY;
1635 try_return( ntStatus);
1639 // We may have raced with an invalidation call and a subsequent re-enumeration of this parent
1640 // and though we created the node, it is already in our list. If this is the case then
1641 // look up the entry rather than create a new entry
1642 // The check is to ensure the DV has been modified
1645 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1648 bReleaseParentTreeLock = TRUE;
1650 if( ParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
1653 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1654 AFS_TRACE_LEVEL_WARNING,
1655 "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",
1657 ParentObjectInfo->FileId.Cell,
1658 ParentObjectInfo->FileId.Volume,
1659 ParentObjectInfo->FileId.Vnode,
1660 ParentObjectInfo->FileId.Unique,
1661 ParentObjectInfo->DataVersion.HighPart,
1662 ParentObjectInfo->DataVersion.LowPart,
1663 pResultCB->ParentDataVersion.HighPart,
1664 pResultCB->ParentDataVersion.LowPart);
1667 // We raced so go and lookup the directory entry in the parent
1670 ulCRC = AFSGenerateCRC( FileName,
1673 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1677 if( pDirNode != NULL)
1680 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1681 AFS_TRACE_LEVEL_VERBOSE,
1682 "AFSNotifyFileCreate Located dir entry %p for file %wZ\n",
1686 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
1687 &pResultCB->DirEnum.FileId))
1690 *DirNode = pDirNode;
1692 try_return( ntStatus = STATUS_REPARSE);
1698 // We found an entry that matches the desired name but it is not the
1699 // same as the one that was created for us by the file server.
1702 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1703 AFS_TRACE_LEVEL_ERROR,
1704 "AFSNotifyFileCreate Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
1707 pDirNode->ObjectInformation->FileId.Cell,
1708 pDirNode->ObjectInformation->FileId.Volume,
1709 pDirNode->ObjectInformation->FileId.Vnode,
1710 pDirNode->ObjectInformation->FileId.Unique,
1711 pResultCB->DirEnum.FileId.Cell,
1712 pResultCB->DirEnum.FileId.Volume,
1713 pResultCB->DirEnum.FileId.Vnode,
1714 pResultCB->DirEnum.FileId.Unique);
1716 if( pDirNode->DirOpenReferenceCount <= 0 &&
1717 pDirNode->NameArrayReferenceCount <= 0)
1720 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1721 AFS_TRACE_LEVEL_VERBOSE,
1722 "AFSNotifyFileCreate Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1724 &pDirNode->NameInformation.FileName,
1725 pDirNode->ObjectInformation->FileId.Cell,
1726 pDirNode->ObjectInformation->FileId.Volume,
1727 pDirNode->ObjectInformation->FileId.Vnode,
1728 pDirNode->ObjectInformation->FileId.Unique,
1729 pResultCB->DirEnum.FileId.Cell,
1730 pResultCB->DirEnum.FileId.Volume,
1731 pResultCB->DirEnum.FileId.Vnode,
1732 pResultCB->DirEnum.FileId.Unique);
1734 AFSDeleteDirEntry( ParentObjectInfo,
1740 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1742 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1743 AFS_TRACE_LEVEL_VERBOSE,
1744 "AFSNotifyFileCreate Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1746 &pDirNode->NameInformation.FileName,
1747 pDirNode->ObjectInformation->FileId.Cell,
1748 pDirNode->ObjectInformation->FileId.Volume,
1749 pDirNode->ObjectInformation->FileId.Vnode,
1750 pDirNode->ObjectInformation->FileId.Unique,
1751 pResultCB->DirEnum.FileId.Cell,
1752 pResultCB->DirEnum.FileId.Volume,
1753 pResultCB->DirEnum.FileId.Vnode,
1754 pResultCB->DirEnum.FileId.Unique);
1756 AFSRemoveNameEntry( ParentObjectInfo,
1765 // We are unsure of our current data so set the verify flag. It may already be set
1766 // but no big deal to reset it
1769 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1771 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1774 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1775 AFS_TRACE_LEVEL_VERBOSE,
1776 "AFSNotifyFileCreate Creating new entry %wZ\n",
1780 // Initialize the directory entry
1783 uniTargetName.Length = (USHORT)pResultCB->DirEnum.TargetNameLength;
1785 uniTargetName.MaximumLength = uniTargetName.Length;
1787 uniTargetName.Buffer = (WCHAR *)((char *)&pResultCB->DirEnum + pResultCB->DirEnum.TargetNameOffset);
1789 pDirNode = AFSInitDirEntry( ParentObjectInfo,
1792 &pResultCB->DirEnum,
1793 (ULONG)InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1795 if( pDirNode == NULL)
1798 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1800 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1802 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1806 // Init the short name if we have one
1809 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1810 pResultCB->DirEnum.ShortNameLength > 0)
1813 UNICODE_STRING uniShortName;
1815 pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
1817 RtlCopyMemory( pDirNode->NameInformation.ShortName,
1818 pResultCB->DirEnum.ShortName,
1819 pDirNode->NameInformation.ShortNameLength);
1822 // Generate the short name index
1825 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1826 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1828 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1831 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1832 AFS_TRACE_LEVEL_VERBOSE,
1833 "AFSNotifyFileCreate Initialized short name %wZ for DE %p for %wZ\n",
1836 &pDirNode->NameInformation.FileName);
1841 // No short name or short names are disabled
1844 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
1847 if ( !BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1851 // Update the parent data version
1854 ParentObjectInfo->DataVersion = pResultCB->ParentDataVersion;
1856 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1857 AFS_TRACE_LEVEL_VERBOSE,
1858 "AFSNotifyFileCreate entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
1860 ParentObjectInfo->FileId.Cell,
1861 ParentObjectInfo->FileId.Volume,
1862 ParentObjectInfo->FileId.Vnode,
1863 ParentObjectInfo->FileId.Unique,
1864 ParentObjectInfo->DataVersion.QuadPart);
1868 // Return the directory node
1871 *DirNode = pDirNode;
1875 if ( *DirNode != NULL)
1878 lCount = InterlockedIncrement( &(*DirNode)->DirOpenReferenceCount);
1880 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1881 AFS_TRACE_LEVEL_VERBOSE,
1882 "AFSNotifyFileCreate Increment count on %wZ DE %p Cnt %d\n",
1883 &(*DirNode)->NameInformation.FileName,
1887 ASSERT( lCount >= 0);
1890 if ( bReleaseParentTreeLock)
1893 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1896 if( pResultCB != NULL)
1899 AFSExFreePoolWithTag( pResultCB, AFS_GENERIC_MEMORY_1_TAG);
1907 AFSUpdateFileInformation( IN AFSFileID *ParentFid,
1908 IN AFSObjectInfoCB *ObjectInfo,
1912 NTSTATUS ntStatus = STATUS_SUCCESS;
1913 AFSFileUpdateCB stUpdateCB;
1914 ULONG ulResultLen = 0;
1915 AFSFileUpdateResultCB *pUpdateResultCB = NULL;
1921 // Init the control block for the request
1924 RtlZeroMemory( &stUpdateCB,
1925 sizeof( AFSFileUpdateCB));
1927 stUpdateCB.AllocationSize = ObjectInfo->EndOfFile;
1929 stUpdateCB.FileAttributes = ObjectInfo->FileAttributes;
1931 stUpdateCB.EaSize = ObjectInfo->EaSize;
1933 stUpdateCB.ParentId = *ParentFid;
1935 stUpdateCB.LastAccessTime = ObjectInfo->LastAccessTime;
1937 stUpdateCB.CreateTime = ObjectInfo->CreationTime;
1939 stUpdateCB.ChangeTime = ObjectInfo->ChangeTime;
1941 stUpdateCB.LastWriteTime = ObjectInfo->LastWriteTime;
1943 pUpdateResultCB = (AFSFileUpdateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1945 AFS_UPDATE_RESULT_TAG);
1947 if( pUpdateResultCB == NULL)
1950 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1953 ulResultLen = PAGE_SIZE;
1955 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_UPDATE_FILE,
1956 AFS_REQUEST_FLAG_SYNCHRONOUS,
1959 &ObjectInfo->FileId,
1960 ObjectInfo->VolumeCB->VolumeInformation.Cell,
1961 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
1963 sizeof( AFSFileUpdateCB),
1967 if( ntStatus != STATUS_SUCCESS)
1970 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1971 AFS_TRACE_LEVEL_ERROR,
1972 "AFSUpdateFileInformation failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1973 ObjectInfo->FileId.Cell,
1974 ObjectInfo->FileId.Volume,
1975 ObjectInfo->FileId.Vnode,
1976 ObjectInfo->FileId.Unique,
1979 try_return( ntStatus);
1983 // Update the data version
1986 AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1989 if ( !BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1992 ObjectInfo->DataVersion = pUpdateResultCB->DirEnum.DataVersion;
1995 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1999 if( pUpdateResultCB != NULL)
2002 AFSExFreePoolWithTag( pUpdateResultCB, AFS_UPDATE_RESULT_TAG);
2010 AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
2012 IN BOOLEAN CheckOnly)
2014 NTSTATUS ntStatus = STATUS_SUCCESS;
2015 ULONG ulResultLen = 0;
2016 AFSFileDeleteCB stDelete;
2017 AFSFileDeleteResultCB stDeleteResult;
2018 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
2019 AFSObjectInfoCB *pObjectInfo = NULL;
2020 AFSObjectInfoCB *pParentObjectInfo = NULL;
2025 pObjectInfo = DirectoryCB->ObjectInformation;
2027 pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
2028 &pObjectInfo->ParentFileId);
2030 stDelete.ParentId = pObjectInfo->ParentFileId;
2032 stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
2034 ulResultLen = sizeof( AFSFileDeleteResultCB);
2038 ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
2041 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
2044 &DirectoryCB->NameInformation.FileName,
2045 &pObjectInfo->FileId,
2046 pObjectInfo->VolumeCB->VolumeInformation.Cell,
2047 pObjectInfo->VolumeCB->VolumeInformation.CellLength,
2049 sizeof( AFSFileDeleteCB),
2053 if( ntStatus != STATUS_SUCCESS)
2056 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2057 AFS_TRACE_LEVEL_ERROR,
2058 "AFSNotifyDelete failed ParentFID %08lX-%08lX-%08lX-%08lX %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2059 stDelete.ParentId.Cell,
2060 stDelete.ParentId.Volume,
2061 stDelete.ParentId.Vnode,
2062 stDelete.ParentId.Unique,
2063 &DirectoryCB->NameInformation.FileName,
2064 pObjectInfo->FileId.Cell,
2065 pObjectInfo->FileId.Volume,
2066 pObjectInfo->FileId.Vnode,
2067 pObjectInfo->FileId.Unique,
2070 try_return( ntStatus);
2073 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2080 // Validate the parent data version
2083 if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
2086 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2088 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2095 // Update the parent data version
2098 if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart - 1)
2101 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2103 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2109 // TODO -- The entry must be removed from the directory at which point the
2110 // Directory data version number can be updated. Until then we must force
2113 // pParentObjectInfor->DataVersion.QuadPart = stDeleteResult.ParentDataVersion.QuadPart;
2116 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2118 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2122 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2126 if ( pParentObjectInfo)
2129 AFSReleaseObjectInfo( &pParentObjectInfo);
2138 AFSNotifyHardLink( IN AFSObjectInfoCB *ObjectInfo,
2140 IN AFSObjectInfoCB *ParentObjectInfo,
2141 IN AFSObjectInfoCB *TargetParentObjectInfo,
2142 IN AFSDirectoryCB *SourceDirectoryCB,
2143 IN UNICODE_STRING *TargetName,
2144 IN BOOLEAN bReplaceIfExists,
2145 OUT AFSDirectoryCB **TargetDirectoryCB)
2148 NTSTATUS ntStatus = STATUS_SUCCESS;
2149 AFSFileHardLinkCB *pHardLinkCB = NULL;
2150 AFSFileHardLinkResultCB *pResultCB = NULL;
2151 ULONG ulResultLen = 0;
2152 AFSDirectoryCB *pDirNode = NULL;
2154 BOOLEAN bReleaseParentLock = FALSE, bReleaseTargetParentLock = FALSE;
2155 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2162 // Init the control block for the request
2165 pHardLinkCB = (AFSFileHardLinkCB *)AFSExAllocatePoolWithTag( PagedPool,
2167 AFS_HARDLINK_REQUEST_TAG);
2169 if( pHardLinkCB == NULL)
2172 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2175 RtlZeroMemory( pHardLinkCB,
2178 pHardLinkCB->SourceParentId = ParentObjectInfo->FileId;
2180 pHardLinkCB->TargetParentId = TargetParentObjectInfo->FileId;
2182 pHardLinkCB->TargetNameLength = TargetName->Length;
2184 RtlCopyMemory( pHardLinkCB->TargetName,
2186 TargetName->Length);
2188 pHardLinkCB->bReplaceIfExists = bReplaceIfExists;
2191 // Use the same buffer for the result control block
2194 pResultCB = (AFSFileHardLinkResultCB *)pHardLinkCB;
2196 ulResultLen = PAGE_SIZE;
2198 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_HARDLINK_FILE,
2199 AFS_REQUEST_FLAG_SYNCHRONOUS,
2201 &SourceDirectoryCB->NameInformation.FileName,
2202 &ObjectInfo->FileId,
2203 ObjectInfo->VolumeCB->VolumeInformation.Cell,
2204 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2206 sizeof( AFSFileHardLinkCB) + TargetName->Length,
2210 if( ntStatus != STATUS_SUCCESS)
2213 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2214 AFS_TRACE_LEVEL_ERROR,
2215 "AFSNotifyHardLink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2216 ObjectInfo->FileId.Cell,
2217 ObjectInfo->FileId.Volume,
2218 ObjectInfo->FileId.Vnode,
2219 ObjectInfo->FileId.Unique,
2222 try_return( ntStatus);
2226 // Update the information from the returned data
2229 if ( ParentObjectInfo != TargetParentObjectInfo)
2232 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2235 bReleaseParentLock = TRUE;
2237 if ( ParentObjectInfo->DataVersion.QuadPart == pResultCB->SourceParentDataVersion.QuadPart - 1)
2240 ParentObjectInfo->DataVersion = pResultCB->SourceParentDataVersion;
2245 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2247 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2251 AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2254 bReleaseTargetParentLock = TRUE;
2256 if ( TargetParentObjectInfo->DataVersion.QuadPart == pResultCB->TargetParentDataVersion.QuadPart - 1)
2259 TargetParentObjectInfo->DataVersion = pResultCB->TargetParentDataVersion;
2264 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2265 AFS_TRACE_LEVEL_WARNING,
2266 "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",
2268 TargetParentObjectInfo->FileId.Cell,
2269 TargetParentObjectInfo->FileId.Volume,
2270 TargetParentObjectInfo->FileId.Vnode,
2271 TargetParentObjectInfo->FileId.Unique,
2272 TargetParentObjectInfo->DataVersion.HighPart,
2273 TargetParentObjectInfo->DataVersion.LowPart,
2274 pResultCB->TargetParentDataVersion.HighPart,
2275 pResultCB->TargetParentDataVersion.LowPart);
2278 // We raced so go and lookup the directory entry in the parent
2281 ulCRC = AFSGenerateCRC( TargetName,
2284 AFSLocateCaseSensitiveDirEntry( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2288 if( pDirNode != NULL)
2291 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2292 AFS_TRACE_LEVEL_VERBOSE,
2293 "AFSNotifyHardLink Located dir entry %p for file %wZ\n",
2297 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2298 &pResultCB->DirEnum.FileId))
2301 try_return( ntStatus = STATUS_REPARSE);
2307 // We found an entry that matches the desired name but it is not the
2308 // same as the one that was created for us by the file server.
2311 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2312 AFS_TRACE_LEVEL_ERROR,
2313 "AFSNotifyHardLink Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
2316 pDirNode->ObjectInformation->FileId.Cell,
2317 pDirNode->ObjectInformation->FileId.Volume,
2318 pDirNode->ObjectInformation->FileId.Vnode,
2319 pDirNode->ObjectInformation->FileId.Unique,
2320 pResultCB->DirEnum.FileId.Cell,
2321 pResultCB->DirEnum.FileId.Volume,
2322 pResultCB->DirEnum.FileId.Vnode,
2323 pResultCB->DirEnum.FileId.Unique);
2325 if( pDirNode->DirOpenReferenceCount <= 0 &&
2326 pDirNode->NameArrayReferenceCount <= 0)
2329 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2330 AFS_TRACE_LEVEL_VERBOSE,
2331 "AFSNotifyHardLink Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2333 &pDirNode->NameInformation.FileName,
2334 pDirNode->ObjectInformation->FileId.Cell,
2335 pDirNode->ObjectInformation->FileId.Volume,
2336 pDirNode->ObjectInformation->FileId.Vnode,
2337 pDirNode->ObjectInformation->FileId.Unique,
2338 pResultCB->DirEnum.FileId.Cell,
2339 pResultCB->DirEnum.FileId.Volume,
2340 pResultCB->DirEnum.FileId.Vnode,
2341 pResultCB->DirEnum.FileId.Unique);
2343 AFSDeleteDirEntry( TargetParentObjectInfo,
2349 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2351 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2352 AFS_TRACE_LEVEL_VERBOSE,
2353 "AFSNotifyHardLink Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2355 &pDirNode->NameInformation.FileName,
2356 pDirNode->ObjectInformation->FileId.Cell,
2357 pDirNode->ObjectInformation->FileId.Volume,
2358 pDirNode->ObjectInformation->FileId.Vnode,
2359 pDirNode->ObjectInformation->FileId.Unique,
2360 pResultCB->DirEnum.FileId.Cell,
2361 pResultCB->DirEnum.FileId.Volume,
2362 pResultCB->DirEnum.FileId.Vnode,
2363 pResultCB->DirEnum.FileId.Unique);
2365 AFSRemoveNameEntry( TargetParentObjectInfo,
2374 // We are unsure of our current data so set the verify flag. It may already be set
2375 // but no big deal to reset it
2378 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2380 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2384 // Create the hard link entry
2387 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2388 AFS_TRACE_LEVEL_VERBOSE,
2389 "AFSNotifyHardLink Creating new entry %wZ\n",
2393 // Initialize the directory entry
2396 pDirNode = AFSInitDirEntry( TargetParentObjectInfo,
2399 &pResultCB->DirEnum,
2400 (ULONG)InterlockedIncrement( &TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
2402 if( pDirNode == NULL)
2405 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2407 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2409 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2413 // Init the short name if we have one
2416 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2417 pResultCB->DirEnum.ShortNameLength > 0)
2420 UNICODE_STRING uniShortName;
2422 pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
2424 RtlCopyMemory( pDirNode->NameInformation.ShortName,
2425 pResultCB->DirEnum.ShortName,
2426 pDirNode->NameInformation.ShortNameLength);
2429 // Generate the short name index
2432 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
2433 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
2435 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
2438 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2439 AFS_TRACE_LEVEL_VERBOSE,
2440 "AFSNotifyHardLink Initialized short name %wZ for DE %p for %wZ\n",
2443 &pDirNode->NameInformation.FileName);
2448 // No short name or short names are disabled
2451 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2454 if ( !BooleanFlagOn( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2458 // Update the target parent data version
2461 TargetParentObjectInfo->DataVersion = pResultCB->TargetParentDataVersion;
2463 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2464 AFS_TRACE_LEVEL_VERBOSE,
2465 "AFSNotifyHardLink entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
2467 TargetParentObjectInfo->FileId.Cell,
2468 TargetParentObjectInfo->FileId.Volume,
2469 TargetParentObjectInfo->FileId.Vnode,
2470 TargetParentObjectInfo->FileId.Unique,
2471 TargetParentObjectInfo->DataVersion.QuadPart);
2476 if ( TargetDirectoryCB != NULL)
2479 lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
2481 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2482 AFS_TRACE_LEVEL_VERBOSE,
2483 "AFSNotifyHardLink Increment count on %wZ DE %p Cnt %d\n",
2484 &pDirNode->NameInformation.FileName,
2488 ASSERT( lCount >= 0);
2490 *TargetDirectoryCB = pDirNode;
2493 if ( bReleaseTargetParentLock)
2496 AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2499 if ( bReleaseParentLock)
2502 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2505 if( pHardLinkCB != NULL)
2508 AFSExFreePoolWithTag( pHardLinkCB, AFS_HARDLINK_REQUEST_TAG);
2518 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
2520 IN AFSObjectInfoCB *ParentObjectInfo,
2521 IN AFSObjectInfoCB *TargetParentObjectInfo,
2522 IN AFSDirectoryCB *DirectoryCB,
2523 IN UNICODE_STRING *TargetName,
2524 OUT AFSFileID *UpdatedFID)
2527 NTSTATUS ntStatus = STATUS_SUCCESS;
2528 AFSFileRenameCB *pRenameCB = NULL;
2529 AFSFileRenameResultCB *pRenameResultCB = NULL;
2530 ULONG ulResultLen = 0;
2531 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2537 // Init the control block for the request
2540 pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
2542 AFS_RENAME_REQUEST_TAG);
2544 if( pRenameCB == NULL)
2547 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2550 RtlZeroMemory( pRenameCB,
2553 pRenameCB->SourceParentId = ParentObjectInfo->FileId;
2555 pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
2557 pRenameCB->TargetNameLength = TargetName->Length;
2559 RtlCopyMemory( pRenameCB->TargetName,
2561 TargetName->Length);
2564 // Use the same buffer for the result control block
2567 pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
2569 ulResultLen = PAGE_SIZE;
2571 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
2572 AFS_REQUEST_FLAG_SYNCHRONOUS,
2574 &DirectoryCB->NameInformation.FileName,
2575 &ObjectInfo->FileId,
2576 ObjectInfo->VolumeCB->VolumeInformation.Cell,
2577 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2579 sizeof( AFSFileRenameCB) + TargetName->Length,
2583 if( ntStatus != STATUS_SUCCESS)
2586 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2587 AFS_TRACE_LEVEL_ERROR,
2588 "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2589 ObjectInfo->FileId.Cell,
2590 ObjectInfo->FileId.Volume,
2591 ObjectInfo->FileId.Vnode,
2592 ObjectInfo->FileId.Unique,
2595 try_return( ntStatus);
2599 // Update the information from the returned data
2602 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2605 if ( ParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->SourceParentDataVersion.QuadPart - 1)
2608 ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
2613 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2615 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2618 if ( ParentObjectInfo != TargetParentObjectInfo)
2621 AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2624 if ( TargetParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->TargetParentDataVersion.QuadPart - 1)
2627 TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
2632 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2634 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2639 // Move over the short name
2642 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2644 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2645 DirectoryCB->NameInformation.ShortNameLength > 0)
2648 UNICODE_STRING uniShortName;
2650 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2651 uniShortName.MaximumLength = uniShortName.Length;
2652 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2654 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2655 AFS_TRACE_LEVEL_VERBOSE,
2656 "AFSNotifyRename Update old short name %wZ for DE %p for %wZ\n",
2659 &DirectoryCB->NameInformation.FileName);
2661 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2663 RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
2664 pRenameResultCB->DirEnum.ShortName,
2665 DirectoryCB->NameInformation.ShortNameLength);
2667 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2668 uniShortName.MaximumLength = uniShortName.Length;
2669 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2671 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2672 AFS_TRACE_LEVEL_VERBOSE,
2673 "AFSNotifyRename Initialized short name %wZ for DE %p for %wZ\n",
2676 &DirectoryCB->NameInformation.FileName);
2681 UNICODE_STRING uniShortName;
2683 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2684 uniShortName.MaximumLength = uniShortName.Length;
2685 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2687 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2688 AFS_TRACE_LEVEL_VERBOSE,
2689 "AFSNotifyRename Removing old short name %wZ for DE %p for %wZ\n",
2692 &DirectoryCB->NameInformation.FileName);
2694 DirectoryCB->NameInformation.ShortNameLength = 0;
2696 DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2699 if ( ParentObjectInfo != TargetParentObjectInfo)
2702 AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2705 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2707 if( UpdatedFID != NULL)
2709 *UpdatedFID = pRenameResultCB->DirEnum.FileId;
2714 if( pRenameCB != NULL)
2717 AFSExFreePoolWithTag( pRenameCB, AFS_RENAME_REQUEST_TAG);
2725 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
2727 IN BOOLEAN FastCall,
2728 OUT AFSDirEnumEntry **DirEnumEntry)
2731 NTSTATUS ntStatus = STATUS_SUCCESS;
2732 AFSEvalTargetCB stTargetID;
2733 ULONG ulResultBufferLength;
2734 AFSFileEvalResultCB *pEvalResultCB = NULL;
2735 AFSDirEnumEntry *pDirEnumCB = NULL;
2736 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
2737 AFSObjectInfoCB *pParentObjectInfo = NULL;
2742 RtlZeroMemory( &stTargetID,
2743 sizeof( AFSEvalTargetCB));
2745 if ( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2748 pParentObjectInfo = AFSFindObjectInfo( ObjectInfo->VolumeCB,
2749 &ObjectInfo->ParentFileId);
2751 stTargetID.ParentId = ObjectInfo->ParentFileId;
2755 // Allocate our response buffer
2758 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2760 AFS_GENERIC_MEMORY_30_TAG);
2762 if( pEvalResultCB == NULL)
2765 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2769 // Call to the service to evaluate the fid
2772 ulResultBufferLength = PAGE_SIZE;
2777 ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
2780 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
2784 &ObjectInfo->FileId,
2785 ObjectInfo->VolumeCB->VolumeInformation.Cell,
2786 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2788 sizeof( AFSEvalTargetCB),
2790 &ulResultBufferLength);
2792 if( ntStatus != STATUS_SUCCESS)
2796 // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
2800 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2803 if( pParentObjectInfo != NULL)
2806 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2809 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2811 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2813 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2817 try_return( ntStatus);
2821 // A BSOD can occur if the pEvalResultCB->FileType is FILE but the
2822 // ObjectInfo->FileType is something else. The same is true for
2823 // pDirEnumEntry->FileType is DIRECTORY. Perform a sanity check
2824 // to ensure consistency. An inconsistent pDirEnumEntry can be
2825 // produced as a result of invalid status info received from a file
2826 // server. If the types are inconsistent or if the type does not
2827 // match the implied type derived from the vnode (odd values are
2828 // directories and even values are other types), prevent the request
2829 // from completing successfully. This may prevent access to the file or
2830 // directory but will prevent a BSOD.
2833 if ( !AFSIsEqualFID( &ObjectInfo->FileId,
2834 &pEvalResultCB->DirEnum.FileId))
2837 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2840 switch ( pEvalResultCB->DirEnum.FileType)
2843 case AFS_FILE_TYPE_DIRECTORY:
2844 if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x1)
2847 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2850 if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
2851 ObjectInfo->FileType != AFS_FILE_TYPE_DIRECTORY)
2854 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2859 case AFS_FILE_TYPE_FILE:
2860 if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x0)
2863 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2866 if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
2867 ObjectInfo->FileType != AFS_FILE_TYPE_FILE)
2870 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2877 // Validate the parent data version
2880 if ( pParentObjectInfo != NULL)
2883 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2886 if ( pParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2889 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2891 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2894 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2898 // Pass back the dir enum entry
2901 if( DirEnumEntry != NULL)
2904 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2906 AFS_GENERIC_MEMORY_2_TAG);
2908 if( pDirEnumCB == NULL)
2911 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2914 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2915 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2917 *DirEnumEntry = pDirEnumCB;
2922 if ( pParentObjectInfo != NULL)
2925 AFSReleaseObjectInfo( &pParentObjectInfo);
2928 if( pEvalResultCB != NULL)
2931 AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_30_TAG);
2934 if( !NT_SUCCESS( ntStatus))
2937 if( pDirEnumCB != NULL)
2940 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_2_TAG);
2943 *DirEnumEntry = NULL;
2951 AFSEvaluateTargetByName( IN GUID *AuthGroup,
2952 IN AFSObjectInfoCB *ParentObjectInfo,
2953 IN PUNICODE_STRING SourceName,
2955 OUT AFSDirEnumEntry **DirEnumEntry)
2958 NTSTATUS ntStatus = STATUS_SUCCESS;
2959 AFSEvalTargetCB stTargetID;
2960 ULONG ulResultBufferLength;
2961 AFSFileEvalResultCB *pEvalResultCB = NULL;
2962 AFSDirEnumEntry *pDirEnumCB = NULL;
2967 stTargetID.ParentId = ParentObjectInfo->FileId;
2970 // Allocate our response buffer
2973 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2975 AFS_GENERIC_MEMORY_31_TAG);
2977 if( pEvalResultCB == NULL)
2980 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2984 // Call to the service to evaluate the fid
2987 ulResultBufferLength = PAGE_SIZE;
2989 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
2990 AFS_REQUEST_FLAG_SYNCHRONOUS | Flags,
2994 ParentObjectInfo->VolumeCB->VolumeInformation.Cell,
2995 ParentObjectInfo->VolumeCB->VolumeInformation.CellLength,
2997 sizeof( AFSEvalTargetCB),
2999 &ulResultBufferLength);
3001 if( ntStatus != STATUS_SUCCESS)
3004 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
3007 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3010 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3012 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
3014 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3017 try_return( ntStatus);
3021 // Validate the parent data version
3024 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3027 if ( ParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
3030 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3032 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
3035 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3038 // Pass back the dir enum entry
3041 if( DirEnumEntry != NULL)
3044 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
3046 AFS_GENERIC_MEMORY_3_TAG);
3048 if( pDirEnumCB == NULL)
3051 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3054 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
3055 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
3057 *DirEnumEntry = pDirEnumCB;
3062 if( pEvalResultCB != NULL)
3065 AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_31_TAG);
3068 if( !NT_SUCCESS( ntStatus))
3071 if( pDirEnumCB != NULL)
3074 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_3_TAG);
3077 *DirEnumEntry = NULL;
3085 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
3086 IN AFSFileID *FileID,
3087 OUT AFSVolumeInfoCB *VolumeInformation)
3090 NTSTATUS ntStatus = STATUS_SUCCESS;
3091 ULONG ulResultLen = 0;
3096 ulResultLen = sizeof( AFSVolumeInfoCB);
3098 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
3099 AFS_REQUEST_FLAG_SYNCHRONOUS,
3110 if( ntStatus != STATUS_SUCCESS)
3113 try_return( ntStatus);
3125 AFSRetrieveVolumeSizeInformation( IN GUID *AuthGroup,
3126 IN AFSFileID *FileID,
3127 OUT AFSVolumeSizeInfoCB *VolumeSizeInformation)
3130 NTSTATUS ntStatus = STATUS_SUCCESS;
3131 ULONG ulResultLen = 0;
3136 ulResultLen = sizeof( AFSVolumeSizeInfoCB);
3138 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_SIZE_INFO,
3139 AFS_REQUEST_FLAG_SYNCHRONOUS,
3147 VolumeSizeInformation,
3150 if( ntStatus != STATUS_SUCCESS)
3153 try_return( ntStatus);
3165 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
3166 IN ULONG InputLength,
3167 IN ULONG OutputLength,
3168 IN void *InputDataBuffer,
3169 OUT void *OutputDataBuffer,
3170 OUT ULONG *BytesReturned)
3173 NTSTATUS ntStatus = STATUS_SUCCESS;
3174 ULONG ulResultLen = 0;
3175 MDL *pInputMdl = NULL, *pOutputMdl = NULL;
3176 void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
3177 AFSPipeIORequestCB *pIoRequest = NULL;
3183 // Map the user buffer to a system address
3186 pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
3190 if( pInputSystemBuffer == NULL)
3193 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3196 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
3197 sizeof( AFSPipeIORequestCB) +
3199 AFS_GENERIC_MEMORY_4_TAG);
3201 if( pIoRequest == NULL)
3204 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3207 RtlZeroMemory( pIoRequest,
3208 sizeof( AFSPipeIORequestCB) + InputLength);
3210 pIoRequest->RequestId = Ccb->RequestID;
3212 pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3214 pIoRequest->BufferLength = InputLength;
3216 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
3220 pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
3224 if( pOutputSystemBuffer == NULL)
3227 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3231 // Send the call to the service
3234 ulResultLen = OutputLength;
3236 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
3237 AFS_REQUEST_FLAG_SYNCHRONOUS,
3239 &Ccb->DirectoryCB->NameInformation.FileName,
3244 sizeof( AFSPipeIORequestCB) + InputLength,
3245 pOutputSystemBuffer,
3248 if( ntStatus != STATUS_SUCCESS &&
3249 ntStatus != STATUS_BUFFER_OVERFLOW)
3252 if( NT_SUCCESS( ntStatus))
3255 ntStatus = STATUS_DEVICE_NOT_READY;
3258 try_return( ntStatus);
3262 // Return the bytes processed
3265 *BytesReturned = ulResultLen;
3269 if( pInputMdl != NULL)
3272 MmUnlockPages( pInputMdl);
3274 IoFreeMdl( pInputMdl);
3277 if( pOutputMdl != NULL)
3280 MmUnlockPages( pOutputMdl);
3282 IoFreeMdl( pOutputMdl);
3285 if( pIoRequest != NULL)
3288 AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_4_TAG);
3296 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
3297 IN ULONG InformationClass,
3298 IN ULONG InputLength,
3299 IN void *DataBuffer)
3302 NTSTATUS ntStatus = STATUS_SUCCESS;
3303 AFSPipeInfoRequestCB *pInfoRequest = NULL;
3308 pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
3309 sizeof( AFSPipeInfoRequestCB) +
3311 AFS_GENERIC_MEMORY_5_TAG);
3313 if( pInfoRequest == NULL)
3316 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3319 RtlZeroMemory( pInfoRequest,
3320 sizeof( AFSPipeInfoRequestCB) + InputLength);
3322 pInfoRequest->RequestId = Ccb->RequestID;
3324 pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3326 pInfoRequest->BufferLength = InputLength;
3328 pInfoRequest->InformationClass = InformationClass;
3330 RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
3335 // Send the call to the service
3338 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
3339 AFS_REQUEST_FLAG_SYNCHRONOUS,
3341 &Ccb->DirectoryCB->NameInformation.FileName,
3346 sizeof( AFSPipeInfoRequestCB) + InputLength,
3350 if( ntStatus != STATUS_SUCCESS)
3353 if( NT_SUCCESS( ntStatus))
3356 ntStatus = STATUS_DEVICE_NOT_READY;
3359 try_return( ntStatus);
3364 if( pInfoRequest != NULL)
3367 AFSExFreePoolWithTag( pInfoRequest, AFS_GENERIC_MEMORY_5_TAG);
3375 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
3376 IN ULONG InformationClass,
3377 IN ULONG OutputLength,
3378 IN void *DataBuffer,
3379 OUT ULONG *BytesReturned)
3382 NTSTATUS ntStatus = STATUS_SUCCESS;
3383 AFSPipeInfoRequestCB stInfoRequest;
3384 ULONG ulBytesProcessed = 0;
3389 RtlZeroMemory( &stInfoRequest,
3390 sizeof( AFSPipeInfoRequestCB));
3392 stInfoRequest.RequestId = Ccb->RequestID;
3394 stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3396 stInfoRequest.BufferLength = OutputLength;
3398 stInfoRequest.InformationClass = InformationClass;
3400 ulBytesProcessed = OutputLength;
3403 // Send the call to the service
3406 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
3407 AFS_REQUEST_FLAG_SYNCHRONOUS,
3409 &Ccb->DirectoryCB->NameInformation.FileName,
3414 sizeof( AFSPipeInfoRequestCB),
3418 if( ntStatus != STATUS_SUCCESS)
3421 if( NT_SUCCESS( ntStatus))
3424 ntStatus = STATUS_DEVICE_NOT_READY;
3427 try_return( ntStatus);
3430 *BytesReturned = ulBytesProcessed;
3441 AFSReleaseFid( IN AFSFileID *FileId)
3444 NTSTATUS ntStatus = STATUS_SUCCESS;
3449 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
3466 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
3467 IN LARGE_INTEGER *ExtentOffset,
3471 BOOLEAN bRequestQueued = FALSE;
3472 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3473 AFSCommSrvcCB *pCommSrvc = NULL;
3474 AFSPoolEntry *pPoolEntry = NULL;
3475 AFSRequestExtentsCB *pRequestExtents = NULL;
3481 pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
3483 AFSAcquireShared( &pCommSrvc->IrpPoolLock,
3486 pPoolEntry = pCommSrvc->RequestPoolHead;
3488 while( pPoolEntry != NULL)
3491 if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
3494 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
3497 pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
3499 if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
3500 pRequestExtents->Length == Length)
3503 bRequestQueued = TRUE;
3508 pPoolEntry = pPoolEntry->fLink;
3511 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
3514 return bRequestQueued;
3518 AFSCreateSymlink( IN GUID *AuthGroup,
3519 IN AFSObjectInfoCB *ParentObjectInfo,
3520 IN UNICODE_STRING *FileName,
3521 IN AFSObjectInfoCB *ObjectInfo,
3522 IN UNICODE_STRING *TargetName)
3525 NTSTATUS ntStatus = STATUS_SUCCESS;
3526 AFSCreateSymlinkCB *pSymlinkCreate = NULL;
3527 ULONG ulResultLen = 0;
3528 AFSCreateSymlinkResultCB *pSymlinkResult = NULL;
3534 // Allocate our request and result structures
3537 pSymlinkCreate = (AFSCreateSymlinkCB *)ExAllocatePoolWithTag( PagedPool,
3538 sizeof( AFSCreateSymlinkCB) +
3540 AFS_SYMLINK_REQUEST_TAG);
3542 if( pSymlinkCreate == NULL)
3545 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3548 RtlZeroMemory( pSymlinkCreate,
3549 sizeof( AFSCreateSymlinkCB) +
3550 TargetName->Length);
3552 pSymlinkResult = (AFSCreateSymlinkResultCB *)ExAllocatePoolWithTag( PagedPool,
3554 AFS_SYMLINK_REQUEST_TAG);
3556 if( pSymlinkResult == NULL)
3559 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3562 RtlZeroMemory( pSymlinkResult,
3566 // Populate the request buffer
3569 RtlCopyMemory( &pSymlinkCreate->ParentId,
3570 &ObjectInfo->ParentFileId,
3571 sizeof( AFSFileID));
3573 pSymlinkCreate->TargetNameLength = TargetName->Length;
3575 RtlCopyMemory( pSymlinkCreate->TargetName,
3577 TargetName->Length);
3579 ulResultLen = PAGE_SIZE;
3582 // Call the service to create the symlink entry
3585 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_SYMLINK,
3586 AFS_REQUEST_FLAG_SYNCHRONOUS,
3589 &ObjectInfo->FileId,
3590 ObjectInfo->VolumeCB->VolumeInformation.Cell,
3591 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
3593 sizeof( AFSCreateSymlinkCB) +
3598 if ( ntStatus == STATUS_FILE_DELETED )
3601 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3602 AFS_TRACE_LEVEL_ERROR,
3603 "AFSCreateSymlink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3604 ObjectInfo->FileId.Cell,
3605 ObjectInfo->FileId.Volume,
3606 ObjectInfo->FileId.Vnode,
3607 ObjectInfo->FileId.Unique,
3610 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3612 ClearFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
3614 SetFlag( ObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
3616 try_return( ntStatus = STATUS_ACCESS_DENIED);
3618 else if( ntStatus != STATUS_SUCCESS)
3621 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3622 AFS_TRACE_LEVEL_ERROR,
3623 "AFSCreateSymlink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3624 ObjectInfo->FileId.Cell,
3625 ObjectInfo->FileId.Volume,
3626 ObjectInfo->FileId.Vnode,
3627 ObjectInfo->FileId.Unique,
3630 try_return( ntStatus);
3634 // After successful creation the open object has been deleted and replaced by
3635 // the actual symlink.
3638 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3640 ClearFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
3642 SetFlag( ObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
3646 if( pSymlinkCreate != NULL)
3649 AFSExFreePoolWithTag( pSymlinkCreate, AFS_SYMLINK_REQUEST_TAG);
3652 if( pSymlinkResult != NULL)
3655 AFSExFreePoolWithTag( pSymlinkResult, AFS_SYMLINK_REQUEST_TAG);