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,
151 ObjectInfoCB->VolumeCB->VolumeInformation.Cell,
152 ObjectInfoCB->VolumeCB->VolumeInformation.CellLength,
154 sizeof( AFSDirQueryCB),
159 if( ntStatus != STATUS_SUCCESS ||
163 if( ntStatus == STATUS_NO_MORE_FILES ||
164 ntStatus == STATUS_NO_MORE_ENTRIES)
167 ntStatus = STATUS_SUCCESS;
169 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
171 AFSAcquireExcl( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock,
174 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
175 AFS_TRACE_LEVEL_VERBOSE,
176 "AFSEnumerateDirectory Directory Complete FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX Status %08lX\n",
177 ObjectInfoCB->FileId.Cell,
178 ObjectInfoCB->FileId.Volume,
179 ObjectInfoCB->FileId.Vnode,
180 ObjectInfoCB->FileId.Unique,
181 pDirEnumResponse->SnapshotDataVersion.HighPart,
182 pDirEnumResponse->SnapshotDataVersion.LowPart,
183 pDirEnumResponse->CurrentDataVersion.HighPart,
184 pDirEnumResponse->CurrentDataVersion.LowPart,
187 ObjectInfoCB->DataVersion = pDirEnumResponse->SnapshotDataVersion;
189 if ( pDirEnumResponse->SnapshotDataVersion.QuadPart != pDirEnumResponse->CurrentDataVersion.QuadPart )
192 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
194 ObjectInfoCB->DataVersion.QuadPart = (ULONGLONG)-1;
196 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
197 AFS_TRACE_LEVEL_VERBOSE,
198 "AFSEnumerateDirectory Force Verify due to DV change during enumeration FID %08lX-%08lX-%08lX-%08lX\n",
199 ObjectInfoCB->FileId.Cell,
200 ObjectInfoCB->FileId.Volume,
201 ObjectInfoCB->FileId.Vnode,
202 ObjectInfoCB->FileId.Unique);
205 AFSReleaseResource( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock);
210 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
211 AFS_TRACE_LEVEL_VERBOSE,
212 "AFSEnumerateDirectory Failed to enumerate directory FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ Status %08lX\n",
213 ObjectInfoCB->FileId.Cell,
214 ObjectInfoCB->FileId.Volume,
215 ObjectInfoCB->FileId.Vnode,
216 ObjectInfoCB->FileId.Unique,
224 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
226 pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
228 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
229 AFS_TRACE_LEVEL_VERBOSE,
230 "AFSEnumerateDirectory Enumerating FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX\n",
231 ObjectInfoCB->FileId.Cell,
232 ObjectInfoCB->FileId.Volume,
233 ObjectInfoCB->FileId.Vnode,
234 ObjectInfoCB->FileId.Unique,
235 pDirEnumResponse->SnapshotDataVersion.HighPart,
236 pDirEnumResponse->SnapshotDataVersion.LowPart,
237 pDirEnumResponse->CurrentDataVersion.HighPart,
238 pDirEnumResponse->CurrentDataVersion.LowPart);
241 // Remove the leading header from the processed length
244 ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
246 while( ulResultLen > 0)
249 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
251 uniDirName.MaximumLength = uniDirName.Length;
253 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
255 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
257 uniTargetName.MaximumLength = uniTargetName.Length;
259 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
262 // Be sure we don't have this entry in the case sensitive tree
265 ulCRC = AFSGenerateCRC( &uniDirName,
268 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
272 if( pDirNode != NULL)
276 // Check that the FIDs are the same
279 if( AFSIsEqualFID( &pCurrentDirEntry->FileId,
280 &pDirNode->ObjectInformation->FileId))
284 // Duplicate entry, skip it
287 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
289 uniTargetName.Length);
291 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
293 if( ulResultLen >= ulEntryLength)
295 ulResultLen -= ulEntryLength;
303 // Update the metadata for the entry
306 if( pDirNode->ObjectInformation->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
310 AFSObjectInfoCB *pObjectInfo = pDirNode->ObjectInformation;
313 // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
316 lCount = AFSObjectInfoIncrement( pObjectInfo,
317 AFS_OBJECT_REFERENCE_INVALIDATION);
319 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
320 AFS_TRACE_LEVEL_VERBOSE,
321 "AFSEnumerateDirectory calling AFSPerformObjectInvalidate Increment count on object %p Cnt %d\n",
325 AFSPerformObjectInvalidate( pObjectInfo,
326 AFS_INVALIDATE_DATA_VERSION);
331 AFSUpdateMetaData( pDirNode,
341 // Need to tear down this entry and rebuild it below
344 if( pDirNode->DirOpenReferenceCount <= 0)
347 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
348 AFS_TRACE_LEVEL_VERBOSE,
349 "AFSEnumerateDirectory Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
351 &pDirNode->NameInformation.FileName,
352 pDirNode->ObjectInformation->FileId.Cell,
353 pDirNode->ObjectInformation->FileId.Volume,
354 pDirNode->ObjectInformation->FileId.Vnode,
355 pDirNode->ObjectInformation->FileId.Unique,
356 pCurrentDirEntry->FileId.Cell,
357 pCurrentDirEntry->FileId.Volume,
358 pCurrentDirEntry->FileId.Vnode,
359 pCurrentDirEntry->FileId.Unique);
361 AFSDeleteDirEntry( ObjectInfoCB,
367 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
369 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
370 AFS_TRACE_LEVEL_VERBOSE,
371 "AFSEnumerateDirectory Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
373 &pDirNode->NameInformation.FileName,
374 pDirNode->ObjectInformation->FileId.Cell,
375 pDirNode->ObjectInformation->FileId.Volume,
376 pDirNode->ObjectInformation->FileId.Vnode,
377 pDirNode->ObjectInformation->FileId.Unique,
378 pCurrentDirEntry->FileId.Cell,
379 pCurrentDirEntry->FileId.Volume,
380 pCurrentDirEntry->FileId.Vnode,
381 pCurrentDirEntry->FileId.Unique);
383 AFSRemoveNameEntry( ObjectInfoCB,
391 pDirNode = AFSInitDirEntry( ObjectInfoCB,
395 (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
397 if( pDirNode == NULL)
400 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
405 AFSUpdateMetaData( pDirNode,
408 if( pDirNode->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
411 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
412 AFS_TRACE_LEVEL_VERBOSE,
413 "AFSEnumerateDirectory Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
415 pDirNode->ObjectInformation->FileId.Cell,
416 pDirNode->ObjectInformation->FileId.Volume,
417 pDirNode->ObjectInformation->FileId.Vnode,
418 pDirNode->ObjectInformation->FileId.Unique);
420 AFSAcquireExcl( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
423 SetFlag( pDirNode->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
425 pDirNode->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
427 AFSReleaseResource( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
431 // Set up the entry length
434 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
435 pCurrentDirEntry->FileNameLength +
436 pCurrentDirEntry->TargetNameLength);
439 // Init the short name if we have one
442 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
443 pCurrentDirEntry->ShortNameLength > 0)
446 UNICODE_STRING uniShortName;
448 pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
450 RtlCopyMemory( pDirNode->NameInformation.ShortName,
451 pCurrentDirEntry->ShortName,
452 pDirNode->NameInformation.ShortNameLength);
455 // Generate the short name index
458 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
459 uniShortName.MaximumLength = uniShortName.Length;
460 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
462 if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
467 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
470 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
471 AFS_TRACE_LEVEL_VERBOSE,
472 "AFSEnumerateDirectory Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
475 &pDirNode->NameInformation.FileName,
476 pCurrentDirEntry->FileId.Cell,
477 pCurrentDirEntry->FileId.Volume,
478 pCurrentDirEntry->FileId.Vnode,
479 pCurrentDirEntry->FileId.Unique);
483 pDirNode->NameInformation.ShortNameLength = 0;
485 RtlZeroMemory( pDirNode->NameInformation.ShortName,
486 (12 * sizeof( WCHAR)));
493 // No short name or short names are disabled
496 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
500 // Insert the node into the name tree
503 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
506 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
508 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
509 AFS_TRACE_LEVEL_VERBOSE,
510 "AFSEnumerateDirectory Insert DE %p to head of case sensitive tree for %wZ\n",
512 &pDirNode->NameInformation.FileName);
517 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
518 AFS_TRACE_LEVEL_VERBOSE,
519 "AFSEnumerateDirectory Insert DE %p to case sensitive tree for %wZ\n",
521 &pDirNode->NameInformation.FileName);
523 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
528 // Delete this dir entry and continue on
531 AFSDeleteDirEntry( ObjectInfoCB,
534 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
536 if( ulResultLen >= ulEntryLength)
538 ulResultLen -= ulEntryLength;
549 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
551 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
554 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
555 AFS_TRACE_LEVEL_VERBOSE,
556 "AFSEnumerateDirectory Insert DE %p to head of case insensitive tree for %wZ\n",
558 &pDirNode->NameInformation.FileName);
560 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
562 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
567 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
568 AFS_TRACE_LEVEL_VERBOSE,
569 "AFSEnumerateDirectory Insert DE %p to case insensitive tree for %wZ\n",
571 &pDirNode->NameInformation.FileName);
573 AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
577 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
580 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
585 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
587 pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
590 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
592 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
594 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
596 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
597 AFS_TRACE_LEVEL_VERBOSE,
598 "AFSEnumerateDirectory Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
599 &pDirNode->NameInformation.FileName,
600 ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
601 ObjectInfoCB->FileId.Cell,
602 ObjectInfoCB->FileId.Volume,
603 ObjectInfoCB->FileId.Vnode,
604 ObjectInfoCB->FileId.Unique);
606 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
610 // Insert the short name entry if we have a valid short name
613 if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
616 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
617 AFS_TRACE_LEVEL_VERBOSE,
618 "AFSEnumerateDirectory Insert DE %p to head of shortname tree for %wZ\n",
620 &pDirNode->NameInformation.FileName);
622 ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
624 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
629 if( NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
632 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
634 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
635 AFS_TRACE_LEVEL_VERBOSE,
636 "AFSEnumerateDirectory Insert DE %p to shortname tree for %wZ\n",
638 &pDirNode->NameInformation.FileName);
647 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
649 if( ulResultLen >= ulEntryLength)
651 ulResultLen -= ulEntryLength;
659 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
662 // Reset the information in the request buffer since it got trampled
666 pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
668 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
669 AFS_TRACE_LEVEL_VERBOSE,
670 "AFSEnumerateDirectory EnumHandle %08lX\n",
671 pDirQueryCB->EnumHandle);
683 AFSExFreePoolWithTag( pBuffer, AFS_DIR_BUFFER_TAG);
687 // If the processing failed then we should reset the directory content in the event
688 // it is re-enumerated
691 if( !NT_SUCCESS( ntStatus))
694 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
695 AFS_TRACE_LEVEL_ERROR,
696 "AFSEnumerateDirectory Resetting content for FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
697 ObjectInfoCB->FileId.Cell,
698 ObjectInfoCB->FileId.Volume,
699 ObjectInfoCB->FileId.Vnode,
700 ObjectInfoCB->FileId.Unique,
703 AFSResetDirectoryContent( ObjectInfoCB);
711 AFSEnumerateDirectoryNoResponse( IN GUID *AuthGroup,
712 IN AFSFileID *FileId)
715 NTSTATUS ntStatus = STATUS_SUCCESS;
716 AFSDirQueryCB stDirQueryCB;
717 ULONG ulRequestFlags = 0;
723 // Use the payload buffer for information we will pass to the service
726 stDirQueryCB.EnumHandle = 0;
728 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
735 (void *)&stDirQueryCB,
736 sizeof( AFSDirQueryCB),
740 if( ntStatus != STATUS_SUCCESS)
743 if( ntStatus == STATUS_NO_MORE_FILES ||
744 ntStatus == STATUS_NO_MORE_ENTRIES)
747 ntStatus = STATUS_SUCCESS;
752 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
753 AFS_TRACE_LEVEL_ERROR,
754 "AFSEnumerateDirectoryNoResponse Failed to enumerate directory Status %08lX\n",
764 AFSVerifyDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB,
768 NTSTATUS ntStatus = STATUS_SUCCESS;
769 void *pBuffer = NULL;
770 ULONG ulResultLen = 0;
771 AFSDirQueryCB *pDirQueryCB;
772 AFSDirEnumEntry *pCurrentDirEntry = NULL;
773 AFSDirectoryCB *pDirNode = NULL;
774 ULONG ulEntryLength = 0;
775 AFSDirEnumResp *pDirEnumResponse = NULL;
776 UNICODE_STRING uniDirName, uniTargetName;
777 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_FAST_REQUEST;
779 AFSObjectInfoCB *pObjectInfo = NULL;
780 ULONGLONG ullIndex = 0;
781 UNICODE_STRING uniGUID;
783 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
788 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
791 uniGUID.MaximumLength = 0;
792 uniGUID.Buffer = NULL;
794 if( AuthGroup != NULL)
796 RtlStringFromGUID( *AuthGroup,
800 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
801 AFS_TRACE_LEVEL_VERBOSE,
802 "AFSVerifyDirectoryContent Verifying content for FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
803 ObjectInfoCB->FileId.Cell,
804 ObjectInfoCB->FileId.Volume,
805 ObjectInfoCB->FileId.Vnode,
806 ObjectInfoCB->FileId.Unique,
809 if( AuthGroup != NULL)
811 RtlFreeUnicodeString( &uniGUID);
815 // Initialize the directory enumeration buffer for the directory
818 pBuffer = AFSExAllocatePoolWithTag( PagedPool,
819 AFS_DIR_ENUM_BUFFER_LEN,
825 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
828 RtlZeroMemory( pBuffer,
829 AFS_DIR_ENUM_BUFFER_LEN);
831 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
834 // Use the payload buffer for information we will pass to the service
837 pDirQueryCB = (AFSDirQueryCB *)pBuffer;
839 pDirQueryCB->EnumHandle = 0;
842 // Loop on the information
849 // If the enumeration handle is -1 then we are done
852 if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
855 ntStatus = STATUS_NO_MORE_ENTRIES;
861 // Go and retrieve the directory contents
864 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
868 &ObjectInfoCB->FileId,
869 ObjectInfoCB->VolumeCB->VolumeInformation.Cell,
870 ObjectInfoCB->VolumeCB->VolumeInformation.CellLength,
872 sizeof( AFSDirQueryCB),
877 if( ntStatus != STATUS_SUCCESS ||
881 if( ntStatus == STATUS_NO_MORE_FILES ||
882 ntStatus == STATUS_NO_MORE_ENTRIES)
885 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
887 AFSAcquireExcl( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock,
890 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
891 AFS_TRACE_LEVEL_VERBOSE,
892 "AFSVerifyDirectoryContent Directory Complete FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX Status %08lX\n",
893 ObjectInfoCB->FileId.Cell,
894 ObjectInfoCB->FileId.Volume,
895 ObjectInfoCB->FileId.Vnode,
896 ObjectInfoCB->FileId.Unique,
897 pDirEnumResponse->SnapshotDataVersion.HighPart,
898 pDirEnumResponse->SnapshotDataVersion.LowPart,
899 pDirEnumResponse->CurrentDataVersion.HighPart,
900 pDirEnumResponse->CurrentDataVersion.LowPart,
903 ntStatus = STATUS_SUCCESS;
905 if ( pDirEnumResponse->SnapshotDataVersion.QuadPart != pDirEnumResponse->CurrentDataVersion.QuadPart )
908 SetFlag( ObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
910 ObjectInfoCB->DataVersion.QuadPart = (ULONGLONG)-1;
912 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
913 AFS_TRACE_LEVEL_VERBOSE,
914 "AFSVerifyDirectoryContent Force Verify due to DV change during enumeration FID %08lX-%08lX-%08lX-%08lX\n",
915 ObjectInfoCB->FileId.Cell,
916 ObjectInfoCB->FileId.Volume,
917 ObjectInfoCB->FileId.Vnode,
918 ObjectInfoCB->FileId.Unique);
923 ObjectInfoCB->DataVersion = pDirEnumResponse->SnapshotDataVersion;
926 AFSReleaseResource( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock);
931 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
932 AFS_TRACE_LEVEL_ERROR,
933 "AFSVerifyDirectoryContent Failed to enumerate directory FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ Status %08lX\n",
934 ObjectInfoCB->FileId.Cell,
935 ObjectInfoCB->FileId.Volume,
936 ObjectInfoCB->FileId.Vnode,
937 ObjectInfoCB->FileId.Unique,
945 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
947 pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
949 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
950 AFS_TRACE_LEVEL_VERBOSE,
951 "AFSVerifyDirectoryContent EnumResponse FID %08lX-%08lX-%08lX-%08lX Snapshot-DV %08lX:%08lX Current-DV %08lX:%08lX\n",
952 ObjectInfoCB->FileId.Cell,
953 ObjectInfoCB->FileId.Volume,
954 ObjectInfoCB->FileId.Vnode,
955 ObjectInfoCB->FileId.Unique,
956 pDirEnumResponse->SnapshotDataVersion.HighPart,
957 pDirEnumResponse->SnapshotDataVersion.LowPart,
958 pDirEnumResponse->CurrentDataVersion.HighPart,
959 pDirEnumResponse->CurrentDataVersion.LowPart);
962 // Remove the leading header from the processed length
965 ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
967 while( ulResultLen > 0)
970 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
972 uniDirName.MaximumLength = uniDirName.Length;
974 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
976 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
978 uniTargetName.MaximumLength = uniTargetName.Length;
980 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
983 // Does this entry already exist in the directory?
986 ulCRC = AFSGenerateCRC( &uniDirName,
989 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
995 // Set up the entry length
998 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
999 pCurrentDirEntry->FileNameLength +
1000 pCurrentDirEntry->TargetNameLength);
1003 AFSIsEqualFID( &pCurrentDirEntry->FileId,
1004 &pDirNode->ObjectInformation->FileId))
1008 // Found matching directory entry by name and FileID
1011 AFSAcquireShared( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock,
1014 ullIndex = AFSCreateLowIndex( &pCurrentDirEntry->FileId);
1016 ntStatus = AFSLocateHashEntry( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeHead,
1018 (AFSBTreeEntry **)&pObjectInfo);
1020 AFSReleaseResource( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock);
1022 if( NT_SUCCESS( ntStatus) &&
1023 pObjectInfo != NULL)
1027 // Indicate this is a valid entry
1030 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
1032 if( pCurrentDirEntry->ShortNameLength > 0 &&
1033 pDirNode->NameInformation.ShortNameLength > 0)
1035 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1036 AFS_TRACE_LEVEL_VERBOSE,
1037 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name %S New short name %S\n",
1039 &pDirNode->NameInformation.FileName,
1040 ObjectInfoCB->FileId.Cell,
1041 ObjectInfoCB->FileId.Volume,
1042 ObjectInfoCB->FileId.Vnode,
1043 ObjectInfoCB->FileId.Unique,
1044 pDirNode->NameInformation.ShortName,
1045 pCurrentDirEntry->ShortName);
1047 else if( pCurrentDirEntry->ShortNameLength == 0 &&
1048 pDirNode->NameInformation.ShortNameLength > 0)
1051 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1052 AFS_TRACE_LEVEL_VERBOSE,
1053 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name %S New short name NULL\n",
1055 &pDirNode->NameInformation.FileName,
1056 ObjectInfoCB->FileId.Cell,
1057 ObjectInfoCB->FileId.Volume,
1058 ObjectInfoCB->FileId.Vnode,
1059 ObjectInfoCB->FileId.Unique,
1060 pDirNode->NameInformation.ShortName);
1062 else if( pCurrentDirEntry->ShortNameLength > 0 &&
1063 pDirNode->NameInformation.ShortNameLength == 0)
1065 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1066 AFS_TRACE_LEVEL_VERBOSE,
1067 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name %S\n",
1069 &pDirNode->NameInformation.FileName,
1070 ObjectInfoCB->FileId.Cell,
1071 ObjectInfoCB->FileId.Volume,
1072 ObjectInfoCB->FileId.Vnode,
1073 ObjectInfoCB->FileId.Unique,
1074 pCurrentDirEntry->ShortName);
1078 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1079 AFS_TRACE_LEVEL_VERBOSE,
1080 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) parent FID %08lX-%08lX-%08lX-%08lX old short name NULL New short name NULL\n",
1082 &pDirNode->NameInformation.FileName,
1083 ObjectInfoCB->FileId.Cell,
1084 ObjectInfoCB->FileId.Volume,
1085 ObjectInfoCB->FileId.Vnode,
1086 ObjectInfoCB->FileId.Unique);
1090 // Update the metadata for the entry
1093 if( pObjectInfo->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
1097 // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
1098 // if successfully queued. Cannot call AFSPerformObjectInvalidate directly
1099 // because ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock is
1100 // held during the sequence AFSVerifyEntry->AFSValidateDirectoryCache->
1101 // AFSVerifyDirectoryContent and AFSPerformObjectInvalidate requires the
1102 // Fcb->NPFcb->Resource which must be held prior to the TreeLock in the
1106 lCount = AFSObjectInfoIncrement( pObjectInfo,
1107 AFS_OBJECT_REFERENCE_INVALIDATION);
1109 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1110 AFS_TRACE_LEVEL_VERBOSE,
1111 "AFSVerifyDirectoryContent calling AFSQueueInvalidateObject Increment count on object %p Cnt %d\n",
1115 if ( !NT_SUCCESS( AFSQueueInvalidateObject( pObjectInfo,
1116 AFS_INVALIDATE_DATA_VERSION)))
1119 lCount = AFSObjectInfoDecrement( pObjectInfo,
1120 AFS_OBJECT_REFERENCE_INVALIDATION);
1122 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1123 AFS_TRACE_LEVEL_VERBOSE,
1124 "AFSVerifyDirectoryContent AFSQueueInvalidateObject failed Decrement count on object %p Cnt %d\n",
1132 AFSUpdateMetaData( pDirNode,
1140 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1142 if( ulResultLen >= ulEntryLength)
1144 ulResultLen -= ulEntryLength;
1158 // File name matches but FileID does not.
1161 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1162 AFS_TRACE_LEVEL_VERBOSE,
1163 "AFSVerifyDirectoryContent Processing dir entry %p %wZ with different FID, same name in parent FID %08lX-%08lX-%08lX-%08lX\n",
1165 &pDirNode->NameInformation.FileName,
1166 ObjectInfoCB->FileId.Cell,
1167 ObjectInfoCB->FileId.Volume,
1168 ObjectInfoCB->FileId.Vnode,
1169 ObjectInfoCB->FileId.Unique);
1172 // Need to tear down this entry and rebuild it below
1175 if( pDirNode->DirOpenReferenceCount <= 0)
1178 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1179 AFS_TRACE_LEVEL_VERBOSE,
1180 "AFSVerifyDirectoryContent Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1182 &pDirNode->NameInformation.FileName,
1183 pDirNode->ObjectInformation->FileId.Cell,
1184 pDirNode->ObjectInformation->FileId.Volume,
1185 pDirNode->ObjectInformation->FileId.Vnode,
1186 pDirNode->ObjectInformation->FileId.Unique,
1187 pCurrentDirEntry->FileId.Cell,
1188 pCurrentDirEntry->FileId.Volume,
1189 pCurrentDirEntry->FileId.Vnode,
1190 pCurrentDirEntry->FileId.Unique);
1192 AFSDeleteDirEntry( ObjectInfoCB,
1198 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1200 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1201 AFS_TRACE_LEVEL_WARNING,
1202 "AFSVerifyDirectoryContent Different FIDs - removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1204 &pDirNode->NameInformation.FileName,
1205 pDirNode->ObjectInformation->FileId.Cell,
1206 pDirNode->ObjectInformation->FileId.Volume,
1207 pDirNode->ObjectInformation->FileId.Vnode,
1208 pDirNode->ObjectInformation->FileId.Unique,
1209 pCurrentDirEntry->FileId.Cell,
1210 pCurrentDirEntry->FileId.Volume,
1211 pCurrentDirEntry->FileId.Vnode,
1212 pCurrentDirEntry->FileId.Unique);
1214 AFSRemoveNameEntry( ObjectInfoCB,
1221 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1222 AFS_TRACE_LEVEL_VERBOSE,
1223 "AFSVerifyDirectoryContent New entry %wZ for parent FID %08lX-%08lX-%08lX-%08lX\n",
1225 ObjectInfoCB->FileId.Cell,
1226 ObjectInfoCB->FileId.Volume,
1227 ObjectInfoCB->FileId.Vnode,
1228 ObjectInfoCB->FileId.Unique);
1231 pDirNode = AFSInitDirEntry( ObjectInfoCB,
1235 (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1237 if( pDirNode == NULL)
1240 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
1245 AFSUpdateMetaData( pDirNode,
1248 if( pDirNode->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1251 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1252 AFS_TRACE_LEVEL_VERBOSE,
1253 "AFSVerifyDirectoryContent Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
1255 pDirNode->ObjectInformation->FileId.Cell,
1256 pDirNode->ObjectInformation->FileId.Volume,
1257 pDirNode->ObjectInformation->FileId.Vnode,
1258 pDirNode->ObjectInformation->FileId.Unique);
1260 AFSAcquireExcl( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1263 SetFlag( pDirNode->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1265 pDirNode->ObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1267 AFSReleaseResource( pDirNode->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1271 // Init the short name if we have one
1274 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1275 pCurrentDirEntry->ShortNameLength > 0)
1278 UNICODE_STRING uniShortName;
1280 pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
1282 RtlCopyMemory( pDirNode->NameInformation.ShortName,
1283 pCurrentDirEntry->ShortName,
1284 pDirNode->NameInformation.ShortNameLength);
1287 // Generate the short name index
1290 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1291 uniShortName.MaximumLength = uniShortName.Length;
1292 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1294 if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
1299 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1302 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1303 AFS_TRACE_LEVEL_VERBOSE,
1304 "AFSVerifyDirectoryContent Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1307 &pDirNode->NameInformation.FileName,
1308 pCurrentDirEntry->FileId.Cell,
1309 pCurrentDirEntry->FileId.Volume,
1310 pCurrentDirEntry->FileId.Vnode,
1311 pCurrentDirEntry->FileId.Unique);
1315 pDirNode->NameInformation.ShortNameLength = 0;
1317 RtlZeroMemory( pDirNode->NameInformation.ShortName,
1318 (12 * sizeof( WCHAR)));
1325 // No short name or short names have been disabled
1328 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
1332 // Insert the node into the name tree
1335 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
1337 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
1340 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
1342 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1343 AFS_TRACE_LEVEL_VERBOSE,
1344 "AFSVerifyDirectoryContent Insert DE %p to head of case sensitive tree for %wZ\n",
1346 &pDirNode->NameInformation.FileName);
1351 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1354 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1355 AFS_TRACE_LEVEL_VERBOSE,
1356 "AFSVerifyDirectoryContent Failed to insert DE %p to case sensitive tree for %wZ\n",
1358 &pDirNode->NameInformation.FileName);
1361 // Delete this dir entry and continue on
1364 AFSDeleteDirEntry( ObjectInfoCB,
1367 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1369 if( ulResultLen >= ulEntryLength)
1371 ulResultLen -= ulEntryLength;
1382 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1383 AFS_TRACE_LEVEL_VERBOSE,
1384 "AFSVerifyDirectoryContent Insert DE %p to case sensitive tree for %wZ\n",
1386 &pDirNode->NameInformation.FileName);
1390 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1392 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
1395 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
1397 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
1399 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1400 AFS_TRACE_LEVEL_VERBOSE,
1401 "AFSVerifyDirectoryContent Insert DE %p to head of case insensitive tree for %wZ\n",
1403 &pDirNode->NameInformation.FileName);
1408 AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1411 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1412 AFS_TRACE_LEVEL_VERBOSE,
1413 "AFSVerifyDirectoryContent Insert DE %p to case insensitive tree for %wZ\n",
1415 &pDirNode->NameInformation.FileName);
1418 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
1421 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
1426 (ObjectInfoCB->Specific.Directory.DirectoryNodeListTail)->ListEntry.fLink = pDirNode;
1428 pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
1431 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
1433 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
1435 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
1437 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1438 AFS_TRACE_LEVEL_VERBOSE,
1439 "AFSVerifyDirectoryContent Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
1440 &pDirNode->NameInformation.FileName,
1441 ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
1442 ObjectInfoCB->FileId.Cell,
1443 ObjectInfoCB->FileId.Volume,
1444 ObjectInfoCB->FileId.Vnode,
1445 ObjectInfoCB->FileId.Unique);
1447 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
1451 // Insert the short name entry if we have a valid short name
1454 if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
1457 ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
1459 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1460 AFS_TRACE_LEVEL_VERBOSE,
1461 "AFSVerifyDirectoryContent Insert DE %p to head of shortname tree for %wZ\n",
1463 &pDirNode->NameInformation.FileName);
1465 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1470 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
1473 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1474 AFS_TRACE_LEVEL_VERBOSE,
1475 "AFSVerifyDirectoryContent Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
1477 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex,
1478 &pDirNode->NameInformation.FileName);
1482 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1484 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1485 AFS_TRACE_LEVEL_VERBOSE,
1486 "AFSVerifyDirectoryContent Insert DE %p to shortname tree for %wZ\n",
1488 &pDirNode->NameInformation.FileName);
1493 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
1499 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1501 if( ulResultLen >= ulEntryLength)
1503 ulResultLen -= ulEntryLength;
1511 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
1514 // Reset the information in the request buffer since it got trampled
1518 pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
1527 if( pBuffer != NULL)
1530 AFSExFreePoolWithTag( pBuffer, AFS_DIR_BUFFER_TAG);
1538 AFSNotifyFileCreate( IN GUID *AuthGroup,
1539 IN AFSObjectInfoCB *ParentObjectInfo,
1540 IN PLARGE_INTEGER FileSize,
1541 IN ULONG FileAttributes,
1542 IN UNICODE_STRING *FileName,
1543 OUT AFSDirectoryCB **DirNode)
1546 NTSTATUS ntStatus = STATUS_SUCCESS;
1547 AFSFileCreateCB stCreateCB;
1548 AFSFileCreateResultCB *pResultCB = NULL;
1549 ULONG ulResultLen = 0;
1550 UNICODE_STRING uniTargetName;
1551 AFSDirectoryCB *pDirNode = NULL;
1554 LARGE_INTEGER liOldDataVersion;
1555 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1556 BOOLEAN bReleaseParentTreeLock = FALSE;
1564 // Init the control block for the request
1567 RtlZeroMemory( &stCreateCB,
1568 sizeof( AFSFileCreateCB));
1570 stCreateCB.ParentId = ParentObjectInfo->FileId;
1572 stCreateCB.AllocationSize = *FileSize;
1574 stCreateCB.FileAttributes = FileAttributes;
1576 stCreateCB.EaSize = 0;
1578 liOldDataVersion = ParentObjectInfo->DataVersion;
1581 // Allocate our return buffer
1584 pResultCB = (AFSFileCreateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1586 AFS_GENERIC_MEMORY_1_TAG);
1588 if( pResultCB == NULL)
1591 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1594 RtlZeroMemory( pResultCB,
1597 ulResultLen = PAGE_SIZE;
1600 // Send the call to the service
1603 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_FILE,
1604 AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_HOLD_FID,
1611 sizeof( AFSFileCreateCB),
1615 if( ntStatus != STATUS_SUCCESS)
1618 if( NT_SUCCESS( ntStatus))
1621 ntStatus = STATUS_DEVICE_NOT_READY;
1624 try_return( ntStatus);
1628 // We may have raced with an invalidation call and a subsequent re-enumeration of this parent
1629 // and though we created the node, it is already in our list. If this is the case then
1630 // look up the entry rather than create a new entry
1631 // The check is to ensure the DV has been modified
1634 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1637 bReleaseParentTreeLock = TRUE;
1639 if( ParentObjectInfo->DataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1)
1642 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1643 AFS_TRACE_LEVEL_WARNING,
1644 "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",
1646 ParentObjectInfo->FileId.Cell,
1647 ParentObjectInfo->FileId.Volume,
1648 ParentObjectInfo->FileId.Vnode,
1649 ParentObjectInfo->FileId.Unique,
1650 ParentObjectInfo->DataVersion.HighPart,
1651 ParentObjectInfo->DataVersion.LowPart,
1652 pResultCB->ParentDataVersion.HighPart,
1653 pResultCB->ParentDataVersion.LowPart);
1656 // We raced so go and lookup the directory entry in the parent
1659 ulCRC = AFSGenerateCRC( FileName,
1662 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1666 if( pDirNode != NULL)
1669 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1670 AFS_TRACE_LEVEL_VERBOSE,
1671 "AFSNotifyFileCreate Located dir entry %p for file %wZ\n",
1675 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
1676 &pResultCB->DirEnum.FileId))
1679 *DirNode = pDirNode;
1681 try_return( ntStatus = STATUS_REPARSE);
1687 // We found an entry that matches the desired name but it is not the
1688 // same as the one that was created for us by the file server.
1691 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1692 AFS_TRACE_LEVEL_ERROR,
1693 "AFSNotifyFileCreate Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
1696 pDirNode->ObjectInformation->FileId.Cell,
1697 pDirNode->ObjectInformation->FileId.Volume,
1698 pDirNode->ObjectInformation->FileId.Vnode,
1699 pDirNode->ObjectInformation->FileId.Unique,
1700 pResultCB->DirEnum.FileId.Cell,
1701 pResultCB->DirEnum.FileId.Volume,
1702 pResultCB->DirEnum.FileId.Vnode,
1703 pResultCB->DirEnum.FileId.Unique);
1705 if( pDirNode->DirOpenReferenceCount <= 0)
1708 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1709 AFS_TRACE_LEVEL_VERBOSE,
1710 "AFSNotifyFileCreate Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1712 &pDirNode->NameInformation.FileName,
1713 pDirNode->ObjectInformation->FileId.Cell,
1714 pDirNode->ObjectInformation->FileId.Volume,
1715 pDirNode->ObjectInformation->FileId.Vnode,
1716 pDirNode->ObjectInformation->FileId.Unique,
1717 pResultCB->DirEnum.FileId.Cell,
1718 pResultCB->DirEnum.FileId.Volume,
1719 pResultCB->DirEnum.FileId.Vnode,
1720 pResultCB->DirEnum.FileId.Unique);
1722 AFSDeleteDirEntry( ParentObjectInfo,
1728 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
1730 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1731 AFS_TRACE_LEVEL_VERBOSE,
1732 "AFSNotifyFileCreate Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
1734 &pDirNode->NameInformation.FileName,
1735 pDirNode->ObjectInformation->FileId.Cell,
1736 pDirNode->ObjectInformation->FileId.Volume,
1737 pDirNode->ObjectInformation->FileId.Vnode,
1738 pDirNode->ObjectInformation->FileId.Unique,
1739 pResultCB->DirEnum.FileId.Cell,
1740 pResultCB->DirEnum.FileId.Volume,
1741 pResultCB->DirEnum.FileId.Vnode,
1742 pResultCB->DirEnum.FileId.Unique);
1744 AFSRemoveNameEntry( ParentObjectInfo,
1753 // We are unsure of our current data so set the verify flag. It may already be set
1754 // but no big deal to reset it
1757 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1759 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1762 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1763 AFS_TRACE_LEVEL_VERBOSE,
1764 "AFSNotifyFileCreate Creating new entry %wZ\n",
1768 // Initialize the directory entry
1771 uniTargetName.Length = (USHORT)pResultCB->DirEnum.TargetNameLength;
1773 uniTargetName.MaximumLength = uniTargetName.Length;
1775 uniTargetName.Buffer = (WCHAR *)((char *)&pResultCB->DirEnum + pResultCB->DirEnum.TargetNameOffset);
1777 pDirNode = AFSInitDirEntry( ParentObjectInfo,
1780 &pResultCB->DirEnum,
1781 (ULONG)InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1783 if( pDirNode == NULL)
1786 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1788 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1790 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1794 // Init the short name if we have one
1797 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1798 pResultCB->DirEnum.ShortNameLength > 0)
1801 UNICODE_STRING uniShortName;
1803 pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
1805 RtlCopyMemory( pDirNode->NameInformation.ShortName,
1806 pResultCB->DirEnum.ShortName,
1807 pDirNode->NameInformation.ShortNameLength);
1810 // Generate the short name index
1813 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1814 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1816 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1819 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1820 AFS_TRACE_LEVEL_VERBOSE,
1821 "AFSNotifyFileCreate Initialized short name %wZ for DE %p for %wZ\n",
1824 &pDirNode->NameInformation.FileName);
1829 // No short name or short names are disabled
1832 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
1835 if ( !BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1839 // Update the parent data version
1842 ParentObjectInfo->DataVersion = pResultCB->ParentDataVersion;
1844 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1845 AFS_TRACE_LEVEL_VERBOSE,
1846 "AFSNotifyFileCreate entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
1848 ParentObjectInfo->FileId.Cell,
1849 ParentObjectInfo->FileId.Volume,
1850 ParentObjectInfo->FileId.Vnode,
1851 ParentObjectInfo->FileId.Unique,
1852 ParentObjectInfo->DataVersion.QuadPart);
1856 // Return the directory node
1859 *DirNode = pDirNode;
1863 if ( *DirNode != NULL)
1866 lCount = InterlockedIncrement( &(*DirNode)->DirOpenReferenceCount);
1868 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1869 AFS_TRACE_LEVEL_VERBOSE,
1870 "AFSNotifyFileCreate Increment count on %wZ DE %p Cnt %d\n",
1871 &(*DirNode)->NameInformation.FileName,
1875 ASSERT( lCount >= 0);
1878 if ( bReleaseParentTreeLock)
1881 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1884 if( pResultCB != NULL)
1887 AFSExFreePoolWithTag( pResultCB, AFS_GENERIC_MEMORY_1_TAG);
1895 AFSUpdateFileInformation( IN AFSFileID *ParentFid,
1896 IN AFSObjectInfoCB *ObjectInfo,
1900 NTSTATUS ntStatus = STATUS_SUCCESS;
1901 AFSFileUpdateCB stUpdateCB;
1902 ULONG ulResultLen = 0;
1903 AFSFileUpdateResultCB *pUpdateResultCB = NULL;
1909 // Init the control block for the request
1912 RtlZeroMemory( &stUpdateCB,
1913 sizeof( AFSFileUpdateCB));
1915 stUpdateCB.AllocationSize = ObjectInfo->EndOfFile;
1917 stUpdateCB.FileAttributes = ObjectInfo->FileAttributes;
1919 stUpdateCB.EaSize = ObjectInfo->EaSize;
1921 stUpdateCB.ParentId = *ParentFid;
1923 stUpdateCB.LastAccessTime = ObjectInfo->LastAccessTime;
1925 stUpdateCB.CreateTime = ObjectInfo->CreationTime;
1927 stUpdateCB.ChangeTime = ObjectInfo->ChangeTime;
1929 stUpdateCB.LastWriteTime = ObjectInfo->LastWriteTime;
1931 pUpdateResultCB = (AFSFileUpdateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1933 AFS_UPDATE_RESULT_TAG);
1935 if( pUpdateResultCB == NULL)
1938 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1941 ulResultLen = PAGE_SIZE;
1943 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_UPDATE_FILE,
1944 AFS_REQUEST_FLAG_SYNCHRONOUS,
1947 &ObjectInfo->FileId,
1948 ObjectInfo->VolumeCB->VolumeInformation.Cell,
1949 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
1951 sizeof( AFSFileUpdateCB),
1955 if( ntStatus != STATUS_SUCCESS)
1958 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1959 AFS_TRACE_LEVEL_ERROR,
1960 "AFSUpdateFileInformation failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1961 ObjectInfo->FileId.Cell,
1962 ObjectInfo->FileId.Volume,
1963 ObjectInfo->FileId.Vnode,
1964 ObjectInfo->FileId.Unique,
1967 try_return( ntStatus);
1971 // Update the data version
1974 AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1977 if ( !BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
1980 ObjectInfo->DataVersion = pUpdateResultCB->DirEnum.DataVersion;
1983 AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1987 if( pUpdateResultCB != NULL)
1990 AFSExFreePoolWithTag( pUpdateResultCB, AFS_UPDATE_RESULT_TAG);
1998 AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
2000 IN BOOLEAN CheckOnly)
2002 NTSTATUS ntStatus = STATUS_SUCCESS;
2003 ULONG ulResultLen = 0;
2004 AFSFileDeleteCB stDelete;
2005 AFSFileDeleteResultCB stDeleteResult;
2006 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
2007 AFSObjectInfoCB *pObjectInfo = NULL;
2008 AFSObjectInfoCB *pParentObjectInfo = NULL;
2013 pObjectInfo = DirectoryCB->ObjectInformation;
2015 pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
2016 &pObjectInfo->ParentFileId);
2018 stDelete.ParentId = pObjectInfo->ParentFileId;
2020 stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
2022 ulResultLen = sizeof( AFSFileDeleteResultCB);
2026 ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
2029 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
2032 &DirectoryCB->NameInformation.FileName,
2033 &pObjectInfo->FileId,
2034 pObjectInfo->VolumeCB->VolumeInformation.Cell,
2035 pObjectInfo->VolumeCB->VolumeInformation.CellLength,
2037 sizeof( AFSFileDeleteCB),
2041 if( ntStatus != STATUS_SUCCESS)
2044 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2045 AFS_TRACE_LEVEL_ERROR,
2046 "AFSNotifyDelete failed ParentFID %08lX-%08lX-%08lX-%08lX %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2047 stDelete.ParentId.Cell,
2048 stDelete.ParentId.Volume,
2049 stDelete.ParentId.Vnode,
2050 stDelete.ParentId.Unique,
2051 &DirectoryCB->NameInformation.FileName,
2052 pObjectInfo->FileId.Cell,
2053 pObjectInfo->FileId.Volume,
2054 pObjectInfo->FileId.Vnode,
2055 pObjectInfo->FileId.Unique,
2058 try_return( ntStatus);
2061 AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2068 // Validate the parent data version
2071 if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
2074 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2076 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2083 // Update the parent data version
2086 if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart - 1)
2089 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2091 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2097 // TODO -- The entry must be removed from the directory at which point the
2098 // Directory data version number can be updated. Until then we must force
2101 // pParentObjectInfor->DataVersion.QuadPart = stDeleteResult.ParentDataVersion.QuadPart;
2104 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2106 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2110 AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2114 if ( pParentObjectInfo)
2117 AFSReleaseObjectInfo( &pParentObjectInfo);
2126 AFSNotifyHardLink( IN AFSObjectInfoCB *ObjectInfo,
2128 IN AFSObjectInfoCB *ParentObjectInfo,
2129 IN AFSObjectInfoCB *TargetParentObjectInfo,
2130 IN AFSDirectoryCB *SourceDirectoryCB,
2131 IN UNICODE_STRING *TargetName,
2132 IN BOOLEAN bReplaceIfExists,
2133 OUT AFSDirectoryCB **TargetDirectoryCB)
2136 NTSTATUS ntStatus = STATUS_SUCCESS;
2137 AFSFileHardLinkCB *pHardLinkCB = NULL;
2138 AFSFileHardLinkResultCB *pResultCB = NULL;
2139 ULONG ulResultLen = 0;
2140 AFSDirectoryCB *pDirNode = NULL;
2142 BOOLEAN bReleaseParentLock = FALSE, bReleaseTargetParentLock = FALSE;
2143 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2150 // Init the control block for the request
2153 pHardLinkCB = (AFSFileHardLinkCB *)AFSExAllocatePoolWithTag( PagedPool,
2155 AFS_HARDLINK_REQUEST_TAG);
2157 if( pHardLinkCB == NULL)
2160 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2163 RtlZeroMemory( pHardLinkCB,
2166 pHardLinkCB->SourceParentId = ParentObjectInfo->FileId;
2168 pHardLinkCB->TargetParentId = TargetParentObjectInfo->FileId;
2170 pHardLinkCB->TargetNameLength = TargetName->Length;
2172 RtlCopyMemory( pHardLinkCB->TargetName,
2174 TargetName->Length);
2176 pHardLinkCB->bReplaceIfExists = bReplaceIfExists;
2179 // Use the same buffer for the result control block
2182 pResultCB = (AFSFileHardLinkResultCB *)pHardLinkCB;
2184 ulResultLen = PAGE_SIZE;
2186 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_HARDLINK_FILE,
2187 AFS_REQUEST_FLAG_SYNCHRONOUS,
2189 &SourceDirectoryCB->NameInformation.FileName,
2190 &ObjectInfo->FileId,
2191 ObjectInfo->VolumeCB->VolumeInformation.Cell,
2192 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2194 sizeof( AFSFileHardLinkCB) + TargetName->Length,
2198 if( ntStatus != STATUS_SUCCESS)
2201 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2202 AFS_TRACE_LEVEL_ERROR,
2203 "AFSNotifyHardLink failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2204 ObjectInfo->FileId.Cell,
2205 ObjectInfo->FileId.Volume,
2206 ObjectInfo->FileId.Vnode,
2207 ObjectInfo->FileId.Unique,
2210 try_return( ntStatus);
2214 // Update the information from the returned data
2217 if ( ParentObjectInfo != TargetParentObjectInfo)
2220 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2223 bReleaseParentLock = TRUE;
2225 if ( ParentObjectInfo->DataVersion.QuadPart == pResultCB->SourceParentDataVersion.QuadPart - 1)
2228 ParentObjectInfo->DataVersion = pResultCB->SourceParentDataVersion;
2233 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2235 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2239 AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2242 bReleaseTargetParentLock = TRUE;
2244 if ( TargetParentObjectInfo->DataVersion.QuadPart == pResultCB->TargetParentDataVersion.QuadPart - 1)
2247 TargetParentObjectInfo->DataVersion = pResultCB->TargetParentDataVersion;
2252 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2253 AFS_TRACE_LEVEL_WARNING,
2254 "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",
2256 TargetParentObjectInfo->FileId.Cell,
2257 TargetParentObjectInfo->FileId.Volume,
2258 TargetParentObjectInfo->FileId.Vnode,
2259 TargetParentObjectInfo->FileId.Unique,
2260 TargetParentObjectInfo->DataVersion.HighPart,
2261 TargetParentObjectInfo->DataVersion.LowPart,
2262 pResultCB->TargetParentDataVersion.HighPart,
2263 pResultCB->TargetParentDataVersion.LowPart);
2266 // We raced so go and lookup the directory entry in the parent
2269 ulCRC = AFSGenerateCRC( TargetName,
2272 AFSLocateCaseSensitiveDirEntry( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2276 if( pDirNode != NULL)
2279 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2280 AFS_TRACE_LEVEL_VERBOSE,
2281 "AFSNotifyHardLink Located dir entry %p for file %wZ\n",
2285 if ( AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2286 &pResultCB->DirEnum.FileId))
2289 try_return( ntStatus = STATUS_REPARSE);
2295 // We found an entry that matches the desired name but it is not the
2296 // same as the one that was created for us by the file server.
2299 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2300 AFS_TRACE_LEVEL_ERROR,
2301 "AFSNotifyHardLink Found matching name entry %wZ DE %p FID %08lX-%08lX-%08lX-%08lX != FID %08lX-%08lX-%08lX-%08lX\n",
2304 pDirNode->ObjectInformation->FileId.Cell,
2305 pDirNode->ObjectInformation->FileId.Volume,
2306 pDirNode->ObjectInformation->FileId.Vnode,
2307 pDirNode->ObjectInformation->FileId.Unique,
2308 pResultCB->DirEnum.FileId.Cell,
2309 pResultCB->DirEnum.FileId.Volume,
2310 pResultCB->DirEnum.FileId.Vnode,
2311 pResultCB->DirEnum.FileId.Unique);
2313 if( pDirNode->DirOpenReferenceCount <= 0)
2316 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2317 AFS_TRACE_LEVEL_VERBOSE,
2318 "AFSNotifyHardLink Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2320 &pDirNode->NameInformation.FileName,
2321 pDirNode->ObjectInformation->FileId.Cell,
2322 pDirNode->ObjectInformation->FileId.Volume,
2323 pDirNode->ObjectInformation->FileId.Vnode,
2324 pDirNode->ObjectInformation->FileId.Unique,
2325 pResultCB->DirEnum.FileId.Cell,
2326 pResultCB->DirEnum.FileId.Volume,
2327 pResultCB->DirEnum.FileId.Vnode,
2328 pResultCB->DirEnum.FileId.Unique);
2330 AFSDeleteDirEntry( TargetParentObjectInfo,
2336 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2338 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2339 AFS_TRACE_LEVEL_VERBOSE,
2340 "AFSNotifyHardLink Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2342 &pDirNode->NameInformation.FileName,
2343 pDirNode->ObjectInformation->FileId.Cell,
2344 pDirNode->ObjectInformation->FileId.Volume,
2345 pDirNode->ObjectInformation->FileId.Vnode,
2346 pDirNode->ObjectInformation->FileId.Unique,
2347 pResultCB->DirEnum.FileId.Cell,
2348 pResultCB->DirEnum.FileId.Volume,
2349 pResultCB->DirEnum.FileId.Vnode,
2350 pResultCB->DirEnum.FileId.Unique);
2352 AFSRemoveNameEntry( TargetParentObjectInfo,
2361 // We are unsure of our current data so set the verify flag. It may already be set
2362 // but no big deal to reset it
2365 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2367 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2371 // Create the hard link entry
2374 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2375 AFS_TRACE_LEVEL_VERBOSE,
2376 "AFSNotifyHardLink Creating new entry %wZ\n",
2380 // Initialize the directory entry
2383 pDirNode = AFSInitDirEntry( TargetParentObjectInfo,
2386 &pResultCB->DirEnum,
2387 (ULONG)InterlockedIncrement( &TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
2389 if( pDirNode == NULL)
2392 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2394 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2396 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2400 // Init the short name if we have one
2403 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2404 pResultCB->DirEnum.ShortNameLength > 0)
2407 UNICODE_STRING uniShortName;
2409 pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
2411 RtlCopyMemory( pDirNode->NameInformation.ShortName,
2412 pResultCB->DirEnum.ShortName,
2413 pDirNode->NameInformation.ShortNameLength);
2416 // Generate the short name index
2419 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
2420 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
2422 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
2425 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2426 AFS_TRACE_LEVEL_VERBOSE,
2427 "AFSNotifyHardLink Initialized short name %wZ for DE %p for %wZ\n",
2430 &pDirNode->NameInformation.FileName);
2435 // No short name or short names are disabled
2438 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2441 if ( !BooleanFlagOn( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2445 // Update the target parent data version
2448 TargetParentObjectInfo->DataVersion = pResultCB->TargetParentDataVersion;
2450 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2451 AFS_TRACE_LEVEL_VERBOSE,
2452 "AFSNotifyHardLink entry %wZ ParentFID %08lX-%08lX-%08lX-%08lX Version %08lX:%08lX\n",
2454 TargetParentObjectInfo->FileId.Cell,
2455 TargetParentObjectInfo->FileId.Volume,
2456 TargetParentObjectInfo->FileId.Vnode,
2457 TargetParentObjectInfo->FileId.Unique,
2458 TargetParentObjectInfo->DataVersion.QuadPart);
2463 if ( TargetDirectoryCB != NULL)
2466 lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
2468 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2469 AFS_TRACE_LEVEL_VERBOSE,
2470 "AFSNotifyHardLink Increment count on %wZ DE %p Cnt %d\n",
2471 &pDirNode->NameInformation.FileName,
2475 ASSERT( lCount >= 0);
2477 *TargetDirectoryCB = pDirNode;
2480 if ( bReleaseTargetParentLock)
2483 AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2486 if ( bReleaseParentLock)
2489 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2492 if( pHardLinkCB != NULL)
2495 AFSExFreePoolWithTag( pHardLinkCB, AFS_HARDLINK_REQUEST_TAG);
2505 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
2507 IN AFSObjectInfoCB *ParentObjectInfo,
2508 IN AFSObjectInfoCB *TargetParentObjectInfo,
2509 IN AFSDirectoryCB *DirectoryCB,
2510 IN UNICODE_STRING *TargetName,
2511 OUT AFSFileID *UpdatedFID)
2514 NTSTATUS ntStatus = STATUS_SUCCESS;
2515 AFSFileRenameCB *pRenameCB = NULL;
2516 AFSFileRenameResultCB *pRenameResultCB = NULL;
2517 ULONG ulResultLen = 0;
2518 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2524 // Init the control block for the request
2527 pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
2529 AFS_RENAME_REQUEST_TAG);
2531 if( pRenameCB == NULL)
2534 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2537 RtlZeroMemory( pRenameCB,
2540 pRenameCB->SourceParentId = ParentObjectInfo->FileId;
2542 pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
2544 pRenameCB->TargetNameLength = TargetName->Length;
2546 RtlCopyMemory( pRenameCB->TargetName,
2548 TargetName->Length);
2551 // Use the same buffer for the result control block
2554 pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
2556 ulResultLen = PAGE_SIZE;
2558 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
2559 AFS_REQUEST_FLAG_SYNCHRONOUS,
2561 &DirectoryCB->NameInformation.FileName,
2562 &ObjectInfo->FileId,
2563 ObjectInfo->VolumeCB->VolumeInformation.Cell,
2564 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2566 sizeof( AFSFileRenameCB) + TargetName->Length,
2570 if( ntStatus != STATUS_SUCCESS)
2573 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2574 AFS_TRACE_LEVEL_ERROR,
2575 "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2576 ObjectInfo->FileId.Cell,
2577 ObjectInfo->FileId.Volume,
2578 ObjectInfo->FileId.Vnode,
2579 ObjectInfo->FileId.Unique,
2582 try_return( ntStatus);
2586 // Update the information from the returned data
2589 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2592 if ( ParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->SourceParentDataVersion.QuadPart - 1)
2595 ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
2600 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2602 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2605 if ( ParentObjectInfo != TargetParentObjectInfo)
2608 AFSAcquireExcl( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2611 if ( TargetParentObjectInfo->DataVersion.QuadPart == pRenameResultCB->TargetParentDataVersion.QuadPart - 1)
2614 TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
2619 SetFlag( TargetParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2621 TargetParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2626 // Move over the short name
2629 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2631 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
2632 DirectoryCB->NameInformation.ShortNameLength > 0)
2635 UNICODE_STRING uniShortName;
2637 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2638 uniShortName.MaximumLength = uniShortName.Length;
2639 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2641 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2642 AFS_TRACE_LEVEL_VERBOSE,
2643 "AFSNotifyRename Update old short name %wZ for DE %p for %wZ\n",
2646 &DirectoryCB->NameInformation.FileName);
2648 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
2650 RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
2651 pRenameResultCB->DirEnum.ShortName,
2652 DirectoryCB->NameInformation.ShortNameLength);
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 Initialized short name %wZ for DE %p for %wZ\n",
2663 &DirectoryCB->NameInformation.FileName);
2668 UNICODE_STRING uniShortName;
2670 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
2671 uniShortName.MaximumLength = uniShortName.Length;
2672 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
2674 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2675 AFS_TRACE_LEVEL_VERBOSE,
2676 "AFSNotifyRename Removing old short name %wZ for DE %p for %wZ\n",
2679 &DirectoryCB->NameInformation.FileName);
2681 DirectoryCB->NameInformation.ShortNameLength = 0;
2683 DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
2686 if ( ParentObjectInfo != TargetParentObjectInfo)
2689 AFSReleaseResource( TargetParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2692 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2694 if( UpdatedFID != NULL)
2696 *UpdatedFID = pRenameResultCB->DirEnum.FileId;
2701 if( pRenameCB != NULL)
2704 AFSExFreePoolWithTag( pRenameCB, AFS_RENAME_REQUEST_TAG);
2712 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
2714 IN BOOLEAN FastCall,
2715 OUT AFSDirEnumEntry **DirEnumEntry)
2718 NTSTATUS ntStatus = STATUS_SUCCESS;
2719 AFSEvalTargetCB stTargetID;
2720 ULONG ulResultBufferLength;
2721 AFSFileEvalResultCB *pEvalResultCB = NULL;
2722 AFSDirEnumEntry *pDirEnumCB = NULL;
2723 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
2724 AFSObjectInfoCB *pParentObjectInfo = NULL;
2729 RtlZeroMemory( &stTargetID,
2730 sizeof( AFSEvalTargetCB));
2732 if ( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2735 pParentObjectInfo = AFSFindObjectInfo( ObjectInfo->VolumeCB,
2736 &ObjectInfo->ParentFileId);
2738 stTargetID.ParentId = ObjectInfo->ParentFileId;
2742 // Allocate our response buffer
2745 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2747 AFS_GENERIC_MEMORY_30_TAG);
2749 if( pEvalResultCB == NULL)
2752 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2756 // Call to the service to evaluate the fid
2759 ulResultBufferLength = PAGE_SIZE;
2764 ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
2767 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
2771 &ObjectInfo->FileId,
2772 ObjectInfo->VolumeCB->VolumeInformation.Cell,
2773 ObjectInfo->VolumeCB->VolumeInformation.CellLength,
2775 sizeof( AFSEvalTargetCB),
2777 &ulResultBufferLength);
2779 if( ntStatus != STATUS_SUCCESS)
2783 // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
2787 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2790 if( pParentObjectInfo != NULL)
2793 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2796 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2798 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2800 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2804 try_return( ntStatus);
2808 // A BSOD can occur if the pEvalResultCB->FileType is FILE but the
2809 // ObjectInfo->FileType is something else. The same is true for
2810 // pDirEnumEntry->FileType is DIRECTORY. Perform a sanity check
2811 // to ensure consistency. An inconsistent pDirEnumEntry can be
2812 // produced as a result of invalid status info received from a file
2813 // server. If the types are inconsistent or if the type does not
2814 // match the implied type derived from the vnode (odd values are
2815 // directories and even values are other types), prevent the request
2816 // from completing successfully. This may prevent access to the file or
2817 // directory but will prevent a BSOD.
2820 if ( !AFSIsEqualFID( &ObjectInfo->FileId,
2821 &pEvalResultCB->DirEnum.FileId))
2824 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2827 switch ( pEvalResultCB->DirEnum.FileType)
2830 case AFS_FILE_TYPE_DIRECTORY:
2831 if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x1)
2834 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2837 if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
2838 ObjectInfo->FileType != AFS_FILE_TYPE_DIRECTORY)
2841 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2846 case AFS_FILE_TYPE_FILE:
2847 if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x0)
2850 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2853 if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
2854 ObjectInfo->FileType != AFS_FILE_TYPE_FILE)
2857 try_return( ntStatus = STATUS_UNSUCCESSFUL);
2864 // Validate the parent data version
2867 if ( pParentObjectInfo != NULL)
2870 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2873 if ( pParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
2876 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2878 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2881 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2885 // Pass back the dir enum entry
2888 if( DirEnumEntry != NULL)
2891 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
2893 AFS_GENERIC_MEMORY_2_TAG);
2895 if( pDirEnumCB == NULL)
2898 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2901 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
2902 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
2904 *DirEnumEntry = pDirEnumCB;
2909 if ( pParentObjectInfo != NULL)
2912 AFSReleaseObjectInfo( &pParentObjectInfo);
2915 if( pEvalResultCB != NULL)
2918 AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_30_TAG);
2921 if( !NT_SUCCESS( ntStatus))
2924 if( pDirEnumCB != NULL)
2927 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_2_TAG);
2930 *DirEnumEntry = NULL;
2938 AFSEvaluateTargetByName( IN GUID *AuthGroup,
2939 IN AFSObjectInfoCB *ParentObjectInfo,
2940 IN PUNICODE_STRING SourceName,
2942 OUT AFSDirEnumEntry **DirEnumEntry)
2945 NTSTATUS ntStatus = STATUS_SUCCESS;
2946 AFSEvalTargetCB stTargetID;
2947 ULONG ulResultBufferLength;
2948 AFSFileEvalResultCB *pEvalResultCB = NULL;
2949 AFSDirEnumEntry *pDirEnumCB = NULL;
2954 stTargetID.ParentId = ParentObjectInfo->FileId;
2957 // Allocate our response buffer
2960 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
2962 AFS_GENERIC_MEMORY_31_TAG);
2964 if( pEvalResultCB == NULL)
2967 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2971 // Call to the service to evaluate the fid
2974 ulResultBufferLength = PAGE_SIZE;
2976 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
2977 AFS_REQUEST_FLAG_SYNCHRONOUS | Flags,
2981 ParentObjectInfo->VolumeCB->VolumeInformation.Cell,
2982 ParentObjectInfo->VolumeCB->VolumeInformation.CellLength,
2984 sizeof( AFSEvalTargetCB),
2986 &ulResultBufferLength);
2988 if( ntStatus != STATUS_SUCCESS)
2991 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
2994 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2997 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2999 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
3001 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3004 try_return( ntStatus);
3008 // Validate the parent data version
3011 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3014 if ( ParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
3017 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3019 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
3022 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3025 // Pass back the dir enum entry
3028 if( DirEnumEntry != NULL)
3031 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
3033 AFS_GENERIC_MEMORY_3_TAG);
3035 if( pDirEnumCB == NULL)
3038 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3041 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
3042 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
3044 *DirEnumEntry = pDirEnumCB;
3049 if( pEvalResultCB != NULL)
3052 AFSExFreePoolWithTag( pEvalResultCB, AFS_GENERIC_MEMORY_31_TAG);
3055 if( !NT_SUCCESS( ntStatus))
3058 if( pDirEnumCB != NULL)
3061 AFSExFreePoolWithTag( pDirEnumCB, AFS_GENERIC_MEMORY_3_TAG);
3064 *DirEnumEntry = NULL;
3072 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
3073 IN AFSFileID *FileID,
3074 OUT AFSVolumeInfoCB *VolumeInformation)
3077 NTSTATUS ntStatus = STATUS_SUCCESS;
3078 ULONG ulResultLen = 0;
3083 ulResultLen = sizeof( AFSVolumeInfoCB);
3085 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
3086 AFS_REQUEST_FLAG_SYNCHRONOUS,
3097 if( ntStatus != STATUS_SUCCESS)
3100 try_return( ntStatus);
3112 AFSRetrieveVolumeSizeInformation( IN GUID *AuthGroup,
3113 IN AFSFileID *FileID,
3114 OUT AFSVolumeSizeInfoCB *VolumeSizeInformation)
3117 NTSTATUS ntStatus = STATUS_SUCCESS;
3118 ULONG ulResultLen = 0;
3123 ulResultLen = sizeof( AFSVolumeSizeInfoCB);
3125 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_SIZE_INFO,
3126 AFS_REQUEST_FLAG_SYNCHRONOUS,
3134 VolumeSizeInformation,
3137 if( ntStatus != STATUS_SUCCESS)
3140 try_return( ntStatus);
3152 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
3153 IN ULONG InputLength,
3154 IN ULONG OutputLength,
3155 IN void *InputDataBuffer,
3156 OUT void *OutputDataBuffer,
3157 OUT ULONG *BytesReturned)
3160 NTSTATUS ntStatus = STATUS_SUCCESS;
3161 ULONG ulResultLen = 0;
3162 MDL *pInputMdl = NULL, *pOutputMdl = NULL;
3163 void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
3164 AFSPipeIORequestCB *pIoRequest = NULL;
3170 // Map the user buffer to a system address
3173 pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
3177 if( pInputSystemBuffer == NULL)
3180 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3183 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
3184 sizeof( AFSPipeIORequestCB) +
3186 AFS_GENERIC_MEMORY_4_TAG);
3188 if( pIoRequest == NULL)
3191 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3194 RtlZeroMemory( pIoRequest,
3195 sizeof( AFSPipeIORequestCB) + InputLength);
3197 pIoRequest->RequestId = Ccb->RequestID;
3199 pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3201 pIoRequest->BufferLength = InputLength;
3203 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
3207 pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
3211 if( pOutputSystemBuffer == NULL)
3214 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3218 // Send the call to the service
3221 ulResultLen = OutputLength;
3223 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
3224 AFS_REQUEST_FLAG_SYNCHRONOUS,
3226 &Ccb->DirectoryCB->NameInformation.FileName,
3231 sizeof( AFSPipeIORequestCB) + InputLength,
3232 pOutputSystemBuffer,
3235 if( ntStatus != STATUS_SUCCESS &&
3236 ntStatus != STATUS_BUFFER_OVERFLOW)
3239 if( NT_SUCCESS( ntStatus))
3242 ntStatus = STATUS_DEVICE_NOT_READY;
3245 try_return( ntStatus);
3249 // Return the bytes processed
3252 *BytesReturned = ulResultLen;
3256 if( pInputMdl != NULL)
3259 MmUnlockPages( pInputMdl);
3261 IoFreeMdl( pInputMdl);
3264 if( pOutputMdl != NULL)
3267 MmUnlockPages( pOutputMdl);
3269 IoFreeMdl( pOutputMdl);
3272 if( pIoRequest != NULL)
3275 AFSExFreePoolWithTag( pIoRequest, AFS_GENERIC_MEMORY_4_TAG);
3283 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
3284 IN ULONG InformationClass,
3285 IN ULONG InputLength,
3286 IN void *DataBuffer)
3289 NTSTATUS ntStatus = STATUS_SUCCESS;
3290 AFSPipeInfoRequestCB *pInfoRequest = NULL;
3295 pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
3296 sizeof( AFSPipeInfoRequestCB) +
3298 AFS_GENERIC_MEMORY_5_TAG);
3300 if( pInfoRequest == NULL)
3303 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3306 RtlZeroMemory( pInfoRequest,
3307 sizeof( AFSPipeInfoRequestCB) + InputLength);
3309 pInfoRequest->RequestId = Ccb->RequestID;
3311 pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3313 pInfoRequest->BufferLength = InputLength;
3315 pInfoRequest->InformationClass = InformationClass;
3317 RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
3322 // Send the call to the service
3325 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
3326 AFS_REQUEST_FLAG_SYNCHRONOUS,
3328 &Ccb->DirectoryCB->NameInformation.FileName,
3333 sizeof( AFSPipeInfoRequestCB) + InputLength,
3337 if( ntStatus != STATUS_SUCCESS)
3340 if( NT_SUCCESS( ntStatus))
3343 ntStatus = STATUS_DEVICE_NOT_READY;
3346 try_return( ntStatus);
3351 if( pInfoRequest != NULL)
3354 AFSExFreePoolWithTag( pInfoRequest, AFS_GENERIC_MEMORY_5_TAG);
3362 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
3363 IN ULONG InformationClass,
3364 IN ULONG OutputLength,
3365 IN void *DataBuffer,
3366 OUT ULONG *BytesReturned)
3369 NTSTATUS ntStatus = STATUS_SUCCESS;
3370 AFSPipeInfoRequestCB stInfoRequest;
3371 ULONG ulBytesProcessed = 0;
3376 RtlZeroMemory( &stInfoRequest,
3377 sizeof( AFSPipeInfoRequestCB));
3379 stInfoRequest.RequestId = Ccb->RequestID;
3381 stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
3383 stInfoRequest.BufferLength = OutputLength;
3385 stInfoRequest.InformationClass = InformationClass;
3387 ulBytesProcessed = OutputLength;
3390 // Send the call to the service
3393 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
3394 AFS_REQUEST_FLAG_SYNCHRONOUS,
3396 &Ccb->DirectoryCB->NameInformation.FileName,
3401 sizeof( AFSPipeInfoRequestCB),
3405 if( ntStatus != STATUS_SUCCESS)
3408 if( NT_SUCCESS( ntStatus))
3411 ntStatus = STATUS_DEVICE_NOT_READY;
3414 try_return( ntStatus);
3417 *BytesReturned = ulBytesProcessed;
3428 AFSReleaseFid( IN AFSFileID *FileId)
3431 NTSTATUS ntStatus = STATUS_SUCCESS;
3436 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
3453 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
3454 IN LARGE_INTEGER *ExtentOffset,
3458 BOOLEAN bRequestQueued = FALSE;
3459 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
3460 AFSCommSrvcCB *pCommSrvc = NULL;
3461 AFSPoolEntry *pPoolEntry = NULL;
3462 AFSRequestExtentsCB *pRequestExtents = NULL;
3468 pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
3470 AFSAcquireShared( &pCommSrvc->IrpPoolLock,
3473 pPoolEntry = pCommSrvc->RequestPoolHead;
3475 while( pPoolEntry != NULL)
3478 if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
3481 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
3484 pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
3486 if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
3487 pRequestExtents->Length == Length)
3490 bRequestQueued = TRUE;
3495 pPoolEntry = pPoolEntry->fLink;
3498 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
3501 return bRequestQueued;