2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 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
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSCommSupport.cpp
39 #include "AFSCommon.h"
42 AFSEnumerateDirectory( IN GUID *AuthGroup,
43 IN AFSObjectInfoCB *ObjectInfoCB,
47 NTSTATUS ntStatus = STATUS_SUCCESS;
49 ULONG ulResultLen = 0;
50 AFSDirQueryCB *pDirQueryCB;
51 AFSDirEnumEntry *pCurrentDirEntry = NULL;
52 AFSDirectoryCB *pDirNode = NULL;
53 ULONG ulEntryLength = 0;
54 AFSDirEnumResp *pDirEnumResponse = NULL;
55 UNICODE_STRING uniDirName, uniTargetName;
56 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
58 UNICODE_STRING uniGUID;
59 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
64 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
66 if( BooleanFlagOn( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
69 try_return( ntStatus = STATUS_SUCCESS);
73 uniGUID.MaximumLength = 0;
74 uniGUID.Buffer = NULL;
76 if( AuthGroup != NULL)
78 RtlStringFromGUID( *AuthGroup,
82 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
83 AFS_TRACE_LEVEL_VERBOSE,
84 "AFSEnumerateDirectory Enumerating FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
85 ObjectInfoCB->FileId.Cell,
86 ObjectInfoCB->FileId.Volume,
87 ObjectInfoCB->FileId.Vnode,
88 ObjectInfoCB->FileId.Unique,
91 if( AuthGroup != NULL)
93 RtlFreeUnicodeString( &uniGUID);
97 // Initialize the directory enumeration buffer for the directory
100 pBuffer = AFSExAllocatePoolWithTag( PagedPool,
101 AFS_DIR_ENUM_BUFFER_LEN,
107 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
110 RtlZeroMemory( pBuffer,
111 AFS_DIR_ENUM_BUFFER_LEN);
113 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
116 // Use the payload buffer for information we will pass to the service
119 pDirQueryCB = (AFSDirQueryCB *)pBuffer;
121 pDirQueryCB->EnumHandle = 0;
126 ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
130 // Loop on the information
137 // If the enumeration handle is -1 then we are done
140 if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
143 ntStatus = STATUS_NO_MORE_ENTRIES;
149 // Go and retrieve the directory contents
152 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
156 &ObjectInfoCB->FileId,
157 ObjectInfoCB->VolumeCB->VolumeInformation.Cell,
158 ObjectInfoCB->VolumeCB->VolumeInformation.CellLength,
160 sizeof( AFSDirQueryCB),
165 if( ntStatus != STATUS_SUCCESS ||
169 if( ntStatus == STATUS_NO_MORE_FILES ||
170 ntStatus == STATUS_NO_MORE_ENTRIES)
173 ntStatus = STATUS_SUCCESS;
175 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
177 AFSAcquireExcl( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock,
180 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
181 AFS_TRACE_LEVEL_VERBOSE,
182 "AFSEnumerateDirectory Directory Complete FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX Status %08lX\n",
183 ObjectInfoCB->FileId.Cell,
184 ObjectInfoCB->FileId.Volume,
185 ObjectInfoCB->FileId.Vnode,
186 ObjectInfoCB->FileId.Unique,
187 pDirEnumResponse->SnapshotDataVersion.HighPart,
188 pDirEnumResponse->SnapshotDataVersion.LowPart,
189 pDirEnumResponse->CurrentDataVersion.HighPart,
190 pDirEnumResponse->CurrentDataVersion.LowPart,
193 ObjectInfoCB->DataVersion = pDirEnumResponse->SnapshotDataVersion;
195 if ( pDirEnumResponse->SnapshotDataVersion.QuadPart != pDirEnumResponse->CurrentDataVersion.QuadPart )
198 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
200 ObjectInfoCB->DataVersion.QuadPart = (ULONGLONG)-1;
202 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
203 AFS_TRACE_LEVEL_VERBOSE,
204 "AFSEnumerateDirectory Force Verify due to DV change during enumeration FID %08lX-%08lX-%08lX-%08lX\n",
205 ObjectInfoCB->FileId.Cell,
206 ObjectInfoCB->FileId.Volume,
207 ObjectInfoCB->FileId.Vnode,
208 ObjectInfoCB->FileId.Unique);
211 AFSReleaseResource( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock);
216 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
217 AFS_TRACE_LEVEL_VERBOSE,
218 "AFSEnumerateDirectory Failed to enumerate directory FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ Status %08lX\n",
219 ObjectInfoCB->FileId.Cell,
220 ObjectInfoCB->FileId.Volume,
221 ObjectInfoCB->FileId.Vnode,
222 ObjectInfoCB->FileId.Unique,
230 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
232 pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
234 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
235 AFS_TRACE_LEVEL_VERBOSE,
236 "AFSEnumerateDirectory Enumerating FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX\n",
237 ObjectInfoCB->FileId.Cell,
238 ObjectInfoCB->FileId.Volume,
239 ObjectInfoCB->FileId.Vnode,
240 ObjectInfoCB->FileId.Unique,
241 pDirEnumResponse->SnapshotDataVersion.HighPart,
242 pDirEnumResponse->SnapshotDataVersion.LowPart,
243 pDirEnumResponse->CurrentDataVersion.HighPart,
244 pDirEnumResponse->CurrentDataVersion.LowPart);
247 // Remove the leading header from the processed length
250 ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
252 while( ulResultLen > 0)
255 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
257 uniDirName.MaximumLength = uniDirName.Length;
259 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
261 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
263 uniTargetName.MaximumLength = uniTargetName.Length;
265 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
268 // Be sure we don't have this entry in the case sensitive tree
271 ulCRC = AFSGenerateCRC( &uniDirName,
274 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
278 if( pDirNode != NULL)
282 // Check that the FIDs are the same
285 if( AFSIsEqualFID( &pCurrentDirEntry->FileId,
286 &pDirNode->ObjectInformation->FileId))
290 // Duplicate entry, skip it
293 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
295 uniTargetName.Length);
297 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
299 if( ulResultLen >= ulEntryLength)
301 ulResultLen -= ulEntryLength;
309 // Update the metadata for the entry
312 if( pDirNode->ObjectInformation->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
316 AFSObjectInfoCB *pObjectInfo = pDirNode->ObjectInformation;
319 // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
322 lCount = AFSObjectInfoIncrement( pObjectInfo,
323 AFS_OBJECT_REFERENCE_INVALIDATION);
325 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
326 AFS_TRACE_LEVEL_VERBOSE,
327 "AFSEnumerateDirectory calling AFSPerformObjectInvalidate Increment count on object %p Cnt %d\n",
331 AFSPerformObjectInvalidate( pObjectInfo,
332 AFS_INVALIDATE_DATA_VERSION);
337 AFSUpdateMetaData( pDirNode,
347 // Need to tear down this entry and rebuild it below
350 if( pDirNode->DirOpenReferenceCount <= 0)
353 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
354 AFS_TRACE_LEVEL_VERBOSE,
355 "AFSEnumerateDirectory Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
357 &pDirNode->NameInformation.FileName,
358 pDirNode->ObjectInformation->FileId.Cell,
359 pDirNode->ObjectInformation->FileId.Volume,
360 pDirNode->ObjectInformation->FileId.Vnode,
361 pDirNode->ObjectInformation->FileId.Unique,
362 pCurrentDirEntry->FileId.Cell,
363 pCurrentDirEntry->FileId.Volume,
364 pCurrentDirEntry->FileId.Vnode,
365 pCurrentDirEntry->FileId.Unique);
367 AFSDeleteDirEntry( ObjectInfoCB,
373 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
375 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
376 AFS_TRACE_LEVEL_VERBOSE,
377 "AFSEnumerateDirectory Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
379 &pDirNode->NameInformation.FileName,
380 pDirNode->ObjectInformation->FileId.Cell,
381 pDirNode->ObjectInformation->FileId.Volume,
382 pDirNode->ObjectInformation->FileId.Vnode,
383 pDirNode->ObjectInformation->FileId.Unique,
384 pCurrentDirEntry->FileId.Cell,
385 pCurrentDirEntry->FileId.Volume,
386 pCurrentDirEntry->FileId.Vnode,
387 pCurrentDirEntry->FileId.Unique);
389 AFSRemoveNameEntry( ObjectInfoCB,
397 pDirNode = AFSInitDirEntry( ObjectInfoCB,
401 (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
403 if( pDirNode == NULL)
406 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
411 AFSUpdateMetaData( pDirNode,
414 if( pDirNode->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
417 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
418 AFS_TRACE_LEVEL_VERBOSE,
419 "AFSEnumerateDirectory Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
421 pDirNode->ObjectInformation->FileId.Cell,
422 pDirNode->ObjectInformation->FileId.Volume,
423 pDirNode->ObjectInformation->FileId.Vnode,
424 pDirNode->ObjectInformation->FileId.Unique);
426 AFSAcquireExcl( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
429 SetFlag( pDirNode->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
431 pDirNode->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
433 AFSReleaseResource( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
437 // Set up the entry length
440 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
441 pCurrentDirEntry->FileNameLength +
442 pCurrentDirEntry->TargetNameLength);
445 // Init the short name if we have one
448 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
449 pCurrentDirEntry->ShortNameLength > 0)
452 UNICODE_STRING uniShortName;
454 pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
456 RtlCopyMemory( pDirNode->NameInformation.ShortName,
457 pCurrentDirEntry->ShortName,
458 pDirNode->NameInformation.ShortNameLength);
461 // Generate the short name index
464 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
465 uniShortName.MaximumLength = uniShortName.Length;
466 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
468 if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
473 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
476 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
477 AFS_TRACE_LEVEL_VERBOSE,
478 "AFSEnumerateDirectory Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
481 &pDirNode->NameInformation.FileName,
482 pCurrentDirEntry->FileId.Cell,
483 pCurrentDirEntry->FileId.Volume,
484 pCurrentDirEntry->FileId.Vnode,
485 pCurrentDirEntry->FileId.Unique);
489 pDirNode->NameInformation.ShortNameLength = 0;
491 RtlZeroMemory( pDirNode->NameInformation.ShortName,
492 (12 * sizeof( WCHAR)));
499 // No short name or short names are disabled
502 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
506 // Insert the node into the name tree
509 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
512 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
514 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
515 AFS_TRACE_LEVEL_VERBOSE,
516 "AFSEnumerateDirectory Insert DE %p to head of case sensitive tree for %wZ\n",
518 &pDirNode->NameInformation.FileName);
523 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
524 AFS_TRACE_LEVEL_VERBOSE,
525 "AFSEnumerateDirectory Insert DE %p to case sensitive tree for %wZ\n",
527 &pDirNode->NameInformation.FileName);
529 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
534 // Delete this dir entry and continue on
537 AFSDeleteDirEntry( ObjectInfoCB,
540 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
542 if( ulResultLen >= ulEntryLength)
544 ulResultLen -= ulEntryLength;
555 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
557 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
560 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
561 AFS_TRACE_LEVEL_VERBOSE,
562 "AFSEnumerateDirectory Insert DE %p to head of case insensitive tree for %wZ\n",
564 &pDirNode->NameInformation.FileName);
566 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
568 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
573 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
574 AFS_TRACE_LEVEL_VERBOSE,
575 "AFSEnumerateDirectory Insert DE %p to case insensitive tree for %wZ\n",
577 &pDirNode->NameInformation.FileName);
579 AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
583 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
586 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
591 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
593 pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
596 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
598 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
600 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
602 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
603 AFS_TRACE_LEVEL_VERBOSE,
604 "AFSEnumerateDirectory Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
605 &pDirNode->NameInformation.FileName,
606 ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
607 ObjectInfoCB->FileId.Cell,
608 ObjectInfoCB->FileId.Volume,
609 ObjectInfoCB->FileId.Vnode,
610 ObjectInfoCB->FileId.Unique);
612 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
616 // Insert the short name entry if we have a valid short name
619 if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
622 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
623 AFS_TRACE_LEVEL_VERBOSE,
624 "AFSEnumerateDirectory Insert DE %p to head of shortname tree for %wZ\n",
626 &pDirNode->NameInformation.FileName);
628 ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
630 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
635 if( NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
638 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
640 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
641 AFS_TRACE_LEVEL_VERBOSE,
642 "AFSEnumerateDirectory Insert DE %p to shortname tree for %wZ\n",
644 &pDirNode->NameInformation.FileName);
653 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
655 if( ulResultLen >= ulEntryLength)
657 ulResultLen -= ulEntryLength;
665 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
668 // Reset the information in the request buffer since it got trampled
672 pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
674 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
675 AFS_TRACE_LEVEL_VERBOSE,
676 "AFSEnumerateDirectory EnumHandle %08lX\n",
677 pDirQueryCB->EnumHandle);
689 AFSExFreePoolWithTag( pBuffer, AFS_DIR_BUFFER_TAG);
692 if ( NT_SUCCESS( ntStatus))
695 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
701 // If the processing failed then we should reset the directory
702 // content in the event it is re-enumerated
705 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
706 AFS_TRACE_LEVEL_ERROR,
707 "AFSEnumerateDirectory Resetting content for FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
708 ObjectInfoCB->FileId.Cell,
709 ObjectInfoCB->FileId.Volume,
710 ObjectInfoCB->FileId.Vnode,
711 ObjectInfoCB->FileId.Unique,
714 AFSResetDirectoryContent( ObjectInfoCB);
722 AFSEnumerateDirectoryNoResponse( IN GUID *AuthGroup,
723 IN AFSFileID *FileId)
726 NTSTATUS ntStatus = STATUS_SUCCESS;
727 AFSDirQueryCB stDirQueryCB;
728 ULONG ulRequestFlags = 0;
734 // Use the payload buffer for information we will pass to the service
737 stDirQueryCB.EnumHandle = 0;
739 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
746 (void *)&stDirQueryCB,
747 sizeof( AFSDirQueryCB),
751 if( ntStatus != STATUS_SUCCESS)
754 if( ntStatus == STATUS_NO_MORE_FILES ||
755 ntStatus == STATUS_NO_MORE_ENTRIES)
758 ntStatus = STATUS_SUCCESS;
763 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
764 AFS_TRACE_LEVEL_ERROR,
765 "AFSEnumerateDirectoryNoResponse Failed to enumerate directory Status %08lX\n",
775 AFSVerifyDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB,
779 NTSTATUS ntStatus = STATUS_SUCCESS;
780 void *pBuffer = NULL;
781 ULONG ulResultLen = 0;
782 AFSDirQueryCB *pDirQueryCB;
783 AFSDirEnumEntry *pCurrentDirEntry = NULL;
784 AFSDirectoryCB *pDirNode = NULL;
785 ULONG ulEntryLength = 0;
786 AFSDirEnumResp *pDirEnumResponse = NULL;
787 UNICODE_STRING uniDirName, uniTargetName;
788 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_FAST_REQUEST;
790 AFSObjectInfoCB *pObjectInfo = NULL;
791 ULONGLONG ullIndex = 0;
792 UNICODE_STRING uniGUID;
794 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
799 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
802 uniGUID.MaximumLength = 0;
803 uniGUID.Buffer = NULL;
805 if( AuthGroup != NULL)
807 RtlStringFromGUID( *AuthGroup,
811 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
812 AFS_TRACE_LEVEL_VERBOSE,
813 "AFSVerifyDirectoryContent Verifying content for FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
814 ObjectInfoCB->FileId.Cell,
815 ObjectInfoCB->FileId.Volume,
816 ObjectInfoCB->FileId.Vnode,
817 ObjectInfoCB->FileId.Unique,
820 if( AuthGroup != NULL)
822 RtlFreeUnicodeString( &uniGUID);
826 // Initialize the directory enumeration buffer for the directory
829 pBuffer = AFSExAllocatePoolWithTag( PagedPool,
830 AFS_DIR_ENUM_BUFFER_LEN,
836 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
839 RtlZeroMemory( pBuffer,
840 AFS_DIR_ENUM_BUFFER_LEN);
842 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
845 // Use the payload buffer for information we will pass to the service
848 pDirQueryCB = (AFSDirQueryCB *)pBuffer;
850 pDirQueryCB->EnumHandle = 0;
853 // Loop on the information
860 // If the enumeration handle is -1 then we are done
863 if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
866 ntStatus = STATUS_NO_MORE_ENTRIES;
872 // Go and retrieve the directory contents
875 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
879 &ObjectInfoCB->FileId,
880 ObjectInfoCB->VolumeCB->VolumeInformation.Cell,
881 ObjectInfoCB->VolumeCB->VolumeInformation.CellLength,
883 sizeof( AFSDirQueryCB),
888 if( ntStatus != STATUS_SUCCESS ||
892 if( ntStatus == STATUS_NO_MORE_FILES ||
893 ntStatus == STATUS_NO_MORE_ENTRIES)
896 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
898 AFSAcquireExcl( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock,
901 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
902 AFS_TRACE_LEVEL_VERBOSE,
903 "AFSVerifyDirectoryContent Directory Complete FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX Status %08lX\n",
904 ObjectInfoCB->FileId.Cell,
905 ObjectInfoCB->FileId.Volume,
906 ObjectInfoCB->FileId.Vnode,
907 ObjectInfoCB->FileId.Unique,
908 pDirEnumResponse->SnapshotDataVersion.HighPart,
909 pDirEnumResponse->SnapshotDataVersion.LowPart,
910 pDirEnumResponse->CurrentDataVersion.HighPart,
911 pDirEnumResponse->CurrentDataVersion.LowPart,
914 ntStatus = STATUS_SUCCESS;
916 if ( pDirEnumResponse->SnapshotDataVersion.QuadPart != pDirEnumResponse->CurrentDataVersion.QuadPart )
919 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
921 ObjectInfoCB->DataVersion.QuadPart = (ULONGLONG)-1;
923 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
924 AFS_TRACE_LEVEL_VERBOSE,
925 "AFSVerifyDirectoryContent Force Verify due to DV change during enumeration FID %08lX-%08lX-%08lX-%08lX\n",
926 ObjectInfoCB->FileId.Cell,
927 ObjectInfoCB->FileId.Volume,
928 ObjectInfoCB->FileId.Vnode,
929 ObjectInfoCB->FileId.Unique);
934 ObjectInfoCB->DataVersion = pDirEnumResponse->SnapshotDataVersion;
937 AFSReleaseResource( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock);
942 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
943 AFS_TRACE_LEVEL_ERROR,
944 "AFSVerifyDirectoryContent Failed to enumerate directory FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ Status %08lX\n",
945 ObjectInfoCB->FileId.Cell,
946 ObjectInfoCB->FileId.Volume,
947 ObjectInfoCB->FileId.Vnode,
948 ObjectInfoCB->FileId.Unique,
956 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
958 pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
960 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
961 AFS_TRACE_LEVEL_VERBOSE,
962 "AFSVerifyDirectoryContent EnumResponse FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX\n",
963 ObjectInfoCB->FileId.Cell,
964 ObjectInfoCB->FileId.Volume,
965 ObjectInfoCB->FileId.Vnode,
966 ObjectInfoCB->FileId.Unique,
967 pDirEnumResponse->SnapshotDataVersion.HighPart,
968 pDirEnumResponse->SnapshotDataVersion.LowPart,
969 pDirEnumResponse->CurrentDataVersion.HighPart,
970 pDirEnumResponse->CurrentDataVersion.LowPart);
973 // Remove the leading header from the processed length
976 ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
978 while( ulResultLen > 0)
981 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
983 uniDirName.MaximumLength = uniDirName.Length;
985 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
987 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
989 uniTargetName.MaximumLength = uniTargetName.Length;
991 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
994 // Does this entry already exist in the directory?
997 ulCRC = AFSGenerateCRC( &uniDirName,
1000 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1006 // Set up the entry length
1009 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
1010 pCurrentDirEntry->FileNameLength +
1011 pCurrentDirEntry->TargetNameLength);
1014 AFSIsEqualFID( &pCurrentDirEntry->FileId,
1015 &pDirNode->ObjectInformation->FileId))
1019 // Found matching directory entry by name and FileID
1022 AFSAcquireShared( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock,
1025 ullIndex = AFSCreateLowIndex( &pCurrentDirEntry->FileId);
1027 ntStatus = AFSLocateHashEntry( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeHead,
1029 (AFSBTreeEntry **)&pObjectInfo);
1031 AFSReleaseResource( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock);
1033 if( NT_SUCCESS( ntStatus) &&
1034 pObjectInfo != NULL)
1038 // Indicate this is a valid entry
1041 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
1043 if( pCurrentDirEntry->ShortNameLength > 0 &&
1044 pDirNode->NameInformation.ShortNameLength > 0)
1046 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1047 AFS_TRACE_LEVEL_VERBOSE,
1048 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name %S New short name %S\n",
1050 &pDirNode->NameInformation.FileName,
1051 ObjectInfoCB->FileId.Cell,
1052 ObjectInfoCB->FileId.Volume,
1053 ObjectInfoCB->FileId.Vnode,
1054 ObjectInfoCB->FileId.Unique,
1055 pDirNode->NameInformation.ShortName,
1056 pCurrentDirEntry->ShortName);
1058 else if( pCurrentDirEntry->ShortNameLength == 0 &&
1059 pDirNode->NameInformation.ShortNameLength > 0)
1062 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1063 AFS_TRACE_LEVEL_VERBOSE,
1064 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name %S New short name NULL\n",
1066 &pDirNode->NameInformation.FileName,
1067 ObjectInfoCB->FileId.Cell,
1068 ObjectInfoCB->FileId.Volume,
1069 ObjectInfoCB->FileId.Vnode,
1070 ObjectInfoCB->FileId.Unique,
1071 pDirNode->NameInformation.ShortName);
1073 else if( pCurrentDirEntry->ShortNameLength > 0 &&
1074 pDirNode->NameInformation.ShortNameLength == 0)
1076 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1077 AFS_TRACE_LEVEL_VERBOSE,
1078 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name %S\n",
1080 &pDirNode->NameInformation.FileName,
1081 ObjectInfoCB->FileId.Cell,
1082 ObjectInfoCB->FileId.Volume,
1083 ObjectInfoCB->FileId.Vnode,
1084 ObjectInfoCB->FileId.Unique,
1085 pCurrentDirEntry->ShortName);
1089 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1090 AFS_TRACE_LEVEL_VERBOSE,
1091 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name NULL\n",
1093 &pDirNode->NameInformation.FileName,
1094 ObjectInfoCB->FileId.Cell,
1095 ObjectInfoCB->FileId.Volume,
1096 ObjectInfoCB->FileId.Vnode,
1097 ObjectInfoCB->FileId.Unique);
1101 // Update the metadata for the entry
1104 if( pObjectInfo->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
1108 // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
1109 // if successfully queued. Cannot call AFSPerformObjectInvalidate directly
1110 // because ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock is
1111 // held during the sequence AFSVerifyEntry->AFSValidateDirectoryCache->
1112 // AFSVerifyDirectoryContent and AFSPerformObjectInvalidate requires the
1113 // Fcb->NPFcb->Resource which must be held prior to the TreeLock in the
1117 lCount = AFSObjectInfoIncrement( pObjectInfo,
1118 AFS_OBJECT_REFERENCE_INVALIDATION);
1120 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1121 AFS_TRACE_LEVEL_VERBOSE,
1122 "AFSVerifyDirectoryContent calling AFSQueueInvalidateObject Increment count on object %p Cnt %d\n",
1126 if ( !NT_SUCCESS( AFSQueueInvalidateObject( pObjectInfo,
1127 AFS_INVALIDATE_DATA_VERSION)))
1130 lCount = AFSObjectInfoDecrement( pObjectInfo,
1131 AFS_OBJECT_REFERENCE_INVALIDATION);
1133 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1134 AFS_TRACE_LEVEL_VERBOSE,
1135 "AFSVerifyDirectoryContent AFSQueueInvalidateObject failed Decrement count on object %p Cnt %d\n",
1143 AFSUpdateMetaData( pDirNode,
1151 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1153 if( ulResultLen >= ulEntryLength)
1155 ulResultLen -= ulEntryLength;
1169 // File name matches but FileID does not.
1172 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1173 AFS_TRACE_LEVEL_VERBOSE,
1174 "AFSVerifyDirectoryContent Processing dir entry %p %wZ with different FID, same name in parent FID %08lX-%08lX-%08lX-%08lX\n",
1176 &pDirNode->NameInformation.FileName,
1177 ObjectInfoCB->FileId.Cell,
1178 ObjectInfoCB->FileId.Volume,
1179 ObjectInfoCB->FileId.Vnode,
1180 ObjectInfoCB->FileId.Unique);
1183 // Need to tear down this entry and rebuild it below
1186 if( pDirNode->DirOpenReferenceCount <= 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)
1719 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1720 AFS_TRACE_LEVEL_VERBOSE,
1721 "AFSNotifyFileCreate Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1723 &pDirNode->NameInformation.FileName,
1724 pDirNode->ObjectInformation->FileId.Cell,
1725 pDirNode->ObjectInformation->FileId.Volume,
1726 pDirNode->ObjectInformation->FileId.Vnode,
1727 pDirNode->ObjectInformation->FileId.Unique,
1728 pResultCB->DirEnum.FileId.Cell,
1729 pResultCB->DirEnum.FileId.Volume,
1730 pResultCB->DirEnum.FileId.Vnode,
1731 pResultCB->DirEnum.FileId.Unique);
1733 AFSDeleteDirEntry( ParentObjectInfo,
1739 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1741 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1742 AFS_TRACE_LEVEL_VERBOSE,
1743 "AFSNotifyFileCreate Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1745 &pDirNode->NameInformation.FileName,
1746 pDirNode->ObjectInformation->FileId.Cell,
1747 pDirNode->ObjectInformation->FileId.Volume,
1748 pDirNode->ObjectInformation->FileId.Vnode,
1749 pDirNode->ObjectInformation->FileId.Unique,
1750 pResultCB->DirEnum.FileId.Cell,
1751 pResultCB->DirEnum.FileId.Volume,
1752 pResultCB->DirEnum.FileId.Vnode,
1753 pResultCB->DirEnum.FileId.Unique);
1755 AFSRemoveNameEntry( ParentObjectInfo,
1764 // We are unsure of our current data so set the verify flag. It may already be set
1765 // but no big deal to reset it
1768 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1770 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1773 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1774 AFS_TRACE_LEVEL_VERBOSE,
1775 "AFSNotifyFileCreate Creating new entry %wZ\n",
1779 // Initialize the directory entry
1782 uniTargetName.Length = (USHORT)pResultCB->DirEnum.TargetNameLength;
1784 uniTargetName.MaximumLength = uniTargetName.Length;
1786 uniTargetName.Buffer = (WCHAR *)((char *)&pResultCB->DirEnum + pResultCB->DirEnum.TargetNameOffset);
1788 pDirNode = AFSInitDirEntry( ParentObjectInfo,
1791 &pResultCB->DirEnum,
1792 (ULONG)InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1794 if( pDirNode == NULL)
1797 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1799 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1801 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1805 // Init the short name if we have one
1808 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1809 pResultCB->DirEnum.ShortNameLength > 0)
1812 UNICODE_STRING uniShortName;
1814 pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
1816 RtlCopyMemory( pDirNode->NameInformation.ShortName,
1817 pResultCB->DirEnum.ShortName,
1818 pDirNode->NameInformation.ShortNameLength);
1821 // Generate the short name index
1824 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1825 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1827 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1830 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1831 AFS_TRACE_LEVEL_VERBOSE,
1832 "AFSNotifyFileCreate Initialized short name %wZ for DE %p for %wZ\n",
1835 &pDirNode->NameInformation.FileName);
1840 // No short name or short names are disabled
1843 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
1846 if ( !BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1850 // Update the parent data version
1853 ParentObjectInfo->DataVersion = pResultCB->ParentDataVersion;
1855 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1856 AFS_TRACE_LEVEL_VERBOSE,
1857 "AFSNotifyFileCreate entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
1859 ParentObjectInfo->FileId.Cell,
1860 ParentObjectInfo->FileId.Volume,
1861 ParentObjectInfo->FileId.Vnode,
1862 ParentObjectInfo->FileId.Unique,
1863 ParentObjectInfo->DataVersion.QuadPart);
1867 // Return the directory node
1870 *DirNode = pDirNode;
1874 if ( *DirNode != NULL)
1877 lCount = InterlockedIncrement( &(*DirNode)->DirOpenReferenceCount);
1879 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1880 AFS_TRACE_LEVEL_VERBOSE,
1881 "AFSNotifyFileCreate Increment count on %wZ DE %p Cnt %d\n",
1882 &(*DirNode)->NameInformation.FileName,
1886 ASSERT( lCount >= 0);
1889 if ( bReleaseParentTreeLock)
1892 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1895 if( pResultCB != NULL)
1898 AFSExFreePoolWithTag( pResultCB, AFS_GENERIC_MEMORY_1_TAG);
1906 AFSUpdateFileInformation( IN AFSFileID *ParentFid,
1907 IN AFSObjectInfoCB *ObjectInfo,
1911 NTSTATUS ntStatus = STATUS_SUCCESS;
1912 AFSFileUpdateCB stUpdateCB;
1913 ULONG ulResultLen = 0;
1914 AFSFileUpdateResultCB *pUpdateResultCB = NULL;
1920 // Init the control block for the request
1923 RtlZeroMemory( &stUpdateCB,
1924 sizeof( AFSFileUpdateCB));
1926 stUpdateCB.AllocationSize = ObjectInfo->EndOfFile;
1928 stUpdateCB.FileAttributes = ObjectInfo->FileAttributes;
1930 stUpdateCB.EaSize = ObjectInfo->EaSize;
1932 stUpdateCB.ParentId = *ParentFid;
1934 stUpdateCB.LastAccessTime = ObjectInfo->LastAccessTime;
1936 stUpdateCB.CreateTime = ObjectInfo->CreationTime;
1938 stUpdateCB.ChangeTime = ObjectInfo->ChangeTime;
1940 stUpdateCB.LastWriteTime = ObjectInfo->LastWriteTime;
1942 pUpdateResultCB = (AFSFileUpdateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1944 AFS_UPDATE_RESULT_TAG);
1946 if( pUpdateResultCB == NULL)
1949 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1952 ulResultLen = PAGE_SIZE;
1954 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_UPDATE_FILE,
1955 AFS_REQUEST_FLAG_SYNCHRONOUS,
1958 &ObjectInfo->FileId,
1959 ObjectInfo->VolumeCB->VolumeInformation.Cell,
1960 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
1962 sizeof( AFSFileUpdateCB),
1966 if( ntStatus != STATUS_SUCCESS)
1969 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1970 AFS_TRACE_LEVEL_ERROR,
1971 "AFSUpdateFileInformation failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1972 ObjectInfo->FileId.Cell,
1973 ObjectInfo->FileId.Volume,
1974 ObjectInfo->FileId.Vnode,
1975 ObjectInfo->FileId.Unique,
1978 try_return( ntStatus);
1982 // Update the data version
1985 AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1988 if ( !BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1991 ObjectInfo->DataVersion = pUpdateResultCB->DirEnum.DataVersion;
1994 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1998 if( pUpdateResultCB != NULL)
2001 AFSExFreePoolWithTag( pUpdateResultCB, AFS_UPDATE_RESULT_TAG);
2009 AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
2011 IN BOOLEAN CheckOnly)
2013 NTSTATUS ntStatus = STATUS_SUCCESS;
2014 ULONG ulResultLen = 0;
2015 AFSFileDeleteCB stDelete;
2016 AFSFileDeleteResultCB stDeleteResult;
2017 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
2018 AFSObjectInfoCB *pObjectInfo = NULL;
2019 AFSObjectInfoCB *pParentObjectInfo = NULL;
2024 pObjectInfo = DirectoryCB->ObjectInformation;
2026 pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
2027 &pObjectInfo->ParentFileId);
2029 stDelete.ParentId = pObjectInfo->ParentFileId;
2031 stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
2033 ulResultLen = sizeof( AFSFileDeleteResultCB);
2037 ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
2040 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
2043 &DirectoryCB->NameInformation.FileName,
2044 &pObjectInfo->FileId,
2045 pObjectInfo->VolumeCB->VolumeInformation.Cell,
2046 pObjectInfo->VolumeCB->VolumeInformation.CellLength,
2048 sizeof( AFSFileDeleteCB),
2052 if( ntStatus != STATUS_SUCCESS)
2055 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2056 AFS_TRACE_LEVEL_ERROR,
2057 "AFSNotifyDelete failed ParentFID %08lX-%08lX-%08lX-%08lX %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2058 stDelete.ParentId.Cell,
2059 stDelete.ParentId.Volume,
2060 stDelete.ParentId.Vnode,
2061 stDelete.ParentId.Unique,
2062 &DirectoryCB->NameInformation.FileName,
2063 pObjectInfo->FileId.Cell,
2064 pObjectInfo->FileId.Volume,
2065 pObjectInfo->FileId.Vnode,
2066 pObjectInfo->FileId.Unique,
2069 try_return( ntStatus);
2072 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2079 // Validate the parent data version
2082 if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
2085 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2087 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2094 // Update the parent data version
2097 if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart - 1)
2100 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2102 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2108 // TODO -- The entry must be removed from the directory at which point the
2109 // Directory data version number can be updated. Until then we must force
2112 // pParentObjectInfor->DataVersion.QuadPart = stDeleteResult.ParentDataVersion.QuadPart;
2115 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2117 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2121 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2125 if ( pParentObjectInfo)
2128 AFSReleaseObjectInfo( &pParentObjectInfo);
2137 AFSNotifyHardLink( IN AFSObjectInfoCB *ObjectInfo,
2139 IN AFSObjectInfoCB *ParentObjectInfo,
2140 IN AFSObjectInfoCB *TargetParentObjectInfo,
2141 IN AFSDirectoryCB *SourceDirectoryCB,
2142 IN UNICODE_STRING *TargetName,
2143 IN BOOLEAN bReplaceIfExists,
2144 OUT AFSDirectoryCB **TargetDirectoryCB)
2147 NTSTATUS ntStatus = STATUS_SUCCESS;
2148 AFSFileHardLinkCB *pHardLinkCB = NULL;
2149 AFSFileHardLinkResultCB *pResultCB = NULL;
2150 ULONG ulResultLen = 0;
2151 AFSDirectoryCB *pDirNode = NULL;
2153 BOOLEAN bReleaseParentLock = FALSE, bReleaseTargetParentLock = FALSE;
2154 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2161 // Init the control block for the request
2164 pHardLinkCB = (AFSFileHardLinkCB *)AFSExAllocatePoolWithTag( PagedPool,
2166 AFS_HARDLINK_REQUEST_TAG);
2168 if( pHardLinkCB == NULL)
2171 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2174 RtlZeroMemory( pHardLinkCB,
2177 pHardLinkCB->SourceParentId = ParentObjectInfo->FileId;
2179 pHardLinkCB->TargetParentId = TargetParentObjectInfo->FileId;
2181 pHardLinkCB->TargetNameLength = TargetName->Length;
2183 RtlCopyMemory( pHardLinkCB->TargetName,
2185 TargetName->Length);
2187 pHardLinkCB->bReplaceIfExists = bReplaceIfExists;
2190 // Use the same buffer for the result control block
2193 pResultCB = (AFSFileHardLinkResultCB *)pHardLinkCB;
2195 ulResultLen = PAGE_SIZE;
2197 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_HARDLINK_FILE,
2198 AFS_REQUEST_FLAG_SYNCHRONOUS,
2200 &SourceDirectoryCB->NameInformation.FileName,
2201 &ObjectInfo->FileId,
2202 ObjectInfo->VolumeCB->VolumeInformation.Cell,
2203 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2205 sizeof( AFSFileHardLinkCB) + TargetName->Length,
2209 if( ntStatus != STATUS_SUCCESS)
2212 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2213 AFS_TRACE_LEVEL_ERROR,
2214 "AFSNotifyHardLink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2215 ObjectInfo->FileId.Cell,
2216 ObjectInfo->FileId.Volume,
2217 ObjectInfo->FileId.Vnode,
2218 ObjectInfo->FileId.Unique,
2221 try_return( ntStatus);
2225 // Update the information from the returned data
2228 if ( ParentObjectInfo != TargetParentObjectInfo)
2231 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2234 bReleaseParentLock = TRUE;
2236 if ( ParentObjectInfo->DataVersion.QuadPart == pResultCB->SourceParentDataVersion.QuadPart - 1)
2239 ParentObjectInfo->DataVersion = pResultCB->SourceParentDataVersion;
2244 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2246 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2250 AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2253 bReleaseTargetParentLock = TRUE;
2255 if ( TargetParentObjectInfo->DataVersion.QuadPart == pResultCB->TargetParentDataVersion.QuadPart - 1)
2258 TargetParentObjectInfo->DataVersion = pResultCB->TargetParentDataVersion;
2263 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2264 AFS_TRACE_LEVEL_WARNING,
2265 "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",
2267 TargetParentObjectInfo->FileId.Cell,
2268 TargetParentObjectInfo->FileId.Volume,
2269 TargetParentObjectInfo->FileId.Vnode,
2270 TargetParentObjectInfo->FileId.Unique,
2271 TargetParentObjectInfo->DataVersion.HighPart,
2272 TargetParentObjectInfo->DataVersion.LowPart,
2273 pResultCB->TargetParentDataVersion.HighPart,
2274 pResultCB->TargetParentDataVersion.LowPart);
2277 // We raced so go and lookup the directory entry in the parent
2280 ulCRC = AFSGenerateCRC( TargetName,
2283 AFSLocateCaseSensitiveDirEntry( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2287 if( pDirNode != NULL)
2290 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2291 AFS_TRACE_LEVEL_VERBOSE,
2292 "AFSNotifyHardLink Located dir entry %p for file %wZ\n",
2296 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2297 &pResultCB->DirEnum.FileId))
2300 try_return( ntStatus = STATUS_REPARSE);
2306 // We found an entry that matches the desired name but it is not the
2307 // same as the one that was created for us by the file server.
2310 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2311 AFS_TRACE_LEVEL_ERROR,
2312 "AFSNotifyHardLink Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
2315 pDirNode->ObjectInformation->FileId.Cell,
2316 pDirNode->ObjectInformation->FileId.Volume,
2317 pDirNode->ObjectInformation->FileId.Vnode,
2318 pDirNode->ObjectInformation->FileId.Unique,
2319 pResultCB->DirEnum.FileId.Cell,
2320 pResultCB->DirEnum.FileId.Volume,
2321 pResultCB->DirEnum.FileId.Vnode,
2322 pResultCB->DirEnum.FileId.Unique);
2324 if( pDirNode->DirOpenReferenceCount <= 0)
2327 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2328 AFS_TRACE_LEVEL_VERBOSE,
2329 "AFSNotifyHardLink Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2331 &pDirNode->NameInformation.FileName,
2332 pDirNode->ObjectInformation->FileId.Cell,
2333 pDirNode->ObjectInformation->FileId.Volume,
2334 pDirNode->ObjectInformation->FileId.Vnode,
2335 pDirNode->ObjectInformation->FileId.Unique,
2336 pResultCB->DirEnum.FileId.Cell,
2337 pResultCB->DirEnum.FileId.Volume,
2338 pResultCB->DirEnum.FileId.Vnode,
2339 pResultCB->DirEnum.FileId.Unique);
2341 AFSDeleteDirEntry( TargetParentObjectInfo,
2347 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2349 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2350 AFS_TRACE_LEVEL_VERBOSE,
2351 "AFSNotifyHardLink Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2353 &pDirNode->NameInformation.FileName,
2354 pDirNode->ObjectInformation->FileId.Cell,
2355 pDirNode->ObjectInformation->FileId.Volume,
2356 pDirNode->ObjectInformation->FileId.Vnode,
2357 pDirNode->ObjectInformation->FileId.Unique,
2358 pResultCB->DirEnum.FileId.Cell,
2359 pResultCB->DirEnum.FileId.Volume,
2360 pResultCB->DirEnum.FileId.Vnode,
2361 pResultCB->DirEnum.FileId.Unique);
2363 AFSRemoveNameEntry( TargetParentObjectInfo,
2372 // We are unsure of our current data so set the verify flag. It may already be set
2373 // but no big deal to reset it
2376 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2378 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2382 // Create the hard link entry
2385 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2386 AFS_TRACE_LEVEL_VERBOSE,
2387 "AFSNotifyHardLink Creating new entry %wZ\n",
2391 // Initialize the directory entry
2394 pDirNode = AFSInitDirEntry( TargetParentObjectInfo,
2397 &pResultCB->DirEnum,
2398 (ULONG)InterlockedIncrement( &TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
2400 if( pDirNode == NULL)
2403 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2405 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2407 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2411 // Init the short name if we have one
2414 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2415 pResultCB->DirEnum.ShortNameLength > 0)
2418 UNICODE_STRING uniShortName;
2420 pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
2422 RtlCopyMemory( pDirNode->NameInformation.ShortName,
2423 pResultCB->DirEnum.ShortName,
2424 pDirNode->NameInformation.ShortNameLength);
2427 // Generate the short name index
2430 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
2431 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
2433 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
2436 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2437 AFS_TRACE_LEVEL_VERBOSE,
2438 "AFSNotifyHardLink Initialized short name %wZ for DE %p for %wZ\n",
2441 &pDirNode->NameInformation.FileName);
2446 // No short name or short names are disabled
2449 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2452 if ( !BooleanFlagOn( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2456 // Update the target parent data version
2459 TargetParentObjectInfo->DataVersion = pResultCB->TargetParentDataVersion;
2461 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2462 AFS_TRACE_LEVEL_VERBOSE,
2463 "AFSNotifyHardLink entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
2465 TargetParentObjectInfo->FileId.Cell,
2466 TargetParentObjectInfo->FileId.Volume,
2467 TargetParentObjectInfo->FileId.Vnode,
2468 TargetParentObjectInfo->FileId.Unique,
2469 TargetParentObjectInfo->DataVersion.QuadPart);
2474 if ( TargetDirectoryCB != NULL)
2477 lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
2479 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2480 AFS_TRACE_LEVEL_VERBOSE,
2481 "AFSNotifyHardLink Increment count on %wZ DE %p Cnt %d\n",
2482 &pDirNode->NameInformation.FileName,
2486 ASSERT( lCount >= 0);
2488 *TargetDirectoryCB = pDirNode;
2491 if ( bReleaseTargetParentLock)
2494 AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2497 if ( bReleaseParentLock)
2500 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2503 if( pHardLinkCB != NULL)
2506 AFSExFreePoolWithTag( pHardLinkCB, AFS_HARDLINK_REQUEST_TAG);
2516 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
2518 IN AFSObjectInfoCB *ParentObjectInfo,
2519 IN AFSObjectInfoCB *TargetParentObjectInfo,
2520 IN AFSDirectoryCB *DirectoryCB,
2521 IN UNICODE_STRING *TargetName,
2522 OUT AFSFileID *UpdatedFID)
2525 NTSTATUS ntStatus = STATUS_SUCCESS;
2526 AFSFileRenameCB *pRenameCB = NULL;
2527 AFSFileRenameResultCB *pRenameResultCB = NULL;
2528 ULONG ulResultLen = 0;
2529 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2535 // Init the control block for the request
2538 pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
2540 AFS_RENAME_REQUEST_TAG);
2542 if( pRenameCB == NULL)
2545 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2548 RtlZeroMemory( pRenameCB,
2551 pRenameCB->SourceParentId = ParentObjectInfo->FileId;
2553 pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
2555 pRenameCB->TargetNameLength = TargetName->Length;
2557 RtlCopyMemory( pRenameCB->TargetName,
2559 TargetName->Length);
2562 // Use the same buffer for the result control block
2565 pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
2567 ulResultLen = PAGE_SIZE;
2569 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
2570 AFS_REQUEST_FLAG_SYNCHRONOUS,
2572 &DirectoryCB->NameInformation.FileName,
2573 &ObjectInfo->FileId,
2574 ObjectInfo->VolumeCB->VolumeInformation.Cell,
2575 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2577 sizeof( AFSFileRenameCB) + TargetName->Length,
2581 if( ntStatus != STATUS_SUCCESS)
2584 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2585 AFS_TRACE_LEVEL_ERROR,
2586 "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2587 ObjectInfo->FileId.Cell,
2588 ObjectInfo->FileId.Volume,
2589 ObjectInfo->FileId.Vnode,
2590 ObjectInfo->FileId.Unique,
2593 try_return( ntStatus);
2597 // Update the information from the returned data
2600 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2603 if ( ParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->SourceParentDataVersion.QuadPart - 1)
2606 ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
2611 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2613 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2616 if ( ParentObjectInfo != TargetParentObjectInfo)
2619 AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2622 if ( TargetParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->TargetParentDataVersion.QuadPart - 1)
2625 TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
2630 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2632 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2637 // Move over the short name
2640 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2642 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2643 DirectoryCB->NameInformation.ShortNameLength > 0)
2646 UNICODE_STRING uniShortName;
2648 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2649 uniShortName.MaximumLength = uniShortName.Length;
2650 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2652 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2653 AFS_TRACE_LEVEL_VERBOSE,
2654 "AFSNotifyRename Update old short name %wZ for DE %p for %wZ\n",
2657 &DirectoryCB->NameInformation.FileName);
2659 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2661 RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
2662 pRenameResultCB->DirEnum.ShortName,
2663 DirectoryCB->NameInformation.ShortNameLength);
2665 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2666 uniShortName.MaximumLength = uniShortName.Length;
2667 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2669 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2670 AFS_TRACE_LEVEL_VERBOSE,
2671 "AFSNotifyRename Initialized short name %wZ for DE %p for %wZ\n",
2674 &DirectoryCB->NameInformation.FileName);
2679 UNICODE_STRING uniShortName;
2681 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2682 uniShortName.MaximumLength = uniShortName.Length;
2683 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2685 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2686 AFS_TRACE_LEVEL_VERBOSE,
2687 "AFSNotifyRename Removing old short name %wZ for DE %p for %wZ\n",
2690 &DirectoryCB->NameInformation.FileName);
2692 DirectoryCB->NameInformation.ShortNameLength = 0;
2694 DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2697 if ( ParentObjectInfo != TargetParentObjectInfo)
2700 AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2703 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2705 if( UpdatedFID != NULL)
2707 *UpdatedFID = pRenameResultCB->DirEnum.FileId;
2712 if( pRenameCB != NULL)
2715 AFSExFreePoolWithTag( pRenameCB, AFS_RENAME_REQUEST_TAG);
2723 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
2725 IN BOOLEAN FastCall,
2726 OUT AFSDirEnumEntry **DirEnumEntry)
2729 NTSTATUS ntStatus = STATUS_SUCCESS;
2730 AFSEvalTargetCB stTargetID;
2731 ULONG ulResultBufferLength;
2732 AFSFileEvalResultCB *pEvalResultCB = NULL;
2733 AFSDirEnumEntry *pDirEnumCB = NULL;
2734 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
2735 AFSObjectInfoCB *pParentObjectInfo = NULL;
2740 RtlZeroMemory( &stTargetID,
2741 sizeof( AFSEvalTargetCB));
2743 if ( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2746 pParentObjectInfo = AFSFindObjectInfo( ObjectInfo->VolumeCB,
2747 &ObjectInfo->ParentFileId);
2749 stTargetID.ParentId = ObjectInfo->ParentFileId;
2753 // Allocate our response buffer
2756 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2758 AFS_GENERIC_MEMORY_30_TAG);
2760 if( pEvalResultCB == NULL)
2763 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2767 // Call to the service to evaluate the fid
2770 ulResultBufferLength = PAGE_SIZE;
2775 ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
2778 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
2782 &ObjectInfo->FileId,
2783 ObjectInfo->VolumeCB->VolumeInformation.Cell,
2784 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2786 sizeof( AFSEvalTargetCB),
2788 &ulResultBufferLength);
2790 if( ntStatus != STATUS_SUCCESS)
2794 // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
2798 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2801 if( pParentObjectInfo != NULL)
2804 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2807 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2809 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2811 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2815 try_return( ntStatus);
2819 // A BSOD can occur if the pEvalResultCB->FileType is FILE but the
2820 // ObjectInfo->FileType is something else. The same is true for
2821 // pDirEnumEntry->FileType is DIRECTORY. Perform a sanity check
2822 // to ensure consistency. An inconsistent pDirEnumEntry can be
2823 // produced as a result of invalid status info received from a file
2824 // server. If the types are inconsistent or if the type does not
2825 // match the implied type derived from the vnode (odd values are
2826 // directories and even values are other types), prevent the request
2827 // from completing successfully. This may prevent access to the file or
2828 // directory but will prevent a BSOD.
2831 if ( !AFSIsEqualFID( &ObjectInfo->FileId,
2832 &pEvalResultCB->DirEnum.FileId))
2835 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2838 switch ( pEvalResultCB->DirEnum.FileType)
2841 case AFS_FILE_TYPE_DIRECTORY:
2842 if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x1)
2845 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2848 if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
2849 ObjectInfo->FileType != AFS_FILE_TYPE_DIRECTORY)
2852 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2857 case AFS_FILE_TYPE_FILE:
2858 if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x0)
2861 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2864 if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
2865 ObjectInfo->FileType != AFS_FILE_TYPE_FILE)
2868 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2875 // Validate the parent data version
2878 if ( pParentObjectInfo != NULL)
2881 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2884 if ( pParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2887 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2889 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2892 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2896 // Pass back the dir enum entry
2899 if( DirEnumEntry != NULL)
2902 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2904 AFS_GENERIC_MEMORY_2_TAG);
2906 if( pDirEnumCB == NULL)
2909 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2912 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2913 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2915 *DirEnumEntry = pDirEnumCB;
2920 if ( pParentObjectInfo != NULL)
2923 AFSReleaseObjectInfo( &pParentObjectInfo);
2926 if( pEvalResultCB != NULL)
2929 AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_30_TAG);
2932 if( !NT_SUCCESS( ntStatus))
2935 if( pDirEnumCB != NULL)
2938 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_2_TAG);
2941 *DirEnumEntry = NULL;
2949 AFSEvaluateTargetByName( IN GUID *AuthGroup,
2950 IN AFSObjectInfoCB *ParentObjectInfo,
2951 IN PUNICODE_STRING SourceName,
2953 OUT AFSDirEnumEntry **DirEnumEntry)
2956 NTSTATUS ntStatus = STATUS_SUCCESS;
2957 AFSEvalTargetCB stTargetID;
2958 ULONG ulResultBufferLength;
2959 AFSFileEvalResultCB *pEvalResultCB = NULL;
2960 AFSDirEnumEntry *pDirEnumCB = NULL;
2965 stTargetID.ParentId = ParentObjectInfo->FileId;
2968 // Allocate our response buffer
2971 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2973 AFS_GENERIC_MEMORY_31_TAG);
2975 if( pEvalResultCB == NULL)
2978 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2982 // Call to the service to evaluate the fid
2985 ulResultBufferLength = PAGE_SIZE;
2987 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
2988 AFS_REQUEST_FLAG_SYNCHRONOUS | Flags,
2992 ParentObjectInfo->VolumeCB->VolumeInformation.Cell,
2993 ParentObjectInfo->VolumeCB->VolumeInformation.CellLength,
2995 sizeof( AFSEvalTargetCB),
2997 &ulResultBufferLength);
2999 if( ntStatus != STATUS_SUCCESS)
3002 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
3005 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3008 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3010 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
3012 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3015 try_return( ntStatus);
3019 // Validate the parent data version
3022 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3025 if ( ParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
3028 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3030 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
3033 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3036 // Pass back the dir enum entry
3039 if( DirEnumEntry != NULL)
3042 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
3044 AFS_GENERIC_MEMORY_3_TAG);
3046 if( pDirEnumCB == NULL)
3049 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3052 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
3053 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
3055 *DirEnumEntry = pDirEnumCB;
3060 if( pEvalResultCB != NULL)
3063 AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_31_TAG);
3066 if( !NT_SUCCESS( ntStatus))
3069 if( pDirEnumCB != NULL)
3072 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_3_TAG);
3075 *DirEnumEntry = NULL;
3083 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
3084 IN AFSFileID *FileID,
3085 OUT AFSVolumeInfoCB *VolumeInformation)
3088 NTSTATUS ntStatus = STATUS_SUCCESS;
3089 ULONG ulResultLen = 0;
3094 ulResultLen = sizeof( AFSVolumeInfoCB);
3096 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
3097 AFS_REQUEST_FLAG_SYNCHRONOUS,
3108 if( ntStatus != STATUS_SUCCESS)
3111 try_return( ntStatus);
3123 AFSRetrieveVolumeSizeInformation( IN GUID *AuthGroup,
3124 IN AFSFileID *FileID,
3125 OUT AFSVolumeSizeInfoCB *VolumeSizeInformation)
3128 NTSTATUS ntStatus = STATUS_SUCCESS;
3129 ULONG ulResultLen = 0;
3134 ulResultLen = sizeof( AFSVolumeSizeInfoCB);
3136 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_SIZE_INFO,
3137 AFS_REQUEST_FLAG_SYNCHRONOUS,
3145 VolumeSizeInformation,
3148 if( ntStatus != STATUS_SUCCESS)
3151 try_return( ntStatus);
3163 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
3164 IN ULONG InputLength,
3165 IN ULONG OutputLength,
3166 IN void *InputDataBuffer,
3167 OUT void *OutputDataBuffer,
3168 OUT ULONG *BytesReturned)
3171 NTSTATUS ntStatus = STATUS_SUCCESS;
3172 ULONG ulResultLen = 0;
3173 MDL *pInputMdl = NULL, *pOutputMdl = NULL;
3174 void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
3175 AFSPipeIORequestCB *pIoRequest = NULL;
3181 // Map the user buffer to a system address
3184 pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
3188 if( pInputSystemBuffer == NULL)
3191 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3194 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
3195 sizeof( AFSPipeIORequestCB) +
3197 AFS_GENERIC_MEMORY_4_TAG);
3199 if( pIoRequest == NULL)
3202 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3205 RtlZeroMemory( pIoRequest,
3206 sizeof( AFSPipeIORequestCB) + InputLength);
3208 pIoRequest->RequestId = Ccb->RequestID;
3210 pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3212 pIoRequest->BufferLength = InputLength;
3214 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
3218 pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
3222 if( pOutputSystemBuffer == NULL)
3225 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3229 // Send the call to the service
3232 ulResultLen = OutputLength;
3234 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
3235 AFS_REQUEST_FLAG_SYNCHRONOUS,
3237 &Ccb->DirectoryCB->NameInformation.FileName,
3242 sizeof( AFSPipeIORequestCB) + InputLength,
3243 pOutputSystemBuffer,
3246 if( ntStatus != STATUS_SUCCESS &&
3247 ntStatus != STATUS_BUFFER_OVERFLOW)
3250 if( NT_SUCCESS( ntStatus))
3253 ntStatus = STATUS_DEVICE_NOT_READY;
3256 try_return( ntStatus);
3260 // Return the bytes processed
3263 *BytesReturned = ulResultLen;
3267 if( pInputMdl != NULL)
3270 MmUnlockPages( pInputMdl);
3272 IoFreeMdl( pInputMdl);
3275 if( pOutputMdl != NULL)
3278 MmUnlockPages( pOutputMdl);
3280 IoFreeMdl( pOutputMdl);
3283 if( pIoRequest != NULL)
3286 AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_4_TAG);
3294 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
3295 IN ULONG InformationClass,
3296 IN ULONG InputLength,
3297 IN void *DataBuffer)
3300 NTSTATUS ntStatus = STATUS_SUCCESS;
3301 AFSPipeInfoRequestCB *pInfoRequest = NULL;
3306 pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
3307 sizeof( AFSPipeInfoRequestCB) +
3309 AFS_GENERIC_MEMORY_5_TAG);
3311 if( pInfoRequest == NULL)
3314 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3317 RtlZeroMemory( pInfoRequest,
3318 sizeof( AFSPipeInfoRequestCB) + InputLength);
3320 pInfoRequest->RequestId = Ccb->RequestID;
3322 pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3324 pInfoRequest->BufferLength = InputLength;
3326 pInfoRequest->InformationClass = InformationClass;
3328 RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
3333 // Send the call to the service
3336 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
3337 AFS_REQUEST_FLAG_SYNCHRONOUS,
3339 &Ccb->DirectoryCB->NameInformation.FileName,
3344 sizeof( AFSPipeInfoRequestCB) + InputLength,
3348 if( ntStatus != STATUS_SUCCESS)
3351 if( NT_SUCCESS( ntStatus))
3354 ntStatus = STATUS_DEVICE_NOT_READY;
3357 try_return( ntStatus);
3362 if( pInfoRequest != NULL)
3365 AFSExFreePoolWithTag( pInfoRequest, AFS_GENERIC_MEMORY_5_TAG);
3373 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
3374 IN ULONG InformationClass,
3375 IN ULONG OutputLength,
3376 IN void *DataBuffer,
3377 OUT ULONG *BytesReturned)
3380 NTSTATUS ntStatus = STATUS_SUCCESS;
3381 AFSPipeInfoRequestCB stInfoRequest;
3382 ULONG ulBytesProcessed = 0;
3387 RtlZeroMemory( &stInfoRequest,
3388 sizeof( AFSPipeInfoRequestCB));
3390 stInfoRequest.RequestId = Ccb->RequestID;
3392 stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3394 stInfoRequest.BufferLength = OutputLength;
3396 stInfoRequest.InformationClass = InformationClass;
3398 ulBytesProcessed = OutputLength;
3401 // Send the call to the service
3404 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
3405 AFS_REQUEST_FLAG_SYNCHRONOUS,
3407 &Ccb->DirectoryCB->NameInformation.FileName,
3412 sizeof( AFSPipeInfoRequestCB),
3416 if( ntStatus != STATUS_SUCCESS)
3419 if( NT_SUCCESS( ntStatus))
3422 ntStatus = STATUS_DEVICE_NOT_READY;
3425 try_return( ntStatus);
3428 *BytesReturned = ulBytesProcessed;
3439 AFSReleaseFid( IN AFSFileID *FileId)
3442 NTSTATUS ntStatus = STATUS_SUCCESS;
3447 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
3464 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
3465 IN LARGE_INTEGER *ExtentOffset,
3469 BOOLEAN bRequestQueued = FALSE;
3470 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3471 AFSCommSrvcCB *pCommSrvc = NULL;
3472 AFSPoolEntry *pPoolEntry = NULL;
3473 AFSRequestExtentsCB *pRequestExtents = NULL;
3479 pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
3481 AFSAcquireShared( &pCommSrvc->IrpPoolLock,
3484 pPoolEntry = pCommSrvc->RequestPoolHead;
3486 while( pPoolEntry != NULL)
3489 if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
3492 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
3495 pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
3497 if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
3498 pRequestExtents->Length == Length)
3501 bRequestQueued = TRUE;
3506 pPoolEntry = pPoolEntry->fLink;
3509 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
3512 return bRequestQueued;