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));
67 uniGUID.MaximumLength = 0;
68 uniGUID.Buffer = NULL;
70 if( AuthGroup != NULL)
72 RtlStringFromGUID( *AuthGroup,
76 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
77 AFS_TRACE_LEVEL_VERBOSE,
78 "AFSEnumerateDirectory Enumerating FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
79 ObjectInfoCB->FileId.Cell,
80 ObjectInfoCB->FileId.Volume,
81 ObjectInfoCB->FileId.Vnode,
82 ObjectInfoCB->FileId.Unique,
85 if( AuthGroup != NULL)
87 RtlFreeUnicodeString( &uniGUID);
91 // Initialize the directory enumeration buffer for the directory
94 pBuffer = AFSExAllocatePoolWithTag( PagedPool,
95 AFS_DIR_ENUM_BUFFER_LEN,
101 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
104 RtlZeroMemory( pBuffer,
105 AFS_DIR_ENUM_BUFFER_LEN);
107 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
110 // Use the payload buffer for information we will pass to the service
113 pDirQueryCB = (AFSDirQueryCB *)pBuffer;
115 pDirQueryCB->EnumHandle = 0;
120 ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
124 // Loop on the information
131 // If the enumeration handle is -1 then we are done
134 if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
137 ntStatus = STATUS_NO_MORE_ENTRIES;
143 // Go and retrieve the directory contents
146 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
150 &ObjectInfoCB->FileId,
152 sizeof( AFSDirQueryCB),
157 if( ntStatus != STATUS_SUCCESS ||
161 if( ntStatus == STATUS_NO_MORE_FILES ||
162 ntStatus == STATUS_NO_MORE_ENTRIES)
165 ntStatus = STATUS_SUCCESS;
167 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
169 AFSAcquireExcl( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock,
172 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
173 AFS_TRACE_LEVEL_VERBOSE,
174 "AFSEnumerateDirectory Directory Complete FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX Status %08lX\n",
175 ObjectInfoCB->FileId.Cell,
176 ObjectInfoCB->FileId.Volume,
177 ObjectInfoCB->FileId.Vnode,
178 ObjectInfoCB->FileId.Unique,
179 pDirEnumResponse->SnapshotDataVersion.HighPart,
180 pDirEnumResponse->SnapshotDataVersion.LowPart,
181 pDirEnumResponse->CurrentDataVersion.HighPart,
182 pDirEnumResponse->CurrentDataVersion.LowPart,
185 ObjectInfoCB->DataVersion = pDirEnumResponse->SnapshotDataVersion;
187 if ( pDirEnumResponse->SnapshotDataVersion.QuadPart != pDirEnumResponse->CurrentDataVersion.QuadPart )
190 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
192 ObjectInfoCB->DataVersion.QuadPart = (ULONGLONG)-1;
194 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
195 AFS_TRACE_LEVEL_VERBOSE,
196 "AFSEnumerateDirectory Force Verify due to DV change during enumeration FID %08lX-%08lX-%08lX-%08lX\n",
197 ObjectInfoCB->FileId.Cell,
198 ObjectInfoCB->FileId.Volume,
199 ObjectInfoCB->FileId.Vnode,
200 ObjectInfoCB->FileId.Unique);
203 AFSReleaseResource( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock);
208 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
209 AFS_TRACE_LEVEL_VERBOSE,
210 "AFSEnumerateDirectory Failed to enumerate directory FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ Status %08lX\n",
211 ObjectInfoCB->FileId.Cell,
212 ObjectInfoCB->FileId.Volume,
213 ObjectInfoCB->FileId.Vnode,
214 ObjectInfoCB->FileId.Unique,
222 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
224 pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
226 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
227 AFS_TRACE_LEVEL_VERBOSE,
228 "AFSEnumerateDirectory Enumerating FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX\n",
229 ObjectInfoCB->FileId.Cell,
230 ObjectInfoCB->FileId.Volume,
231 ObjectInfoCB->FileId.Vnode,
232 ObjectInfoCB->FileId.Unique,
233 pDirEnumResponse->SnapshotDataVersion.HighPart,
234 pDirEnumResponse->SnapshotDataVersion.LowPart,
235 pDirEnumResponse->CurrentDataVersion.HighPart,
236 pDirEnumResponse->CurrentDataVersion.LowPart);
239 // Remove the leading header from the processed length
242 ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
244 while( ulResultLen > 0)
247 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
249 uniDirName.MaximumLength = uniDirName.Length;
251 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
253 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
255 uniTargetName.MaximumLength = uniTargetName.Length;
257 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
260 // Be sure we don't have this entry in the case sensitive tree
263 ulCRC = AFSGenerateCRC( &uniDirName,
266 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
270 if( pDirNode != NULL)
274 // Check that the FIDs are the same
277 if( AFSIsEqualFID( &pCurrentDirEntry->FileId,
278 &pDirNode->ObjectInformation->FileId))
282 // Duplicate entry, skip it
285 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
287 uniTargetName.Length);
289 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
291 if( ulResultLen >= ulEntryLength)
293 ulResultLen -= ulEntryLength;
301 // Update the metadata for the entry
304 if( pDirNode->ObjectInformation->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
308 AFSObjectInfoCB *pObjectInfo = pDirNode->ObjectInformation;
311 // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
314 lCount = AFSObjectInfoIncrement( pObjectInfo,
315 AFS_OBJECT_REFERENCE_INVALIDATION);
317 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
318 AFS_TRACE_LEVEL_VERBOSE,
319 "AFSEnumerateDirectory calling AFSPerformObjectInvalidate Increment count on object %p Cnt %d\n",
323 AFSPerformObjectInvalidate( pObjectInfo,
324 AFS_INVALIDATE_DATA_VERSION);
329 AFSUpdateMetaData( pDirNode,
339 // Need to tear down this entry and rebuild it below
342 if( pDirNode->DirOpenReferenceCount <= 0)
345 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
346 AFS_TRACE_LEVEL_VERBOSE,
347 "AFSEnumerateDirectory Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
349 &pDirNode->NameInformation.FileName,
350 pDirNode->ObjectInformation->FileId.Cell,
351 pDirNode->ObjectInformation->FileId.Volume,
352 pDirNode->ObjectInformation->FileId.Vnode,
353 pDirNode->ObjectInformation->FileId.Unique,
354 pCurrentDirEntry->FileId.Cell,
355 pCurrentDirEntry->FileId.Volume,
356 pCurrentDirEntry->FileId.Vnode,
357 pCurrentDirEntry->FileId.Unique);
359 AFSDeleteDirEntry( ObjectInfoCB,
365 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
367 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
368 AFS_TRACE_LEVEL_VERBOSE,
369 "AFSEnumerateDirectory Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
371 &pDirNode->NameInformation.FileName,
372 pDirNode->ObjectInformation->FileId.Cell,
373 pDirNode->ObjectInformation->FileId.Volume,
374 pDirNode->ObjectInformation->FileId.Vnode,
375 pDirNode->ObjectInformation->FileId.Unique,
376 pCurrentDirEntry->FileId.Cell,
377 pCurrentDirEntry->FileId.Volume,
378 pCurrentDirEntry->FileId.Vnode,
379 pCurrentDirEntry->FileId.Unique);
381 AFSRemoveNameEntry( ObjectInfoCB,
389 pDirNode = AFSInitDirEntry( ObjectInfoCB,
393 (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
395 if( pDirNode == NULL)
398 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
403 AFSUpdateMetaData( pDirNode,
406 if( pDirNode->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
409 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
410 AFS_TRACE_LEVEL_VERBOSE,
411 "AFSEnumerateDirectory Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
413 pDirNode->ObjectInformation->FileId.Cell,
414 pDirNode->ObjectInformation->FileId.Volume,
415 pDirNode->ObjectInformation->FileId.Vnode,
416 pDirNode->ObjectInformation->FileId.Unique);
418 AFSAcquireExcl( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
421 SetFlag( pDirNode->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
423 pDirNode->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
425 AFSReleaseResource( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
429 // Set up the entry length
432 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
433 pCurrentDirEntry->FileNameLength +
434 pCurrentDirEntry->TargetNameLength);
437 // Init the short name if we have one
440 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
441 pCurrentDirEntry->ShortNameLength > 0)
444 UNICODE_STRING uniShortName;
446 pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
448 RtlCopyMemory( pDirNode->NameInformation.ShortName,
449 pCurrentDirEntry->ShortName,
450 pDirNode->NameInformation.ShortNameLength);
453 // Generate the short name index
456 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
457 uniShortName.MaximumLength = uniShortName.Length;
458 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
460 if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
465 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
468 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
469 AFS_TRACE_LEVEL_VERBOSE,
470 "AFSEnumerateDirectory Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
473 &pDirNode->NameInformation.FileName,
474 pCurrentDirEntry->FileId.Cell,
475 pCurrentDirEntry->FileId.Volume,
476 pCurrentDirEntry->FileId.Vnode,
477 pCurrentDirEntry->FileId.Unique);
481 pDirNode->NameInformation.ShortNameLength = 0;
483 RtlZeroMemory( pDirNode->NameInformation.ShortName,
484 (12 * sizeof( WCHAR)));
491 // No short name or short names are disabled
494 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
498 // Insert the node into the name tree
501 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
504 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
506 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
507 AFS_TRACE_LEVEL_VERBOSE,
508 "AFSEnumerateDirectory Insert DE %p to head of case sensitive tree for %wZ\n",
510 &pDirNode->NameInformation.FileName);
515 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
516 AFS_TRACE_LEVEL_VERBOSE,
517 "AFSEnumerateDirectory Insert DE %p to case sensitive tree for %wZ\n",
519 &pDirNode->NameInformation.FileName);
521 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
526 // Delete this dir entry and continue on
529 AFSDeleteDirEntry( ObjectInfoCB,
532 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
534 if( ulResultLen >= ulEntryLength)
536 ulResultLen -= ulEntryLength;
547 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
549 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
552 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
553 AFS_TRACE_LEVEL_VERBOSE,
554 "AFSEnumerateDirectory Insert DE %p to head of case insensitive tree for %wZ\n",
556 &pDirNode->NameInformation.FileName);
558 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
560 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
565 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
566 AFS_TRACE_LEVEL_VERBOSE,
567 "AFSEnumerateDirectory Insert DE %p to case insensitive tree for %wZ\n",
569 &pDirNode->NameInformation.FileName);
571 AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
575 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
578 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
583 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
585 pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
588 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
590 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
592 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
594 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
595 AFS_TRACE_LEVEL_VERBOSE,
596 "AFSEnumerateDirectory Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
597 &pDirNode->NameInformation.FileName,
598 ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
599 ObjectInfoCB->FileId.Cell,
600 ObjectInfoCB->FileId.Volume,
601 ObjectInfoCB->FileId.Vnode,
602 ObjectInfoCB->FileId.Unique);
604 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
608 // Insert the short name entry if we have a valid short name
611 if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
614 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
615 AFS_TRACE_LEVEL_VERBOSE,
616 "AFSEnumerateDirectory Insert DE %p to head of shortname tree for %wZ\n",
618 &pDirNode->NameInformation.FileName);
620 ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
622 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
627 if( NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
630 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
632 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
633 AFS_TRACE_LEVEL_VERBOSE,
634 "AFSEnumerateDirectory Insert DE %p to shortname tree for %wZ\n",
636 &pDirNode->NameInformation.FileName);
645 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
647 if( ulResultLen >= ulEntryLength)
649 ulResultLen -= ulEntryLength;
657 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
660 // Reset the information in the request buffer since it got trampled
664 pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
666 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
667 AFS_TRACE_LEVEL_VERBOSE,
668 "AFSEnumerateDirectory EnumHandle %08lX\n",
669 pDirQueryCB->EnumHandle);
681 AFSExFreePoolWithTag( pBuffer, AFS_DIR_BUFFER_TAG);
685 // If the processing failed then we should reset the directory content in the event
686 // it is re-enumerated
689 if( !NT_SUCCESS( ntStatus))
692 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
693 AFS_TRACE_LEVEL_ERROR,
694 "AFSEnumerateDirectory Resetting content for FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
695 ObjectInfoCB->FileId.Cell,
696 ObjectInfoCB->FileId.Volume,
697 ObjectInfoCB->FileId.Vnode,
698 ObjectInfoCB->FileId.Unique,
701 AFSResetDirectoryContent( ObjectInfoCB);
709 AFSEnumerateDirectoryNoResponse( IN GUID *AuthGroup,
710 IN AFSFileID *FileId)
713 NTSTATUS ntStatus = STATUS_SUCCESS;
714 AFSDirQueryCB stDirQueryCB;
715 ULONG ulRequestFlags = 0;
721 // Use the payload buffer for information we will pass to the service
724 stDirQueryCB.EnumHandle = 0;
726 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
731 (void *)&stDirQueryCB,
732 sizeof( AFSDirQueryCB),
736 if( ntStatus != STATUS_SUCCESS)
739 if( ntStatus == STATUS_NO_MORE_FILES ||
740 ntStatus == STATUS_NO_MORE_ENTRIES)
743 ntStatus = STATUS_SUCCESS;
748 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
749 AFS_TRACE_LEVEL_ERROR,
750 "AFSEnumerateDirectoryNoResponse Failed to enumerate directory Status %08lX\n",
760 AFSVerifyDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB,
764 NTSTATUS ntStatus = STATUS_SUCCESS;
765 void *pBuffer = NULL;
766 ULONG ulResultLen = 0;
767 AFSDirQueryCB *pDirQueryCB;
768 AFSDirEnumEntry *pCurrentDirEntry = NULL;
769 AFSDirectoryCB *pDirNode = NULL;
770 ULONG ulEntryLength = 0;
771 AFSDirEnumResp *pDirEnumResponse = NULL;
772 UNICODE_STRING uniDirName, uniTargetName;
773 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_FAST_REQUEST;
775 AFSObjectInfoCB *pObjectInfo = NULL;
776 ULONGLONG ullIndex = 0;
777 UNICODE_STRING uniGUID;
779 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
784 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
787 uniGUID.MaximumLength = 0;
788 uniGUID.Buffer = NULL;
790 if( AuthGroup != NULL)
792 RtlStringFromGUID( *AuthGroup,
796 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
797 AFS_TRACE_LEVEL_VERBOSE,
798 "AFSVerifyDirectoryContent Verifying content for FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
799 ObjectInfoCB->FileId.Cell,
800 ObjectInfoCB->FileId.Volume,
801 ObjectInfoCB->FileId.Vnode,
802 ObjectInfoCB->FileId.Unique,
805 if( AuthGroup != NULL)
807 RtlFreeUnicodeString( &uniGUID);
811 // Initialize the directory enumeration buffer for the directory
814 pBuffer = AFSExAllocatePoolWithTag( PagedPool,
815 AFS_DIR_ENUM_BUFFER_LEN,
821 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
824 RtlZeroMemory( pBuffer,
825 AFS_DIR_ENUM_BUFFER_LEN);
827 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
830 // Use the payload buffer for information we will pass to the service
833 pDirQueryCB = (AFSDirQueryCB *)pBuffer;
835 pDirQueryCB->EnumHandle = 0;
838 // Loop on the information
845 // If the enumeration handle is -1 then we are done
848 if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
851 ntStatus = STATUS_NO_MORE_ENTRIES;
857 // Go and retrieve the directory contents
860 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
864 &ObjectInfoCB->FileId,
866 sizeof( AFSDirQueryCB),
871 if( ntStatus != STATUS_SUCCESS ||
875 if( ntStatus == STATUS_NO_MORE_FILES ||
876 ntStatus == STATUS_NO_MORE_ENTRIES)
879 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
881 AFSAcquireExcl( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock,
884 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
885 AFS_TRACE_LEVEL_VERBOSE,
886 "AFSVerifyDirectoryContent Directory Complete FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX Status %08lX\n",
887 ObjectInfoCB->FileId.Cell,
888 ObjectInfoCB->FileId.Volume,
889 ObjectInfoCB->FileId.Vnode,
890 ObjectInfoCB->FileId.Unique,
891 pDirEnumResponse->SnapshotDataVersion.HighPart,
892 pDirEnumResponse->SnapshotDataVersion.LowPart,
893 pDirEnumResponse->CurrentDataVersion.HighPart,
894 pDirEnumResponse->CurrentDataVersion.LowPart,
897 ntStatus = STATUS_SUCCESS;
899 if ( pDirEnumResponse->SnapshotDataVersion.QuadPart != pDirEnumResponse->CurrentDataVersion.QuadPart )
902 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
904 ObjectInfoCB->DataVersion.QuadPart = (ULONGLONG)-1;
906 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
907 AFS_TRACE_LEVEL_VERBOSE,
908 "AFSVerifyDirectoryContent Force Verify due to DV change during enumeration FID %08lX-%08lX-%08lX-%08lX\n",
909 ObjectInfoCB->FileId.Cell,
910 ObjectInfoCB->FileId.Volume,
911 ObjectInfoCB->FileId.Vnode,
912 ObjectInfoCB->FileId.Unique);
917 ObjectInfoCB->DataVersion = pDirEnumResponse->SnapshotDataVersion;
920 AFSReleaseResource( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock);
925 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
926 AFS_TRACE_LEVEL_ERROR,
927 "AFSVerifyDirectoryContent Failed to enumerate directory FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ Status %08lX\n",
928 ObjectInfoCB->FileId.Cell,
929 ObjectInfoCB->FileId.Volume,
930 ObjectInfoCB->FileId.Vnode,
931 ObjectInfoCB->FileId.Unique,
939 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
941 pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
943 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
944 AFS_TRACE_LEVEL_VERBOSE,
945 "AFSVerifyDirectoryContent EnumResponse FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX\n",
946 ObjectInfoCB->FileId.Cell,
947 ObjectInfoCB->FileId.Volume,
948 ObjectInfoCB->FileId.Vnode,
949 ObjectInfoCB->FileId.Unique,
950 pDirEnumResponse->SnapshotDataVersion.HighPart,
951 pDirEnumResponse->SnapshotDataVersion.LowPart,
952 pDirEnumResponse->CurrentDataVersion.HighPart,
953 pDirEnumResponse->CurrentDataVersion.LowPart);
956 // Remove the leading header from the processed length
959 ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
961 while( ulResultLen > 0)
964 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
966 uniDirName.MaximumLength = uniDirName.Length;
968 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
970 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
972 uniTargetName.MaximumLength = uniTargetName.Length;
974 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
977 // Does this entry already exist in the directory?
980 ulCRC = AFSGenerateCRC( &uniDirName,
983 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
989 // Set up the entry length
992 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
993 pCurrentDirEntry->FileNameLength +
994 pCurrentDirEntry->TargetNameLength);
997 AFSIsEqualFID( &pCurrentDirEntry->FileId,
998 &pDirNode->ObjectInformation->FileId))
1002 // Found matching directory entry by name and FileID
1005 AFSAcquireShared( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock,
1008 ullIndex = AFSCreateLowIndex( &pCurrentDirEntry->FileId);
1010 ntStatus = AFSLocateHashEntry( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeHead,
1012 (AFSBTreeEntry **)&pObjectInfo);
1014 AFSReleaseResource( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock);
1016 if( NT_SUCCESS( ntStatus) &&
1017 pObjectInfo != NULL)
1021 // Indicate this is a valid entry
1024 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
1026 if( pCurrentDirEntry->ShortNameLength > 0 &&
1027 pDirNode->NameInformation.ShortNameLength > 0)
1029 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1030 AFS_TRACE_LEVEL_VERBOSE,
1031 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name %S New short name %S\n",
1033 &pDirNode->NameInformation.FileName,
1034 ObjectInfoCB->FileId.Cell,
1035 ObjectInfoCB->FileId.Volume,
1036 ObjectInfoCB->FileId.Vnode,
1037 ObjectInfoCB->FileId.Unique,
1038 pDirNode->NameInformation.ShortName,
1039 pCurrentDirEntry->ShortName);
1041 else if( pCurrentDirEntry->ShortNameLength == 0 &&
1042 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 NULL\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);
1056 else if( pCurrentDirEntry->ShortNameLength > 0 &&
1057 pDirNode->NameInformation.ShortNameLength == 0)
1059 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1060 AFS_TRACE_LEVEL_VERBOSE,
1061 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name %S\n",
1063 &pDirNode->NameInformation.FileName,
1064 ObjectInfoCB->FileId.Cell,
1065 ObjectInfoCB->FileId.Volume,
1066 ObjectInfoCB->FileId.Vnode,
1067 ObjectInfoCB->FileId.Unique,
1068 pCurrentDirEntry->ShortName);
1072 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1073 AFS_TRACE_LEVEL_VERBOSE,
1074 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name NULL\n",
1076 &pDirNode->NameInformation.FileName,
1077 ObjectInfoCB->FileId.Cell,
1078 ObjectInfoCB->FileId.Volume,
1079 ObjectInfoCB->FileId.Vnode,
1080 ObjectInfoCB->FileId.Unique);
1084 // Update the metadata for the entry
1087 if( pObjectInfo->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
1091 // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
1092 // if successfully queued. Cannot call AFSPerformObjectInvalidate directly
1093 // because ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock is
1094 // held during the sequence AFSVerifyEntry->AFSValidateDirectoryCache->
1095 // AFSVerifyDirectoryContent and AFSPerformObjectInvalidate requires the
1096 // Fcb->NPFcb->Resource which must be held prior to the TreeLock in the
1100 lCount = AFSObjectInfoIncrement( pObjectInfo,
1101 AFS_OBJECT_REFERENCE_INVALIDATION);
1103 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1104 AFS_TRACE_LEVEL_VERBOSE,
1105 "AFSVerifyDirectoryContent calling AFSQueueInvalidateObject Increment count on object %p Cnt %d\n",
1109 if ( !NT_SUCCESS( AFSQueueInvalidateObject( pObjectInfo,
1110 AFS_INVALIDATE_DATA_VERSION)))
1113 lCount = AFSObjectInfoDecrement( pObjectInfo,
1114 AFS_OBJECT_REFERENCE_INVALIDATION);
1116 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1117 AFS_TRACE_LEVEL_VERBOSE,
1118 "AFSVerifyDirectoryContent AFSQueueInvalidateObject failed Decrement count on object %p Cnt %d\n",
1126 AFSUpdateMetaData( pDirNode,
1134 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1136 if( ulResultLen >= ulEntryLength)
1138 ulResultLen -= ulEntryLength;
1152 // File name matches but FileID does not.
1155 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1156 AFS_TRACE_LEVEL_VERBOSE,
1157 "AFSVerifyDirectoryContent Processing dir entry %p %wZ with different FID, same name in parent FID %08lX-%08lX-%08lX-%08lX\n",
1159 &pDirNode->NameInformation.FileName,
1160 ObjectInfoCB->FileId.Cell,
1161 ObjectInfoCB->FileId.Volume,
1162 ObjectInfoCB->FileId.Vnode,
1163 ObjectInfoCB->FileId.Unique);
1166 // Need to tear down this entry and rebuild it below
1169 if( pDirNode->DirOpenReferenceCount <= 0)
1172 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1173 AFS_TRACE_LEVEL_VERBOSE,
1174 "AFSVerifyDirectoryContent Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1176 &pDirNode->NameInformation.FileName,
1177 pDirNode->ObjectInformation->FileId.Cell,
1178 pDirNode->ObjectInformation->FileId.Volume,
1179 pDirNode->ObjectInformation->FileId.Vnode,
1180 pDirNode->ObjectInformation->FileId.Unique,
1181 pCurrentDirEntry->FileId.Cell,
1182 pCurrentDirEntry->FileId.Volume,
1183 pCurrentDirEntry->FileId.Vnode,
1184 pCurrentDirEntry->FileId.Unique);
1186 AFSDeleteDirEntry( ObjectInfoCB,
1192 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1194 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1195 AFS_TRACE_LEVEL_WARNING,
1196 "AFSVerifyDirectoryContent Different FIDs - removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1198 &pDirNode->NameInformation.FileName,
1199 pDirNode->ObjectInformation->FileId.Cell,
1200 pDirNode->ObjectInformation->FileId.Volume,
1201 pDirNode->ObjectInformation->FileId.Vnode,
1202 pDirNode->ObjectInformation->FileId.Unique,
1203 pCurrentDirEntry->FileId.Cell,
1204 pCurrentDirEntry->FileId.Volume,
1205 pCurrentDirEntry->FileId.Vnode,
1206 pCurrentDirEntry->FileId.Unique);
1208 AFSRemoveNameEntry( ObjectInfoCB,
1215 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1216 AFS_TRACE_LEVEL_VERBOSE,
1217 "AFSVerifyDirectoryContent New entry %wZ for parent FID %08lX-%08lX-%08lX-%08lX\n",
1219 ObjectInfoCB->FileId.Cell,
1220 ObjectInfoCB->FileId.Volume,
1221 ObjectInfoCB->FileId.Vnode,
1222 ObjectInfoCB->FileId.Unique);
1225 pDirNode = AFSInitDirEntry( ObjectInfoCB,
1229 (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1231 if( pDirNode == NULL)
1234 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
1239 AFSUpdateMetaData( pDirNode,
1242 if( pDirNode->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1245 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1246 AFS_TRACE_LEVEL_VERBOSE,
1247 "AFSVerifyDirectoryContent Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
1249 pDirNode->ObjectInformation->FileId.Cell,
1250 pDirNode->ObjectInformation->FileId.Volume,
1251 pDirNode->ObjectInformation->FileId.Vnode,
1252 pDirNode->ObjectInformation->FileId.Unique);
1254 AFSAcquireExcl( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1257 SetFlag( pDirNode->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1259 pDirNode->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1261 AFSReleaseResource( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1265 // Init the short name if we have one
1268 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1269 pCurrentDirEntry->ShortNameLength > 0)
1272 UNICODE_STRING uniShortName;
1274 pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
1276 RtlCopyMemory( pDirNode->NameInformation.ShortName,
1277 pCurrentDirEntry->ShortName,
1278 pDirNode->NameInformation.ShortNameLength);
1281 // Generate the short name index
1284 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1285 uniShortName.MaximumLength = uniShortName.Length;
1286 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1288 if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
1293 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1296 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1297 AFS_TRACE_LEVEL_VERBOSE,
1298 "AFSVerifyDirectoryContent Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1301 &pDirNode->NameInformation.FileName,
1302 pCurrentDirEntry->FileId.Cell,
1303 pCurrentDirEntry->FileId.Volume,
1304 pCurrentDirEntry->FileId.Vnode,
1305 pCurrentDirEntry->FileId.Unique);
1309 pDirNode->NameInformation.ShortNameLength = 0;
1311 RtlZeroMemory( pDirNode->NameInformation.ShortName,
1312 (12 * sizeof( WCHAR)));
1319 // No short name or short names have been disabled
1322 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
1326 // Insert the node into the name tree
1329 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
1331 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
1334 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
1336 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1337 AFS_TRACE_LEVEL_VERBOSE,
1338 "AFSVerifyDirectoryContent Insert DE %p to head of case sensitive tree for %wZ\n",
1340 &pDirNode->NameInformation.FileName);
1345 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1348 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1349 AFS_TRACE_LEVEL_VERBOSE,
1350 "AFSVerifyDirectoryContent Failed to insert DE %p to case sensitive tree for %wZ\n",
1352 &pDirNode->NameInformation.FileName);
1355 // Delete this dir entry and continue on
1358 AFSDeleteDirEntry( ObjectInfoCB,
1361 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1363 if( ulResultLen >= ulEntryLength)
1365 ulResultLen -= ulEntryLength;
1376 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1377 AFS_TRACE_LEVEL_VERBOSE,
1378 "AFSVerifyDirectoryContent Insert DE %p to case sensitive tree for %wZ\n",
1380 &pDirNode->NameInformation.FileName);
1384 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1386 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
1389 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
1391 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
1393 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1394 AFS_TRACE_LEVEL_VERBOSE,
1395 "AFSVerifyDirectoryContent Insert DE %p to head of case insensitive tree for %wZ\n",
1397 &pDirNode->NameInformation.FileName);
1402 AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1405 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1406 AFS_TRACE_LEVEL_VERBOSE,
1407 "AFSVerifyDirectoryContent Insert DE %p to case insensitive tree for %wZ\n",
1409 &pDirNode->NameInformation.FileName);
1412 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
1415 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
1420 (ObjectInfoCB->Specific.Directory.DirectoryNodeListTail)->ListEntry.fLink = pDirNode;
1422 pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
1425 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
1427 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
1429 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
1431 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1432 AFS_TRACE_LEVEL_VERBOSE,
1433 "AFSVerifyDirectoryContent Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
1434 &pDirNode->NameInformation.FileName,
1435 ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
1436 ObjectInfoCB->FileId.Cell,
1437 ObjectInfoCB->FileId.Volume,
1438 ObjectInfoCB->FileId.Vnode,
1439 ObjectInfoCB->FileId.Unique);
1441 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
1445 // Insert the short name entry if we have a valid short name
1448 if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
1451 ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
1453 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1454 AFS_TRACE_LEVEL_VERBOSE,
1455 "AFSVerifyDirectoryContent Insert DE %p to head of shortname tree for %wZ\n",
1457 &pDirNode->NameInformation.FileName);
1459 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1464 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
1467 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1468 AFS_TRACE_LEVEL_VERBOSE,
1469 "AFSVerifyDirectoryContent Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
1471 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex,
1472 &pDirNode->NameInformation.FileName);
1476 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1478 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1479 AFS_TRACE_LEVEL_VERBOSE,
1480 "AFSVerifyDirectoryContent Insert DE %p to shortname tree for %wZ\n",
1482 &pDirNode->NameInformation.FileName);
1487 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
1493 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1495 if( ulResultLen >= ulEntryLength)
1497 ulResultLen -= ulEntryLength;
1505 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
1508 // Reset the information in the request buffer since it got trampled
1512 pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
1521 if( pBuffer != NULL)
1524 AFSExFreePoolWithTag( pBuffer, AFS_DIR_BUFFER_TAG);
1532 AFSNotifyFileCreate( IN GUID *AuthGroup,
1533 IN AFSObjectInfoCB *ParentObjectInfo,
1534 IN PLARGE_INTEGER FileSize,
1535 IN ULONG FileAttributes,
1536 IN UNICODE_STRING *FileName,
1537 OUT AFSDirectoryCB **DirNode)
1540 NTSTATUS ntStatus = STATUS_SUCCESS;
1541 AFSFileCreateCB stCreateCB;
1542 AFSFileCreateResultCB *pResultCB = NULL;
1543 ULONG ulResultLen = 0;
1544 UNICODE_STRING uniTargetName;
1545 AFSDirectoryCB *pDirNode = NULL;
1548 LARGE_INTEGER liOldDataVersion;
1549 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1550 BOOLEAN bReleaseParentTreeLock = FALSE;
1558 // Init the control block for the request
1561 RtlZeroMemory( &stCreateCB,
1562 sizeof( AFSFileCreateCB));
1564 stCreateCB.ParentId = ParentObjectInfo->FileId;
1566 stCreateCB.AllocationSize = *FileSize;
1568 stCreateCB.FileAttributes = FileAttributes;
1570 stCreateCB.EaSize = 0;
1572 liOldDataVersion = ParentObjectInfo->DataVersion;
1575 // Allocate our return buffer
1578 pResultCB = (AFSFileCreateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1580 AFS_GENERIC_MEMORY_1_TAG);
1582 if( pResultCB == NULL)
1585 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1588 RtlZeroMemory( pResultCB,
1591 ulResultLen = PAGE_SIZE;
1594 // Send the call to the service
1597 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_FILE,
1598 AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_HOLD_FID,
1603 sizeof( AFSFileCreateCB),
1607 if( ntStatus != STATUS_SUCCESS)
1610 if( NT_SUCCESS( ntStatus))
1613 ntStatus = STATUS_DEVICE_NOT_READY;
1616 try_return( ntStatus);
1620 // We may have raced with an invalidation call and a subsequent re-enumeration of this parent
1621 // and though we created the node, it is already in our list. If this is the case then
1622 // look up the entry rather than create a new entry
1623 // The check is to ensure the DV has been modified
1626 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1629 bReleaseParentTreeLock = TRUE;
1631 if( ParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
1634 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1635 AFS_TRACE_LEVEL_WARNING,
1636 "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",
1638 ParentObjectInfo->FileId.Cell,
1639 ParentObjectInfo->FileId.Volume,
1640 ParentObjectInfo->FileId.Vnode,
1641 ParentObjectInfo->FileId.Unique,
1642 ParentObjectInfo->DataVersion.HighPart,
1643 ParentObjectInfo->DataVersion.LowPart,
1644 pResultCB->ParentDataVersion.HighPart,
1645 pResultCB->ParentDataVersion.LowPart);
1648 // We raced so go and lookup the directory entry in the parent
1651 ulCRC = AFSGenerateCRC( FileName,
1654 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1658 if( pDirNode != NULL)
1661 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1662 AFS_TRACE_LEVEL_VERBOSE,
1663 "AFSNotifyFileCreate Located dir entry %p for file %wZ\n",
1667 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
1668 &pResultCB->DirEnum.FileId))
1671 *DirNode = pDirNode;
1673 try_return( ntStatus = STATUS_REPARSE);
1679 // We found an entry that matches the desired name but it is not the
1680 // same as the one that was created for us by the file server.
1683 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1684 AFS_TRACE_LEVEL_ERROR,
1685 "AFSNotifyFileCreate Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
1688 pDirNode->ObjectInformation->FileId.Cell,
1689 pDirNode->ObjectInformation->FileId.Volume,
1690 pDirNode->ObjectInformation->FileId.Vnode,
1691 pDirNode->ObjectInformation->FileId.Unique,
1692 pResultCB->DirEnum.FileId.Cell,
1693 pResultCB->DirEnum.FileId.Volume,
1694 pResultCB->DirEnum.FileId.Vnode,
1695 pResultCB->DirEnum.FileId.Unique);
1697 if( pDirNode->DirOpenReferenceCount <= 0)
1700 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1701 AFS_TRACE_LEVEL_VERBOSE,
1702 "AFSNotifyFileCreate Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1704 &pDirNode->NameInformation.FileName,
1705 pDirNode->ObjectInformation->FileId.Cell,
1706 pDirNode->ObjectInformation->FileId.Volume,
1707 pDirNode->ObjectInformation->FileId.Vnode,
1708 pDirNode->ObjectInformation->FileId.Unique,
1709 pResultCB->DirEnum.FileId.Cell,
1710 pResultCB->DirEnum.FileId.Volume,
1711 pResultCB->DirEnum.FileId.Vnode,
1712 pResultCB->DirEnum.FileId.Unique);
1714 AFSDeleteDirEntry( ParentObjectInfo,
1720 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1722 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1723 AFS_TRACE_LEVEL_VERBOSE,
1724 "AFSNotifyFileCreate Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1726 &pDirNode->NameInformation.FileName,
1727 pDirNode->ObjectInformation->FileId.Cell,
1728 pDirNode->ObjectInformation->FileId.Volume,
1729 pDirNode->ObjectInformation->FileId.Vnode,
1730 pDirNode->ObjectInformation->FileId.Unique,
1731 pResultCB->DirEnum.FileId.Cell,
1732 pResultCB->DirEnum.FileId.Volume,
1733 pResultCB->DirEnum.FileId.Vnode,
1734 pResultCB->DirEnum.FileId.Unique);
1736 AFSRemoveNameEntry( ParentObjectInfo,
1745 // We are unsure of our current data so set the verify flag. It may already be set
1746 // but no big deal to reset it
1749 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1751 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1754 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1755 AFS_TRACE_LEVEL_VERBOSE,
1756 "AFSNotifyFileCreate Creating new entry %wZ\n",
1760 // Initialize the directory entry
1763 uniTargetName.Length = (USHORT)pResultCB->DirEnum.TargetNameLength;
1765 uniTargetName.MaximumLength = uniTargetName.Length;
1767 uniTargetName.Buffer = (WCHAR *)((char *)&pResultCB->DirEnum + pResultCB->DirEnum.TargetNameOffset);
1769 pDirNode = AFSInitDirEntry( ParentObjectInfo,
1772 &pResultCB->DirEnum,
1773 (ULONG)InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1775 if( pDirNode == NULL)
1778 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1780 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1782 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1786 // Init the short name if we have one
1789 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1790 pResultCB->DirEnum.ShortNameLength > 0)
1793 UNICODE_STRING uniShortName;
1795 pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
1797 RtlCopyMemory( pDirNode->NameInformation.ShortName,
1798 pResultCB->DirEnum.ShortName,
1799 pDirNode->NameInformation.ShortNameLength);
1802 // Generate the short name index
1805 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1806 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1808 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1811 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1812 AFS_TRACE_LEVEL_VERBOSE,
1813 "AFSNotifyFileCreate Initialized short name %wZ for DE %p for %wZ\n",
1816 &pDirNode->NameInformation.FileName);
1821 // No short name or short names are disabled
1824 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
1827 if ( !BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1831 // Update the parent data version
1834 ParentObjectInfo->DataVersion = pResultCB->ParentDataVersion;
1836 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1837 AFS_TRACE_LEVEL_VERBOSE,
1838 "AFSNotifyFileCreate entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
1840 ParentObjectInfo->FileId.Cell,
1841 ParentObjectInfo->FileId.Volume,
1842 ParentObjectInfo->FileId.Vnode,
1843 ParentObjectInfo->FileId.Unique,
1844 ParentObjectInfo->DataVersion.QuadPart);
1848 // Return the directory node
1851 *DirNode = pDirNode;
1855 if ( *DirNode != NULL)
1858 lCount = InterlockedIncrement( &(*DirNode)->DirOpenReferenceCount);
1860 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1861 AFS_TRACE_LEVEL_VERBOSE,
1862 "AFSNotifyFileCreate Increment count on %wZ DE %p Cnt %d\n",
1863 &(*DirNode)->NameInformation.FileName,
1867 ASSERT( lCount >= 0);
1870 if ( bReleaseParentTreeLock)
1873 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1876 if( pResultCB != NULL)
1879 AFSExFreePoolWithTag( pResultCB, AFS_GENERIC_MEMORY_1_TAG);
1887 AFSUpdateFileInformation( IN AFSFileID *ParentFid,
1888 IN AFSObjectInfoCB *ObjectInfo,
1892 NTSTATUS ntStatus = STATUS_SUCCESS;
1893 AFSFileUpdateCB stUpdateCB;
1894 ULONG ulResultLen = 0;
1895 AFSFileUpdateResultCB *pUpdateResultCB = NULL;
1901 // Init the control block for the request
1904 RtlZeroMemory( &stUpdateCB,
1905 sizeof( AFSFileUpdateCB));
1907 stUpdateCB.AllocationSize = ObjectInfo->EndOfFile;
1909 stUpdateCB.FileAttributes = ObjectInfo->FileAttributes;
1911 stUpdateCB.EaSize = ObjectInfo->EaSize;
1913 stUpdateCB.ParentId = *ParentFid;
1915 stUpdateCB.LastAccessTime = ObjectInfo->LastAccessTime;
1917 stUpdateCB.CreateTime = ObjectInfo->CreationTime;
1919 stUpdateCB.ChangeTime = ObjectInfo->ChangeTime;
1921 stUpdateCB.LastWriteTime = ObjectInfo->LastWriteTime;
1923 pUpdateResultCB = (AFSFileUpdateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1925 AFS_UPDATE_RESULT_TAG);
1927 if( pUpdateResultCB == NULL)
1930 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1933 ulResultLen = PAGE_SIZE;
1935 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_UPDATE_FILE,
1936 AFS_REQUEST_FLAG_SYNCHRONOUS,
1939 &ObjectInfo->FileId,
1941 sizeof( AFSFileUpdateCB),
1945 if( ntStatus != STATUS_SUCCESS)
1948 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1949 AFS_TRACE_LEVEL_ERROR,
1950 "AFSUpdateFileInformation failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1951 ObjectInfo->FileId.Cell,
1952 ObjectInfo->FileId.Volume,
1953 ObjectInfo->FileId.Vnode,
1954 ObjectInfo->FileId.Unique,
1957 try_return( ntStatus);
1961 // Update the data version
1964 AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1967 if ( !BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1970 ObjectInfo->DataVersion = pUpdateResultCB->DirEnum.DataVersion;
1973 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1977 if( pUpdateResultCB != NULL)
1980 AFSExFreePoolWithTag( pUpdateResultCB, AFS_UPDATE_RESULT_TAG);
1988 AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
1990 IN BOOLEAN CheckOnly)
1992 NTSTATUS ntStatus = STATUS_SUCCESS;
1993 ULONG ulResultLen = 0;
1994 AFSFileDeleteCB stDelete;
1995 AFSFileDeleteResultCB stDeleteResult;
1996 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1997 AFSObjectInfoCB *pObjectInfo = NULL;
1998 AFSObjectInfoCB *pParentObjectInfo = NULL;
2003 pObjectInfo = DirectoryCB->ObjectInformation;
2005 pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
2006 &pObjectInfo->ParentFileId);
2008 stDelete.ParentId = pObjectInfo->ParentFileId;
2010 stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
2012 ulResultLen = sizeof( AFSFileDeleteResultCB);
2016 ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
2019 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
2022 &DirectoryCB->NameInformation.FileName,
2023 &pObjectInfo->FileId,
2025 sizeof( AFSFileDeleteCB),
2029 if( ntStatus != STATUS_SUCCESS)
2032 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2033 AFS_TRACE_LEVEL_ERROR,
2034 "AFSNotifyDelete failed ParentFID %08lX-%08lX-%08lX-%08lX %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2035 stDelete.ParentId.Cell,
2036 stDelete.ParentId.Volume,
2037 stDelete.ParentId.Vnode,
2038 stDelete.ParentId.Unique,
2039 &DirectoryCB->NameInformation.FileName,
2040 pObjectInfo->FileId.Cell,
2041 pObjectInfo->FileId.Volume,
2042 pObjectInfo->FileId.Vnode,
2043 pObjectInfo->FileId.Unique,
2046 try_return( ntStatus);
2049 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2056 // Validate the parent data version
2059 if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
2062 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2064 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2071 // Update the parent data version
2074 if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart - 1)
2077 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2079 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2085 // TODO -- The entry must be removed from the directory at which point the
2086 // Directory data version number can be updated. Until then we must force
2089 // pParentObjectInfor->DataVersion.QuadPart = stDeleteResult.ParentDataVersion.QuadPart;
2092 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2094 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2098 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2102 if ( pParentObjectInfo)
2105 AFSReleaseObjectInfo( &pParentObjectInfo);
2114 AFSNotifyHardLink( IN AFSObjectInfoCB *ObjectInfo,
2116 IN AFSObjectInfoCB *ParentObjectInfo,
2117 IN AFSObjectInfoCB *TargetParentObjectInfo,
2118 IN AFSDirectoryCB *SourceDirectoryCB,
2119 IN UNICODE_STRING *TargetName,
2120 IN BOOLEAN bReplaceIfExists,
2121 OUT AFSDirectoryCB **TargetDirectoryCB)
2124 NTSTATUS ntStatus = STATUS_SUCCESS;
2125 AFSFileHardLinkCB *pHardLinkCB = NULL;
2126 AFSFileHardLinkResultCB *pResultCB = NULL;
2127 ULONG ulResultLen = 0;
2128 AFSDirectoryCB *pDirNode = NULL;
2130 BOOLEAN bReleaseParentLock = FALSE, bReleaseTargetParentLock = FALSE;
2131 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2138 // Init the control block for the request
2141 pHardLinkCB = (AFSFileHardLinkCB *)AFSExAllocatePoolWithTag( PagedPool,
2143 AFS_HARDLINK_REQUEST_TAG);
2145 if( pHardLinkCB == NULL)
2148 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2151 RtlZeroMemory( pHardLinkCB,
2154 pHardLinkCB->SourceParentId = ParentObjectInfo->FileId;
2156 pHardLinkCB->TargetParentId = TargetParentObjectInfo->FileId;
2158 pHardLinkCB->TargetNameLength = TargetName->Length;
2160 RtlCopyMemory( pHardLinkCB->TargetName,
2162 TargetName->Length);
2164 pHardLinkCB->bReplaceIfExists = bReplaceIfExists;
2167 // Use the same buffer for the result control block
2170 pResultCB = (AFSFileHardLinkResultCB *)pHardLinkCB;
2172 ulResultLen = PAGE_SIZE;
2174 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_HARDLINK_FILE,
2175 AFS_REQUEST_FLAG_SYNCHRONOUS,
2177 &SourceDirectoryCB->NameInformation.FileName,
2178 &ObjectInfo->FileId,
2180 sizeof( AFSFileHardLinkCB) + TargetName->Length,
2184 if( ntStatus != STATUS_SUCCESS)
2187 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2188 AFS_TRACE_LEVEL_ERROR,
2189 "AFSNotifyHardLink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2190 ObjectInfo->FileId.Cell,
2191 ObjectInfo->FileId.Volume,
2192 ObjectInfo->FileId.Vnode,
2193 ObjectInfo->FileId.Unique,
2196 try_return( ntStatus);
2200 // Update the information from the returned data
2203 if ( ParentObjectInfo != TargetParentObjectInfo)
2206 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2209 bReleaseParentLock = TRUE;
2211 if ( ParentObjectInfo->DataVersion.QuadPart == pResultCB->SourceParentDataVersion.QuadPart - 1)
2214 ParentObjectInfo->DataVersion = pResultCB->SourceParentDataVersion;
2219 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2221 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2225 AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2228 bReleaseTargetParentLock = TRUE;
2230 if ( TargetParentObjectInfo->DataVersion.QuadPart == pResultCB->TargetParentDataVersion.QuadPart - 1)
2233 TargetParentObjectInfo->DataVersion = pResultCB->TargetParentDataVersion;
2238 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2239 AFS_TRACE_LEVEL_WARNING,
2240 "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",
2242 TargetParentObjectInfo->FileId.Cell,
2243 TargetParentObjectInfo->FileId.Volume,
2244 TargetParentObjectInfo->FileId.Vnode,
2245 TargetParentObjectInfo->FileId.Unique,
2246 TargetParentObjectInfo->DataVersion.HighPart,
2247 TargetParentObjectInfo->DataVersion.LowPart,
2248 pResultCB->TargetParentDataVersion.HighPart,
2249 pResultCB->TargetParentDataVersion.LowPart);
2252 // We raced so go and lookup the directory entry in the parent
2255 ulCRC = AFSGenerateCRC( TargetName,
2258 AFSLocateCaseSensitiveDirEntry( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2262 if( pDirNode != NULL)
2265 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2266 AFS_TRACE_LEVEL_VERBOSE,
2267 "AFSNotifyHardLink Located dir entry %p for file %wZ\n",
2271 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2272 &pResultCB->DirEnum.FileId))
2275 try_return( ntStatus = STATUS_REPARSE);
2281 // We found an entry that matches the desired name but it is not the
2282 // same as the one that was created for us by the file server.
2285 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2286 AFS_TRACE_LEVEL_ERROR,
2287 "AFSNotifyHardLink Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
2290 pDirNode->ObjectInformation->FileId.Cell,
2291 pDirNode->ObjectInformation->FileId.Volume,
2292 pDirNode->ObjectInformation->FileId.Vnode,
2293 pDirNode->ObjectInformation->FileId.Unique,
2294 pResultCB->DirEnum.FileId.Cell,
2295 pResultCB->DirEnum.FileId.Volume,
2296 pResultCB->DirEnum.FileId.Vnode,
2297 pResultCB->DirEnum.FileId.Unique);
2299 if( pDirNode->DirOpenReferenceCount <= 0)
2302 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2303 AFS_TRACE_LEVEL_VERBOSE,
2304 "AFSNotifyHardLink Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2306 &pDirNode->NameInformation.FileName,
2307 pDirNode->ObjectInformation->FileId.Cell,
2308 pDirNode->ObjectInformation->FileId.Volume,
2309 pDirNode->ObjectInformation->FileId.Vnode,
2310 pDirNode->ObjectInformation->FileId.Unique,
2311 pResultCB->DirEnum.FileId.Cell,
2312 pResultCB->DirEnum.FileId.Volume,
2313 pResultCB->DirEnum.FileId.Vnode,
2314 pResultCB->DirEnum.FileId.Unique);
2316 AFSDeleteDirEntry( TargetParentObjectInfo,
2322 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2324 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2325 AFS_TRACE_LEVEL_VERBOSE,
2326 "AFSNotifyHardLink Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2328 &pDirNode->NameInformation.FileName,
2329 pDirNode->ObjectInformation->FileId.Cell,
2330 pDirNode->ObjectInformation->FileId.Volume,
2331 pDirNode->ObjectInformation->FileId.Vnode,
2332 pDirNode->ObjectInformation->FileId.Unique,
2333 pResultCB->DirEnum.FileId.Cell,
2334 pResultCB->DirEnum.FileId.Volume,
2335 pResultCB->DirEnum.FileId.Vnode,
2336 pResultCB->DirEnum.FileId.Unique);
2338 AFSRemoveNameEntry( TargetParentObjectInfo,
2347 // We are unsure of our current data so set the verify flag. It may already be set
2348 // but no big deal to reset it
2351 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2353 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2357 // Create the hard link entry
2360 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2361 AFS_TRACE_LEVEL_VERBOSE,
2362 "AFSNotifyHardLink Creating new entry %wZ\n",
2366 // Initialize the directory entry
2369 pDirNode = AFSInitDirEntry( TargetParentObjectInfo,
2372 &pResultCB->DirEnum,
2373 (ULONG)InterlockedIncrement( &TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
2375 if( pDirNode == NULL)
2378 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2380 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2382 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2386 // Init the short name if we have one
2389 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2390 pResultCB->DirEnum.ShortNameLength > 0)
2393 UNICODE_STRING uniShortName;
2395 pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
2397 RtlCopyMemory( pDirNode->NameInformation.ShortName,
2398 pResultCB->DirEnum.ShortName,
2399 pDirNode->NameInformation.ShortNameLength);
2402 // Generate the short name index
2405 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
2406 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
2408 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
2411 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2412 AFS_TRACE_LEVEL_VERBOSE,
2413 "AFSNotifyHardLink Initialized short name %wZ for DE %p for %wZ\n",
2416 &pDirNode->NameInformation.FileName);
2421 // No short name or short names are disabled
2424 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2427 if ( !BooleanFlagOn( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2431 // Update the target parent data version
2434 TargetParentObjectInfo->DataVersion = pResultCB->TargetParentDataVersion;
2436 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2437 AFS_TRACE_LEVEL_VERBOSE,
2438 "AFSNotifyHardLink entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
2440 TargetParentObjectInfo->FileId.Cell,
2441 TargetParentObjectInfo->FileId.Volume,
2442 TargetParentObjectInfo->FileId.Vnode,
2443 TargetParentObjectInfo->FileId.Unique,
2444 TargetParentObjectInfo->DataVersion.QuadPart);
2449 if ( TargetDirectoryCB != NULL)
2452 lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
2454 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2455 AFS_TRACE_LEVEL_VERBOSE,
2456 "AFSNotifyHardLink Increment count on %wZ DE %p Cnt %d\n",
2457 &pDirNode->NameInformation.FileName,
2461 ASSERT( lCount >= 0);
2463 *TargetDirectoryCB = pDirNode;
2466 if ( bReleaseTargetParentLock)
2469 AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2472 if ( bReleaseParentLock)
2475 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2478 if( pHardLinkCB != NULL)
2481 AFSExFreePoolWithTag( pHardLinkCB, AFS_HARDLINK_REQUEST_TAG);
2491 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
2493 IN AFSObjectInfoCB *ParentObjectInfo,
2494 IN AFSObjectInfoCB *TargetParentObjectInfo,
2495 IN AFSDirectoryCB *DirectoryCB,
2496 IN UNICODE_STRING *TargetName,
2497 OUT AFSFileID *UpdatedFID)
2500 NTSTATUS ntStatus = STATUS_SUCCESS;
2501 AFSFileRenameCB *pRenameCB = NULL;
2502 AFSFileRenameResultCB *pRenameResultCB = NULL;
2503 ULONG ulResultLen = 0;
2504 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2510 // Init the control block for the request
2513 pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
2515 AFS_RENAME_REQUEST_TAG);
2517 if( pRenameCB == NULL)
2520 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2523 RtlZeroMemory( pRenameCB,
2526 pRenameCB->SourceParentId = ParentObjectInfo->FileId;
2528 pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
2530 pRenameCB->TargetNameLength = TargetName->Length;
2532 RtlCopyMemory( pRenameCB->TargetName,
2534 TargetName->Length);
2537 // Use the same buffer for the result control block
2540 pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
2542 ulResultLen = PAGE_SIZE;
2544 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
2545 AFS_REQUEST_FLAG_SYNCHRONOUS,
2547 &DirectoryCB->NameInformation.FileName,
2548 &ObjectInfo->FileId,
2550 sizeof( AFSFileRenameCB) + TargetName->Length,
2554 if( ntStatus != STATUS_SUCCESS)
2557 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2558 AFS_TRACE_LEVEL_ERROR,
2559 "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2560 ObjectInfo->FileId.Cell,
2561 ObjectInfo->FileId.Volume,
2562 ObjectInfo->FileId.Vnode,
2563 ObjectInfo->FileId.Unique,
2566 try_return( ntStatus);
2570 // Update the information from the returned data
2573 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2576 if ( ParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->SourceParentDataVersion.QuadPart - 1)
2579 ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
2584 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2586 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2589 if ( ParentObjectInfo != TargetParentObjectInfo)
2592 AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2595 if ( TargetParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->TargetParentDataVersion.QuadPart - 1)
2598 TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
2603 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2605 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2610 // Move over the short name
2613 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2615 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2616 DirectoryCB->NameInformation.ShortNameLength > 0)
2619 UNICODE_STRING uniShortName;
2621 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2622 uniShortName.MaximumLength = uniShortName.Length;
2623 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2625 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2626 AFS_TRACE_LEVEL_VERBOSE,
2627 "AFSNotifyRename Update old short name %wZ for DE %p for %wZ\n",
2630 &DirectoryCB->NameInformation.FileName);
2632 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2634 RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
2635 pRenameResultCB->DirEnum.ShortName,
2636 DirectoryCB->NameInformation.ShortNameLength);
2638 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2639 uniShortName.MaximumLength = uniShortName.Length;
2640 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2642 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2643 AFS_TRACE_LEVEL_VERBOSE,
2644 "AFSNotifyRename Initialized short name %wZ for DE %p for %wZ\n",
2647 &DirectoryCB->NameInformation.FileName);
2652 UNICODE_STRING uniShortName;
2654 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2655 uniShortName.MaximumLength = uniShortName.Length;
2656 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2658 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2659 AFS_TRACE_LEVEL_VERBOSE,
2660 "AFSNotifyRename Removing old short name %wZ for DE %p for %wZ\n",
2663 &DirectoryCB->NameInformation.FileName);
2665 DirectoryCB->NameInformation.ShortNameLength = 0;
2667 DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2670 if ( ParentObjectInfo != TargetParentObjectInfo)
2673 AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2676 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2678 if( UpdatedFID != NULL)
2680 *UpdatedFID = pRenameResultCB->DirEnum.FileId;
2685 if( pRenameCB != NULL)
2688 AFSExFreePoolWithTag( pRenameCB, AFS_RENAME_REQUEST_TAG);
2696 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
2698 IN BOOLEAN FastCall,
2699 OUT AFSDirEnumEntry **DirEnumEntry)
2702 NTSTATUS ntStatus = STATUS_SUCCESS;
2703 AFSEvalTargetCB stTargetID;
2704 ULONG ulResultBufferLength;
2705 AFSFileEvalResultCB *pEvalResultCB = NULL;
2706 AFSDirEnumEntry *pDirEnumCB = NULL;
2707 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
2708 AFSObjectInfoCB *pParentObjectInfo = NULL;
2713 RtlZeroMemory( &stTargetID,
2714 sizeof( AFSEvalTargetCB));
2716 if ( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2719 pParentObjectInfo = AFSFindObjectInfo( ObjectInfo->VolumeCB,
2720 &ObjectInfo->ParentFileId);
2722 stTargetID.ParentId = ObjectInfo->ParentFileId;
2726 // Allocate our response buffer
2729 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2731 AFS_GENERIC_MEMORY_30_TAG);
2733 if( pEvalResultCB == NULL)
2736 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2740 // Call to the service to evaluate the fid
2743 ulResultBufferLength = PAGE_SIZE;
2748 ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
2751 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
2755 &ObjectInfo->FileId,
2757 sizeof( AFSEvalTargetCB),
2759 &ulResultBufferLength);
2761 if( ntStatus != STATUS_SUCCESS)
2765 // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
2769 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2772 if( pParentObjectInfo != NULL)
2775 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2778 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2780 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2782 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2786 try_return( ntStatus);
2790 // A BSOD can occur if the pEvalResultCB->FileType is FILE but the
2791 // ObjectInfo->FileType is something else. The same is true for
2792 // pDirEnumEntry->FileType is DIRECTORY. Perform a sanity check
2793 // to ensure consistency. An inconsistent pDirEnumEntry can be
2794 // produced as a result of invalid status info received from a file
2795 // server. If the types are inconsistent or if the type does not
2796 // match the implied type derived from the vnode (odd values are
2797 // directories and even values are other types), prevent the request
2798 // from completing successfully. This may prevent access to the file or
2799 // directory but will prevent a BSOD.
2802 if ( !AFSIsEqualFID( &ObjectInfo->FileId,
2803 &pEvalResultCB->DirEnum.FileId))
2806 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2809 switch ( pEvalResultCB->DirEnum.FileType)
2812 case AFS_FILE_TYPE_DIRECTORY:
2813 if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x1)
2816 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2819 if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
2820 ObjectInfo->FileType != AFS_FILE_TYPE_DIRECTORY)
2823 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2828 case AFS_FILE_TYPE_FILE:
2829 if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x0)
2832 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2835 if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
2836 ObjectInfo->FileType != AFS_FILE_TYPE_FILE)
2839 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2846 // Validate the parent data version
2849 if ( pParentObjectInfo != NULL)
2852 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2855 if ( pParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2858 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2860 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2863 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2867 // Pass back the dir enum entry
2870 if( DirEnumEntry != NULL)
2873 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2875 AFS_GENERIC_MEMORY_2_TAG);
2877 if( pDirEnumCB == NULL)
2880 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2883 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2884 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2886 *DirEnumEntry = pDirEnumCB;
2891 if ( pParentObjectInfo != NULL)
2894 AFSReleaseObjectInfo( &pParentObjectInfo);
2897 if( pEvalResultCB != NULL)
2900 AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_30_TAG);
2903 if( !NT_SUCCESS( ntStatus))
2906 if( pDirEnumCB != NULL)
2909 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_2_TAG);
2912 *DirEnumEntry = NULL;
2920 AFSEvaluateTargetByName( IN GUID *AuthGroup,
2921 IN AFSObjectInfoCB *ParentObjectInfo,
2922 IN PUNICODE_STRING SourceName,
2923 OUT AFSDirEnumEntry **DirEnumEntry)
2926 NTSTATUS ntStatus = STATUS_SUCCESS;
2927 AFSEvalTargetCB stTargetID;
2928 ULONG ulResultBufferLength;
2929 AFSFileEvalResultCB *pEvalResultCB = NULL;
2930 AFSDirEnumEntry *pDirEnumCB = NULL;
2935 stTargetID.ParentId = ParentObjectInfo->FileId;
2938 // Allocate our response buffer
2941 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2943 AFS_GENERIC_MEMORY_31_TAG);
2945 if( pEvalResultCB == NULL)
2948 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2952 // Call to the service to evaluate the fid
2955 ulResultBufferLength = PAGE_SIZE;
2957 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
2958 AFS_REQUEST_FLAG_SYNCHRONOUS,
2963 sizeof( AFSEvalTargetCB),
2965 &ulResultBufferLength);
2967 if( ntStatus != STATUS_SUCCESS)
2970 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2973 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2976 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2978 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2980 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2983 try_return( ntStatus);
2987 // Validate the parent data version
2990 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2993 if ( ParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2996 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2998 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
3001 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3004 // Pass back the dir enum entry
3007 if( DirEnumEntry != NULL)
3010 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
3012 AFS_GENERIC_MEMORY_3_TAG);
3014 if( pDirEnumCB == NULL)
3017 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3020 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
3021 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
3023 *DirEnumEntry = pDirEnumCB;
3028 if( pEvalResultCB != NULL)
3031 AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_31_TAG);
3034 if( !NT_SUCCESS( ntStatus))
3037 if( pDirEnumCB != NULL)
3040 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_3_TAG);
3043 *DirEnumEntry = NULL;
3051 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
3052 IN AFSFileID *FileID,
3053 OUT AFSVolumeInfoCB *VolumeInformation)
3056 NTSTATUS ntStatus = STATUS_SUCCESS;
3057 ULONG ulResultLen = 0;
3062 ulResultLen = sizeof( AFSVolumeInfoCB);
3064 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
3065 AFS_REQUEST_FLAG_SYNCHRONOUS,
3074 if( ntStatus != STATUS_SUCCESS)
3077 try_return( ntStatus);
3089 AFSRetrieveVolumeSizeInformation( IN GUID *AuthGroup,
3090 IN AFSFileID *FileID,
3091 OUT AFSVolumeSizeInfoCB *VolumeSizeInformation)
3094 NTSTATUS ntStatus = STATUS_SUCCESS;
3095 ULONG ulResultLen = 0;
3100 ulResultLen = sizeof( AFSVolumeSizeInfoCB);
3102 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_SIZE_INFO,
3103 AFS_REQUEST_FLAG_SYNCHRONOUS,
3109 VolumeSizeInformation,
3112 if( ntStatus != STATUS_SUCCESS)
3115 try_return( ntStatus);
3127 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
3128 IN ULONG InputLength,
3129 IN ULONG OutputLength,
3130 IN void *InputDataBuffer,
3131 OUT void *OutputDataBuffer,
3132 OUT ULONG *BytesReturned)
3135 NTSTATUS ntStatus = STATUS_SUCCESS;
3136 ULONG ulResultLen = 0;
3137 MDL *pInputMdl = NULL, *pOutputMdl = NULL;
3138 void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
3139 AFSPipeIORequestCB *pIoRequest = NULL;
3145 // Map the user buffer to a system address
3148 pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
3152 if( pInputSystemBuffer == NULL)
3155 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3158 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
3159 sizeof( AFSPipeIORequestCB) +
3161 AFS_GENERIC_MEMORY_4_TAG);
3163 if( pIoRequest == NULL)
3166 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3169 RtlZeroMemory( pIoRequest,
3170 sizeof( AFSPipeIORequestCB) + InputLength);
3172 pIoRequest->RequestId = Ccb->RequestID;
3174 pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3176 pIoRequest->BufferLength = InputLength;
3178 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
3182 pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
3186 if( pOutputSystemBuffer == NULL)
3189 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3193 // Send the call to the service
3196 ulResultLen = OutputLength;
3198 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
3199 AFS_REQUEST_FLAG_SYNCHRONOUS,
3201 &Ccb->DirectoryCB->NameInformation.FileName,
3204 sizeof( AFSPipeIORequestCB) + InputLength,
3205 pOutputSystemBuffer,
3208 if( ntStatus != STATUS_SUCCESS &&
3209 ntStatus != STATUS_BUFFER_OVERFLOW)
3212 if( NT_SUCCESS( ntStatus))
3215 ntStatus = STATUS_DEVICE_NOT_READY;
3218 try_return( ntStatus);
3222 // Return the bytes processed
3225 *BytesReturned = ulResultLen;
3229 if( pInputMdl != NULL)
3232 MmUnlockPages( pInputMdl);
3234 IoFreeMdl( pInputMdl);
3237 if( pOutputMdl != NULL)
3240 MmUnlockPages( pOutputMdl);
3242 IoFreeMdl( pOutputMdl);
3245 if( pIoRequest != NULL)
3248 AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_4_TAG);
3256 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
3257 IN ULONG InformationClass,
3258 IN ULONG InputLength,
3259 IN void *DataBuffer)
3262 NTSTATUS ntStatus = STATUS_SUCCESS;
3263 AFSPipeInfoRequestCB *pInfoRequest = NULL;
3268 pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
3269 sizeof( AFSPipeInfoRequestCB) +
3271 AFS_GENERIC_MEMORY_5_TAG);
3273 if( pInfoRequest == NULL)
3276 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3279 RtlZeroMemory( pInfoRequest,
3280 sizeof( AFSPipeInfoRequestCB) + InputLength);
3282 pInfoRequest->RequestId = Ccb->RequestID;
3284 pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3286 pInfoRequest->BufferLength = InputLength;
3288 pInfoRequest->InformationClass = InformationClass;
3290 RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
3295 // Send the call to the service
3298 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
3299 AFS_REQUEST_FLAG_SYNCHRONOUS,
3301 &Ccb->DirectoryCB->NameInformation.FileName,
3304 sizeof( AFSPipeInfoRequestCB) + InputLength,
3308 if( ntStatus != STATUS_SUCCESS)
3311 if( NT_SUCCESS( ntStatus))
3314 ntStatus = STATUS_DEVICE_NOT_READY;
3317 try_return( ntStatus);
3322 if( pInfoRequest != NULL)
3325 AFSExFreePoolWithTag( pInfoRequest, AFS_GENERIC_MEMORY_5_TAG);
3333 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
3334 IN ULONG InformationClass,
3335 IN ULONG OutputLength,
3336 IN void *DataBuffer,
3337 OUT ULONG *BytesReturned)
3340 NTSTATUS ntStatus = STATUS_SUCCESS;
3341 AFSPipeInfoRequestCB stInfoRequest;
3342 ULONG ulBytesProcessed = 0;
3347 RtlZeroMemory( &stInfoRequest,
3348 sizeof( AFSPipeInfoRequestCB));
3350 stInfoRequest.RequestId = Ccb->RequestID;
3352 stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3354 stInfoRequest.BufferLength = OutputLength;
3356 stInfoRequest.InformationClass = InformationClass;
3358 ulBytesProcessed = OutputLength;
3361 // Send the call to the service
3364 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
3365 AFS_REQUEST_FLAG_SYNCHRONOUS,
3367 &Ccb->DirectoryCB->NameInformation.FileName,
3370 sizeof( AFSPipeInfoRequestCB),
3374 if( ntStatus != STATUS_SUCCESS)
3377 if( NT_SUCCESS( ntStatus))
3380 ntStatus = STATUS_DEVICE_NOT_READY;
3383 try_return( ntStatus);
3386 *BytesReturned = ulBytesProcessed;
3397 AFSReleaseFid( IN AFSFileID *FileId)
3400 NTSTATUS ntStatus = STATUS_SUCCESS;
3405 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
3420 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
3421 IN LARGE_INTEGER *ExtentOffset,
3425 BOOLEAN bRequestQueued = FALSE;
3426 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3427 AFSCommSrvcCB *pCommSrvc = NULL;
3428 AFSPoolEntry *pPoolEntry = NULL;
3429 AFSRequestExtentsCB *pRequestExtents = NULL;
3435 pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
3437 AFSAcquireShared( &pCommSrvc->IrpPoolLock,
3440 pPoolEntry = pCommSrvc->RequestPoolHead;
3442 while( pPoolEntry != NULL)
3445 if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
3448 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
3451 pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
3453 if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
3454 pRequestExtents->Length == Length)
3457 bRequestQueued = TRUE;
3462 pPoolEntry = pPoolEntry->fLink;
3465 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
3468 return bRequestQueued;