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;
64 uniGUID.MaximumLength = 0;
65 uniGUID.Buffer = NULL;
67 if( AuthGroup != NULL)
69 RtlStringFromGUID( *AuthGroup,
73 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
74 AFS_TRACE_LEVEL_VERBOSE,
75 "AFSEnumerateDirectory Enumerating FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
76 ObjectInfoCB->FileId.Cell,
77 ObjectInfoCB->FileId.Volume,
78 ObjectInfoCB->FileId.Vnode,
79 ObjectInfoCB->FileId.Unique,
82 if( AuthGroup != NULL)
84 RtlFreeUnicodeString( &uniGUID);
88 // Initialize the directory enumeration buffer for the directory
91 pBuffer = AFSExAllocatePoolWithTag( PagedPool,
92 AFS_DIR_ENUM_BUFFER_LEN,
98 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
101 RtlZeroMemory( pBuffer,
102 AFS_DIR_ENUM_BUFFER_LEN);
104 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
107 // Use the payload buffer for information we will pass to the service
110 pDirQueryCB = (AFSDirQueryCB *)pBuffer;
112 pDirQueryCB->EnumHandle = 0;
117 ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
121 // Loop on the information
128 // Go and retrieve the directory contents
131 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
135 &ObjectInfoCB->FileId,
137 sizeof( AFSDirQueryCB),
141 if( ntStatus != STATUS_SUCCESS ||
145 if( ntStatus == STATUS_NO_MORE_FILES ||
146 ntStatus == STATUS_NO_MORE_ENTRIES)
149 ntStatus = STATUS_SUCCESS;
154 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
155 AFS_TRACE_LEVEL_ERROR,
156 "AFSEnumerateDirectory Failed to enumerate directory Status %08lX\n",
163 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
165 pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
168 // Remove the leading header from the processed length
171 ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
173 while( ulResultLen > 0)
176 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
178 uniDirName.MaximumLength = uniDirName.Length;
180 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
182 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
184 uniTargetName.MaximumLength = uniTargetName.Length;
186 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
189 // Be sure we don't have this entry in the case sensitive tree
192 ulCRC = AFSGenerateCRC( &uniDirName,
195 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
199 if( pDirNode != NULL)
203 // Duplicate entry, skip it
206 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
208 uniTargetName.Length);
210 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
212 if( ulResultLen >= ulEntryLength)
214 ulResultLen -= ulEntryLength;
224 pDirNode = AFSInitDirEntry( ObjectInfoCB,
228 (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
230 if( pDirNode == NULL)
233 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
239 // Set up the entry length
242 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
243 pCurrentDirEntry->FileNameLength +
244 pCurrentDirEntry->TargetNameLength);
247 // Init the short name if we have one
250 if( pCurrentDirEntry->ShortNameLength > 0)
253 UNICODE_STRING uniShortName;
255 pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
257 RtlCopyMemory( pDirNode->NameInformation.ShortName,
258 pCurrentDirEntry->ShortName,
259 pDirNode->NameInformation.ShortNameLength);
262 // Generate the short name index
265 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
266 uniShortName.MaximumLength = uniShortName.Length;
267 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
269 if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
274 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
277 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
278 AFS_TRACE_LEVEL_VERBOSE,
279 "AFSEnumerateDirectory Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
282 &pDirNode->NameInformation.FileName,
283 pCurrentDirEntry->FileId.Cell,
284 pCurrentDirEntry->FileId.Volume,
285 pCurrentDirEntry->FileId.Vnode,
286 pCurrentDirEntry->FileId.Unique);
290 pDirNode->NameInformation.ShortNameLength = 0;
292 RtlZeroMemory( pDirNode->NameInformation.ShortName,
293 (12 * sizeof( WCHAR)));
298 // Insert the node into the name tree
301 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
303 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
306 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
308 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
309 AFS_TRACE_LEVEL_VERBOSE,
310 "AFSEnumerateDirectory Insert DE %p to head of case sensitive tree for %wZ\n",
312 &pDirNode->NameInformation.FileName);
317 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
318 AFS_TRACE_LEVEL_VERBOSE,
319 "AFSEnumerateDirectory Insert DE %p to case sensitive tree for %wZ\n",
321 &pDirNode->NameInformation.FileName);
323 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
328 // Delete this dir entry and continue on
331 AFSDeleteDirEntry( ObjectInfoCB,
334 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
336 if( ulResultLen >= ulEntryLength)
338 ulResultLen -= ulEntryLength;
349 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
351 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
354 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
355 AFS_TRACE_LEVEL_VERBOSE,
356 "AFSEnumerateDirectory Insert DE %p to head of case insensitive tree for %wZ\n",
358 &pDirNode->NameInformation.FileName);
360 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
362 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
367 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
368 AFS_TRACE_LEVEL_VERBOSE,
369 "AFSEnumerateDirectory Insert DE %p to case insensitive tree for %wZ\n",
371 &pDirNode->NameInformation.FileName);
373 AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
377 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
380 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
385 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
387 pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
390 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
392 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
394 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
396 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
397 AFS_TRACE_LEVEL_VERBOSE,
398 "AFSEnumerateDirectory Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
399 &pDirNode->NameInformation.FileName,
400 ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
401 ObjectInfoCB->FileId.Cell,
402 ObjectInfoCB->FileId.Volume,
403 ObjectInfoCB->FileId.Vnode,
404 ObjectInfoCB->FileId.Unique);
406 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
410 // Insert the short name entry if we have a valid short name
413 if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
416 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
417 AFS_TRACE_LEVEL_VERBOSE,
418 "AFSEnumerateDirectory Insert DE %p to head of shortname tree for %wZ\n",
420 &pDirNode->NameInformation.FileName);
422 ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
424 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
429 if( NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
432 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
434 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
435 AFS_TRACE_LEVEL_VERBOSE,
436 "AFSEnumerateDirectory Insert DE %p to shortname tree for %wZ\n",
438 &pDirNode->NameInformation.FileName);
447 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
449 if( ulResultLen >= ulEntryLength)
451 ulResultLen -= ulEntryLength;
459 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
462 // Reset the information in the request buffer since it got trampled
466 pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
468 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
469 AFS_TRACE_LEVEL_VERBOSE,
470 "AFSEnumerateDirectory EnumHandle %08lX\n",
471 pDirQueryCB->EnumHandle);
474 // If the enumeration handle is -1 then we are done
477 if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
493 AFSExFreePool( pBuffer);
497 // If the processing failed then we should reset the directory content in the event
498 // it is re-enumerated
501 if( !NT_SUCCESS( ntStatus))
504 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
505 AFS_TRACE_LEVEL_ERROR,
506 "AFSEnumerateDirectory Resetting content for FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
507 ObjectInfoCB->FileId.Cell,
508 ObjectInfoCB->FileId.Volume,
509 ObjectInfoCB->FileId.Vnode,
510 ObjectInfoCB->FileId.Unique,
513 AFSResetDirectoryContent( ObjectInfoCB);
521 AFSEnumerateDirectoryNoResponse( IN GUID *AuthGroup,
522 IN AFSFileID *FileId)
525 NTSTATUS ntStatus = STATUS_SUCCESS;
526 AFSDirQueryCB stDirQueryCB;
527 ULONG ulRequestFlags = 0;
533 // Use the payload buffer for information we will pass to the service
536 stDirQueryCB.EnumHandle = 0;
538 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
543 (void *)&stDirQueryCB,
544 sizeof( AFSDirQueryCB),
548 if( ntStatus != STATUS_SUCCESS)
551 if( ntStatus == STATUS_NO_MORE_FILES ||
552 ntStatus == STATUS_NO_MORE_ENTRIES)
555 ntStatus = STATUS_SUCCESS;
560 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
561 AFS_TRACE_LEVEL_ERROR,
562 "AFSEnumerateDirectoryNoResponse Failed to enumerate directory Status %08lX\n",
572 AFSVerifyDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB,
576 NTSTATUS ntStatus = STATUS_SUCCESS;
577 void *pBuffer = NULL;
578 ULONG ulResultLen = 0;
579 AFSDirQueryCB *pDirQueryCB;
580 AFSDirEnumEntry *pCurrentDirEntry = NULL;
581 AFSDirectoryCB *pDirNode = NULL;
582 ULONG ulEntryLength = 0;
583 AFSDirEnumResp *pDirEnumResponse = NULL;
584 UNICODE_STRING uniDirName, uniTargetName;
585 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_FAST_REQUEST;
587 AFSObjectInfoCB *pObjectInfo = NULL;
588 ULONGLONG ullIndex = 0;
589 UNICODE_STRING uniGUID;
595 uniGUID.MaximumLength = 0;
596 uniGUID.Buffer = NULL;
598 if( AuthGroup != NULL)
600 RtlStringFromGUID( *AuthGroup,
604 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
605 AFS_TRACE_LEVEL_VERBOSE,
606 "AFSVerifyDirectoryContent Verifying content for FID %08lX-%08lX-%08lX-%08lX AuthGroup %wZ\n",
607 ObjectInfoCB->FileId.Cell,
608 ObjectInfoCB->FileId.Volume,
609 ObjectInfoCB->FileId.Vnode,
610 ObjectInfoCB->FileId.Unique,
613 if( AuthGroup != NULL)
615 RtlFreeUnicodeString( &uniGUID);
619 // Initialize the directory enumeration buffer for the directory
622 pBuffer = AFSExAllocatePoolWithTag( PagedPool,
623 AFS_DIR_ENUM_BUFFER_LEN,
629 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
632 RtlZeroMemory( pBuffer,
633 AFS_DIR_ENUM_BUFFER_LEN);
635 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
638 // Use the payload buffer for information we will pass to the service
641 pDirQueryCB = (AFSDirQueryCB *)pBuffer;
643 pDirQueryCB->EnumHandle = 0;
646 // Loop on the information
653 // Go and retrieve the directory contents
656 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DIR_ENUM,
660 &ObjectInfoCB->FileId,
662 sizeof( AFSDirQueryCB),
666 if( ntStatus != STATUS_SUCCESS ||
670 if( ntStatus == STATUS_NO_MORE_FILES ||
671 ntStatus == STATUS_NO_MORE_ENTRIES)
674 ntStatus = STATUS_SUCCESS;
679 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
680 AFS_TRACE_LEVEL_ERROR,
681 "AFSVerifyDirectoryContent Failed to enumerate directory Status %08lX\n",
688 pDirEnumResponse = (AFSDirEnumResp *)pBuffer;
690 pCurrentDirEntry = (AFSDirEnumEntry *)pDirEnumResponse->Entry;
693 // Remove the leading header from the processed length
696 ulResultLen -= FIELD_OFFSET( AFSDirEnumResp, Entry);
698 while( ulResultLen > 0)
701 uniDirName.Length = (USHORT)pCurrentDirEntry->FileNameLength;
703 uniDirName.MaximumLength = uniDirName.Length;
705 uniDirName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->FileNameOffset);
707 uniTargetName.Length = (USHORT)pCurrentDirEntry->TargetNameLength;
709 uniTargetName.MaximumLength = uniTargetName.Length;
711 uniTargetName.Buffer = (WCHAR *)((char *)pCurrentDirEntry + pCurrentDirEntry->TargetNameOffset);
714 // Does this entry already exist in the directory?
717 ulCRC = AFSGenerateCRC( &uniDirName,
720 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
722 AFSLocateCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
728 // Set up the entry length
731 ulEntryLength = QuadAlign( sizeof( AFSDirEnumEntry) +
732 pCurrentDirEntry->FileNameLength +
733 pCurrentDirEntry->TargetNameLength);
735 if( pDirNode != NULL)
739 // Check that the FIDs are the same
742 if( AFSIsEqualFID( &pCurrentDirEntry->FileId,
743 &pDirNode->ObjectInformation->FileId))
746 AFSAcquireShared( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock,
749 ullIndex = AFSCreateLowIndex( &pCurrentDirEntry->FileId);
751 ntStatus = AFSLocateHashEntry( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeHead,
753 (AFSBTreeEntry **)&pObjectInfo);
755 AFSReleaseResource( ObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock);
757 if( NT_SUCCESS( ntStatus) &&
762 // Indicate this is a valid entry
765 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID);
767 if( pCurrentDirEntry->ShortNameLength > 0 &&
768 pDirNode->NameInformation.ShortNameLength > 0)
770 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
771 AFS_TRACE_LEVEL_VERBOSE,
772 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) old short name %S New short name %S\n",
774 &pDirNode->NameInformation.FileName,
775 pDirNode->NameInformation.ShortName,
776 pCurrentDirEntry->ShortName);
778 else if( pCurrentDirEntry->ShortNameLength == 0 &&
779 pDirNode->NameInformation.ShortNameLength > 0)
781 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
782 AFS_TRACE_LEVEL_VERBOSE,
783 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) old short name %S New short name NULL\n",
785 &pDirNode->NameInformation.FileName,
786 pDirNode->NameInformation.ShortName);
788 else if( pCurrentDirEntry->ShortNameLength > 0 &&
789 pDirNode->NameInformation.ShortNameLength == 0)
791 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
792 AFS_TRACE_LEVEL_VERBOSE,
793 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) old short name NULL New short name %S\n",
795 &pDirNode->NameInformation.FileName,
796 pCurrentDirEntry->ShortName);
800 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
801 AFS_TRACE_LEVEL_VERBOSE,
802 "AFSVerifyDirectoryContent Verified entry %wZ (%wZ) old short name NULL New short name NULL\n",
804 &pDirNode->NameInformation.FileName);
807 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
808 AFS_TRACE_LEVEL_VERBOSE,
809 "AFSVerifyDirectoryContent Verified entry %wZ for parent FID %08lX-%08lX-%08lX-%08lX\n",
811 ObjectInfoCB->FileId.Cell,
812 ObjectInfoCB->FileId.Volume,
813 ObjectInfoCB->FileId.Vnode,
814 ObjectInfoCB->FileId.Unique);
818 // Update the metadata for the entry
821 if( pObjectInfo->DataVersion.QuadPart == 0 ||
822 pObjectInfo->DataVersion.QuadPart != pCurrentDirEntry->DataVersion.QuadPart)
825 AFSUpdateMetaData( pDirNode,
828 if( pObjectInfo->FileType == AFS_FILE_TYPE_DIRECTORY)
831 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
832 AFS_TRACE_LEVEL_VERBOSE,
833 "AFSVerifyDirectoryContent Setting VERIFY on entry %wZ for FID %08lX-%08lX-%08lX-%08lX\n",
835 pObjectInfo->FileId.Cell,
836 pObjectInfo->FileId.Volume,
837 pObjectInfo->FileId.Vnode,
838 pObjectInfo->FileId.Unique);
840 SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
841 pObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
842 pObjectInfo->Expiration.QuadPart = 0;
850 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
852 if( ulResultLen >= ulEntryLength)
854 ulResultLen -= ulEntryLength;
865 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
866 AFS_TRACE_LEVEL_VERBOSE,
867 "AFSVerifyDirectoryContent Processing dir entry %p %wZ with different FID, same name in parent FID %08lX-%08lX-%08lX-%08lX\n",
869 &pDirNode->NameInformation.FileName,
870 ObjectInfoCB->FileId.Cell,
871 ObjectInfoCB->FileId.Volume,
872 ObjectInfoCB->FileId.Vnode,
873 ObjectInfoCB->FileId.Unique);
876 // Need to tear down this entry and rebuild it below
879 if( pDirNode->OpenReferenceCount == 0)
882 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
883 AFS_TRACE_LEVEL_VERBOSE,
884 "AFSVerifyDirectoryContent Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
886 &pDirNode->NameInformation.FileName,
887 pDirNode->ObjectInformation->FileId.Cell,
888 pDirNode->ObjectInformation->FileId.Volume,
889 pDirNode->ObjectInformation->FileId.Vnode,
890 pDirNode->ObjectInformation->FileId.Unique,
891 pCurrentDirEntry->FileId.Cell,
892 pCurrentDirEntry->FileId.Volume,
893 pCurrentDirEntry->FileId.Vnode,
894 pCurrentDirEntry->FileId.Unique);
896 AFSDeleteDirEntry( ObjectInfoCB,
902 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_DELETED);
904 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
905 AFS_TRACE_LEVEL_VERBOSE,
906 "AFSVerifyDirectoryContent Different FIDs - removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
908 &pDirNode->NameInformation.FileName,
909 pDirNode->ObjectInformation->FileId.Cell,
910 pDirNode->ObjectInformation->FileId.Volume,
911 pDirNode->ObjectInformation->FileId.Vnode,
912 pDirNode->ObjectInformation->FileId.Unique,
913 pCurrentDirEntry->FileId.Cell,
914 pCurrentDirEntry->FileId.Volume,
915 pCurrentDirEntry->FileId.Vnode,
916 pCurrentDirEntry->FileId.Unique);
918 AFSRemoveNameEntry( ObjectInfoCB,
923 pDirNode = AFSInitDirEntry( ObjectInfoCB,
927 (ULONG)InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.ContentIndex));
929 if( pDirNode == NULL)
932 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
938 // Init the short name if we have one
941 if( pCurrentDirEntry->ShortNameLength > 0)
944 UNICODE_STRING uniShortName;
946 pDirNode->NameInformation.ShortNameLength = pCurrentDirEntry->ShortNameLength;
948 RtlCopyMemory( pDirNode->NameInformation.ShortName,
949 pCurrentDirEntry->ShortName,
950 pDirNode->NameInformation.ShortNameLength);
953 // Generate the short name index
956 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
957 uniShortName.MaximumLength = uniShortName.Length;
958 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
960 if( !RtlIsNameLegalDOS8Dot3( &pDirNode->NameInformation.FileName,
965 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
968 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
969 AFS_TRACE_LEVEL_VERBOSE,
970 "AFSVerifyDirectoryContent Initialized short name %wZ for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
973 &pDirNode->NameInformation.FileName,
974 pCurrentDirEntry->FileId.Cell,
975 pCurrentDirEntry->FileId.Volume,
976 pCurrentDirEntry->FileId.Vnode,
977 pCurrentDirEntry->FileId.Unique);
981 pDirNode->NameInformation.ShortNameLength = 0;
983 RtlZeroMemory( pDirNode->NameInformation.ShortName,
984 (12 * sizeof( WCHAR)));
990 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
991 AFS_TRACE_LEVEL_VERBOSE,
992 "AFSVerifyDirectoryContent NO short name for DE %p for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
994 &pDirNode->NameInformation.FileName,
995 pCurrentDirEntry->FileId.Cell,
996 pCurrentDirEntry->FileId.Volume,
997 pCurrentDirEntry->FileId.Vnode,
998 pCurrentDirEntry->FileId.Unique);
1002 // Insert the node into the name tree
1005 ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
1007 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
1010 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = pDirNode;
1012 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1013 AFS_TRACE_LEVEL_VERBOSE,
1014 "AFSVerifyDirectoryContent Insert DE %p to head of case sensitive tree for %wZ\n",
1016 &pDirNode->NameInformation.FileName);
1021 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1024 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1025 AFS_TRACE_LEVEL_VERBOSE,
1026 "AFSVerifyDirectoryContent Failed to insert DE %p to case sensitive tree for %wZ\n",
1028 &pDirNode->NameInformation.FileName);
1031 // Delete this dir entry and continue on
1034 AFSDeleteDirEntry( ObjectInfoCB,
1037 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1039 if( ulResultLen >= ulEntryLength)
1041 ulResultLen -= ulEntryLength;
1052 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1053 AFS_TRACE_LEVEL_VERBOSE,
1054 "AFSVerifyDirectoryContent Insert DE %p to case sensitive tree for %wZ\n",
1056 &pDirNode->NameInformation.FileName);
1060 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1062 if( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
1065 ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = pDirNode;
1067 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
1069 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1070 AFS_TRACE_LEVEL_VERBOSE,
1071 "AFSVerifyDirectoryContent Insert DE %p to head of case insensitive tree for %wZ\n",
1073 &pDirNode->NameInformation.FileName);
1078 AFSInsertCaseInsensitiveDirEntry( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1081 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1082 AFS_TRACE_LEVEL_VERBOSE,
1083 "AFSVerifyDirectoryContent Insert DE %p to case insensitive tree for %wZ\n",
1085 &pDirNode->NameInformation.FileName);
1088 if( ObjectInfoCB->Specific.Directory.DirectoryNodeListHead == NULL)
1091 ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = pDirNode;
1096 (ObjectInfoCB->Specific.Directory.DirectoryNodeListTail)->ListEntry.fLink = pDirNode;
1098 pDirNode->ListEntry.bLink = ObjectInfoCB->Specific.Directory.DirectoryNodeListTail;
1101 ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = pDirNode;
1103 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
1105 InterlockedIncrement( &ObjectInfoCB->Specific.Directory.DirectoryNodeCount);
1107 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1108 AFS_TRACE_LEVEL_VERBOSE,
1109 "AFSVerifyDirectoryContent Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
1110 &pDirNode->NameInformation.FileName,
1111 ObjectInfoCB->Specific.Directory.DirectoryNodeCount,
1112 ObjectInfoCB->FileId.Cell,
1113 ObjectInfoCB->FileId.Volume,
1114 ObjectInfoCB->FileId.Vnode,
1115 ObjectInfoCB->FileId.Unique);
1117 if( pDirNode->Type.Data.ShortNameTreeEntry.HashIndex != 0)
1121 // Insert the short name entry if we have a valid short name
1124 if( ObjectInfoCB->Specific.Directory.ShortNameTree == NULL)
1127 ObjectInfoCB->Specific.Directory.ShortNameTree = pDirNode;
1129 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1130 AFS_TRACE_LEVEL_VERBOSE,
1131 "AFSVerifyDirectoryContent Insert DE %p to head of shortname tree for %wZ\n",
1133 &pDirNode->NameInformation.FileName);
1135 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1140 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfoCB->Specific.Directory.ShortNameTree,
1143 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1144 AFS_TRACE_LEVEL_VERBOSE,
1145 "AFSVerifyDirectoryContent Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
1147 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex,
1148 &pDirNode->NameInformation.FileName);
1152 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
1154 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1155 AFS_TRACE_LEVEL_VERBOSE,
1156 "AFSVerifyDirectoryContent Insert DE %p to shortname tree for %wZ\n",
1158 &pDirNode->NameInformation.FileName);
1167 pCurrentDirEntry = (AFSDirEnumEntry *)((char *)pCurrentDirEntry + ulEntryLength);
1169 if( ulResultLen >= ulEntryLength)
1171 ulResultLen -= ulEntryLength;
1179 ulResultLen = AFS_DIR_ENUM_BUFFER_LEN;
1182 // Reset the information in the request buffer since it got trampled
1186 pDirQueryCB->EnumHandle = pDirEnumResponse->EnumHandle;
1189 // If the enumeration handle is -1 then we are done
1192 if( ((ULONG)-1) == pDirQueryCB->EnumHandle )
1205 if( pBuffer != NULL)
1208 AFSExFreePool( pBuffer);
1216 AFSNotifyFileCreate( IN GUID *AuthGroup,
1217 IN AFSObjectInfoCB *ParentObjectInfo,
1218 IN PLARGE_INTEGER FileSize,
1219 IN ULONG FileAttributes,
1220 IN UNICODE_STRING *FileName,
1221 OUT AFSDirectoryCB **DirNode)
1224 NTSTATUS ntStatus = STATUS_SUCCESS;
1225 AFSFileCreateCB stCreateCB;
1226 AFSFileCreateResultCB *pResultCB = NULL;
1227 ULONG ulResultLen = 0;
1228 UNICODE_STRING uniTargetName;
1229 AFSDirectoryCB *pDirNode = NULL;
1231 LARGE_INTEGER liOldDataVersion;
1237 // Init the control block for the request
1240 RtlZeroMemory( &stCreateCB,
1241 sizeof( AFSFileCreateCB));
1243 stCreateCB.ParentId = ParentObjectInfo->FileId;
1245 stCreateCB.AllocationSize = *FileSize;
1247 stCreateCB.FileAttributes = FileAttributes;
1249 stCreateCB.EaSize = 0;
1251 liOldDataVersion = ParentObjectInfo->DataVersion;
1254 // Allocate our return buffer
1257 pResultCB = (AFSFileCreateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1259 AFS_GENERIC_MEMORY_1_TAG);
1261 if( pResultCB == NULL)
1264 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1267 RtlZeroMemory( pResultCB,
1270 ulResultLen = PAGE_SIZE;
1273 // Send the call to the service
1276 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_CREATE_FILE,
1277 AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_HOLD_FID,
1282 sizeof( AFSFileCreateCB),
1286 if( ntStatus != STATUS_SUCCESS)
1289 if( NT_SUCCESS( ntStatus))
1292 ntStatus = STATUS_DEVICE_NOT_READY;
1295 try_return( ntStatus);
1299 // We may have raced with an invalidation call and a subsequent re-enumeration of this parent
1300 // and though we created the node, it is already in our list. If this is the case then
1301 // look up the entry rather than create a new entry
1302 // The check is to ensure the DV has been modified
1305 if( liOldDataVersion.QuadPart != pResultCB->ParentDataVersion.QuadPart - 1 ||
1306 liOldDataVersion.QuadPart != ParentObjectInfo->DataVersion.QuadPart)
1309 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1310 AFS_TRACE_LEVEL_VERBOSE,
1311 "AFSNotifyFileCreate Raced with an invalidate call and a re-enumeration for entry %wZ\n",
1315 // We raced so go and lookup the directory entry in the parent
1318 ulCRC = AFSGenerateCRC( FileName,
1321 AFSAcquireShared( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1324 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1328 if( pDirNode != NULL)
1331 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1332 AFS_TRACE_LEVEL_VERBOSE,
1333 "AFSNotifyFileCreate Located dir entry for file %wZ\n",
1336 InterlockedIncrement( &pDirNode->OpenReferenceCount);
1338 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1339 AFS_TRACE_LEVEL_VERBOSE,
1340 "AFSNotifyFileCreate Increment count on %wZ DE %p Cnt %d\n",
1341 &pDirNode->NameInformation.FileName,
1343 pDirNode->OpenReferenceCount);
1345 *DirNode = pDirNode;
1347 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1349 try_return( ntStatus = STATUS_REPARSE);
1352 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1355 // We are unsure of our current data so set the verify flag. It may already be set
1356 // but no big deal to reset it
1359 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1361 ParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1367 // Update the parent data version
1370 ParentObjectInfo->DataVersion = pResultCB->ParentDataVersion;
1373 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1374 AFS_TRACE_LEVEL_VERBOSE,
1375 "AFSNotifyFileCreate Creating new entry %wZ\n",
1379 // Initialize the directory entry
1382 uniTargetName.Length = (USHORT)pResultCB->DirEnum.TargetNameLength;
1384 uniTargetName.MaximumLength = uniTargetName.Length;
1386 uniTargetName.Buffer = (WCHAR *)((char *)&pResultCB->DirEnum + pResultCB->DirEnum.TargetNameOffset);
1388 pDirNode = AFSInitDirEntry( ParentObjectInfo,
1391 &pResultCB->DirEnum,
1392 (ULONG)InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.ContentIndex));
1394 if( pDirNode == NULL)
1397 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1401 // Init the short name if we have one
1404 if( pResultCB->DirEnum.ShortNameLength > 0)
1407 UNICODE_STRING uniShortName;
1409 pDirNode->NameInformation.ShortNameLength = pResultCB->DirEnum.ShortNameLength;
1411 RtlCopyMemory( pDirNode->NameInformation.ShortName,
1412 pResultCB->DirEnum.ShortName,
1413 pDirNode->NameInformation.ShortNameLength);
1416 // Generate the short name index
1419 uniShortName.Length = pDirNode->NameInformation.ShortNameLength;
1420 uniShortName.Buffer = pDirNode->NameInformation.ShortName;
1422 pDirNode->Type.Data.ShortNameTreeEntry.HashIndex = AFSGenerateCRC( &uniShortName,
1425 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1426 AFS_TRACE_LEVEL_VERBOSE,
1427 "AFSNotifyFileCreate Initialized short name %wZ for DE %p for %wZ\n",
1430 &pDirNode->NameInformation.FileName);
1434 // Return the directory node
1437 *DirNode = pDirNode;
1441 if( pResultCB != NULL)
1444 AFSExFreePool( pResultCB);
1452 AFSUpdateFileInformation( IN AFSFileID *ParentFid,
1453 IN AFSObjectInfoCB *ObjectInfo,
1457 NTSTATUS ntStatus = STATUS_SUCCESS;
1458 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1459 AFSFileUpdateCB stUpdateCB;
1460 ULONG ulResultLen = 0;
1461 AFSFileUpdateResultCB *pUpdateResultCB = NULL;
1467 // Init the control block for the request
1470 RtlZeroMemory( &stUpdateCB,
1471 sizeof( AFSFileUpdateCB));
1473 stUpdateCB.AllocationSize = ObjectInfo->EndOfFile;
1475 stUpdateCB.FileAttributes = ObjectInfo->FileAttributes;
1477 stUpdateCB.EaSize = ObjectInfo->EaSize;
1479 stUpdateCB.ParentId = *ParentFid;
1481 stUpdateCB.LastAccessTime = ObjectInfo->LastAccessTime;
1483 stUpdateCB.CreateTime = ObjectInfo->CreationTime;
1485 stUpdateCB.ChangeTime = ObjectInfo->ChangeTime;
1487 stUpdateCB.LastWriteTime = ObjectInfo->LastWriteTime;
1489 pUpdateResultCB = (AFSFileUpdateResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1491 AFS_UPDATE_RESULT_TAG);
1493 if( pUpdateResultCB == NULL)
1496 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1499 ulResultLen = PAGE_SIZE;
1501 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_UPDATE_FILE,
1502 AFS_REQUEST_FLAG_SYNCHRONOUS,
1505 &ObjectInfo->FileId,
1507 sizeof( AFSFileUpdateCB),
1511 if( ntStatus != STATUS_SUCCESS)
1514 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1515 AFS_TRACE_LEVEL_ERROR,
1516 "AFSUpdateFileInformation failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1517 ObjectInfo->FileId.Cell,
1518 ObjectInfo->FileId.Volume,
1519 ObjectInfo->FileId.Vnode,
1520 ObjectInfo->FileId.Unique,
1523 try_return( ntStatus);
1527 // Update the data version
1530 ObjectInfo->DataVersion = pUpdateResultCB->DirEnum.DataVersion;
1534 if( pUpdateResultCB != NULL)
1537 AFSExFreePool( pUpdateResultCB);
1545 AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
1547 IN BOOLEAN CheckOnly)
1549 NTSTATUS ntStatus = STATUS_SUCCESS;
1550 ULONG ulResultLen = 0;
1551 AFSFileDeleteCB stDelete;
1552 AFSFileDeleteResultCB stDeleteResult;
1553 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1558 stDelete.ParentId = DirectoryCB->ObjectInformation->ParentObjectInformation->FileId;
1560 stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
1562 ulResultLen = sizeof( AFSFileDeleteResultCB);
1566 ulRequestFlags |= AFS_REQUEST_FLAG_CHECK_ONLY;
1569 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_DELETE_FILE,
1572 &DirectoryCB->NameInformation.FileName,
1573 &DirectoryCB->ObjectInformation->FileId,
1575 sizeof( AFSFileDeleteCB),
1579 if( ntStatus != STATUS_SUCCESS)
1582 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1583 AFS_TRACE_LEVEL_ERROR,
1584 "AFSNotifyDelete failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1585 &DirectoryCB->ObjectInformation->FileId.Cell,
1586 &DirectoryCB->ObjectInformation->FileId.Volume,
1587 &DirectoryCB->ObjectInformation->FileId.Vnode,
1588 &DirectoryCB->ObjectInformation->FileId.Unique,
1591 try_return( ntStatus);
1598 // Update the parent data version
1601 if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
1604 SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1606 DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1619 AFSNotifyRename( IN AFSObjectInfoCB *ObjectInfo,
1621 IN AFSObjectInfoCB *ParentObjectInfo,
1622 IN AFSObjectInfoCB *TargetParentObjectInfo,
1623 IN AFSDirectoryCB *DirectoryCB,
1624 IN UNICODE_STRING *TargetName,
1625 OUT AFSFileID *UpdatedFID)
1628 NTSTATUS ntStatus = STATUS_SUCCESS;
1629 AFSFileRenameCB *pRenameCB = NULL;
1630 AFSFileRenameResultCB *pRenameResultCB = NULL;
1631 ULONG ulResultLen = 0;
1637 // Init the control block for the request
1640 pRenameCB = (AFSFileRenameCB *)AFSExAllocatePoolWithTag( PagedPool,
1642 AFS_RENAME_REQUEST_TAG);
1644 if( pRenameCB == NULL)
1647 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1650 RtlZeroMemory( pRenameCB,
1653 pRenameCB->SourceParentId = ParentObjectInfo->FileId;
1655 pRenameCB->TargetParentId = TargetParentObjectInfo->FileId;
1657 pRenameCB->TargetNameLength = TargetName->Length;
1659 RtlCopyMemory( pRenameCB->TargetName,
1661 TargetName->Length);
1664 // Use the same buffer for the result control block
1667 pRenameResultCB = (AFSFileRenameResultCB *)pRenameCB;
1669 ulResultLen = PAGE_SIZE;
1671 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RENAME_FILE,
1672 AFS_REQUEST_FLAG_SYNCHRONOUS,
1674 &DirectoryCB->NameInformation.FileName,
1675 &ObjectInfo->FileId,
1677 sizeof( AFSFileRenameCB) + TargetName->Length,
1681 if( ntStatus != STATUS_SUCCESS)
1684 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1685 AFS_TRACE_LEVEL_ERROR,
1686 "AFSNotifyRename failed FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1687 ObjectInfo->FileId.Cell,
1688 ObjectInfo->FileId.Volume,
1689 ObjectInfo->FileId.Vnode,
1690 ObjectInfo->FileId.Unique,
1693 try_return( ntStatus);
1697 // Update the information from the returned data
1700 ParentObjectInfo->DataVersion = pRenameResultCB->SourceParentDataVersion;
1702 TargetParentObjectInfo->DataVersion = pRenameResultCB->TargetParentDataVersion;
1705 // Move over the short name
1708 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
1710 if( DirectoryCB->NameInformation.ShortNameLength > 0)
1713 UNICODE_STRING uniShortName;
1715 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
1716 uniShortName.MaximumLength = uniShortName.Length;
1717 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
1719 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1720 AFS_TRACE_LEVEL_VERBOSE,
1721 "AFSNotifyRename Update old short name %wZ for DE %p for %wZ\n",
1724 &DirectoryCB->NameInformation.FileName);
1726 DirectoryCB->NameInformation.ShortNameLength = pRenameResultCB->DirEnum.ShortNameLength;
1728 RtlCopyMemory( DirectoryCB->NameInformation.ShortName,
1729 pRenameResultCB->DirEnum.ShortName,
1730 DirectoryCB->NameInformation.ShortNameLength);
1732 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
1733 uniShortName.MaximumLength = uniShortName.Length;
1734 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
1736 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1737 AFS_TRACE_LEVEL_VERBOSE,
1738 "AFSNotifyRename Initialized short name %wZ for DE %p for %wZ\n",
1741 &DirectoryCB->NameInformation.FileName);
1746 UNICODE_STRING uniShortName;
1748 uniShortName.Length = DirectoryCB->NameInformation.ShortNameLength;
1749 uniShortName.MaximumLength = uniShortName.Length;
1750 uniShortName.Buffer = DirectoryCB->NameInformation.ShortName;
1752 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1753 AFS_TRACE_LEVEL_VERBOSE,
1754 "AFSNotifyRename Removing old short name %wZ for DE %p for %wZ\n",
1757 &DirectoryCB->NameInformation.FileName);
1759 DirectoryCB->NameInformation.ShortNameLength = 0;
1761 DirectoryCB->Type.Data.ShortNameTreeEntry.HashIndex = 0;
1764 if( UpdatedFID != NULL)
1766 *UpdatedFID = pRenameResultCB->DirEnum.FileId;
1771 if( pRenameCB != NULL)
1774 AFSExFreePool( pRenameCB);
1782 AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
1784 IN BOOLEAN FastCall,
1785 OUT AFSDirEnumEntry **DirEnumEntry)
1788 NTSTATUS ntStatus = STATUS_SUCCESS;
1789 AFSEvalTargetCB stTargetID;
1790 ULONG ulResultBufferLength;
1791 AFSFileEvalResultCB *pEvalResultCB = NULL;
1792 AFSDirEnumEntry *pDirEnumCB = NULL;
1793 ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
1798 RtlZeroMemory( &stTargetID,
1799 sizeof( AFSEvalTargetCB));
1801 if( ObjectInfo->ParentObjectInformation != NULL)
1804 stTargetID.ParentId = ObjectInfo->ParentObjectInformation->FileId;
1808 // Allocate our response buffer
1811 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1813 AFS_GENERIC_MEMORY_30_TAG);
1815 if( pEvalResultCB == NULL)
1818 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1822 // Call to the service to evaluate the fid
1825 ulResultBufferLength = PAGE_SIZE;
1830 ulRequestFlags |= AFS_REQUEST_FLAG_FAST_REQUEST;
1833 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_ID,
1837 &ObjectInfo->FileId,
1839 sizeof( AFSEvalTargetCB),
1841 &ulResultBufferLength);
1843 if( ntStatus != STATUS_SUCCESS)
1847 // If we received back a STATUS_INVALID_HANDLE then mark the parent as requiring
1851 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
1854 if( ObjectInfo->ParentObjectInformation != NULL)
1857 SetFlag( ObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1861 try_return( ntStatus);
1865 // Pass back the dir enum entry
1868 if( DirEnumEntry != NULL)
1871 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
1873 AFS_GENERIC_MEMORY_2_TAG);
1875 if( pDirEnumCB == NULL)
1878 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1881 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
1882 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
1884 *DirEnumEntry = pDirEnumCB;
1889 if( pEvalResultCB != NULL)
1892 AFSExFreePool( pEvalResultCB);
1895 if( !NT_SUCCESS( ntStatus))
1898 if( pDirEnumCB != NULL)
1901 AFSExFreePool( pDirEnumCB);
1904 *DirEnumEntry = NULL;
1912 AFSEvaluateTargetByName( IN GUID *AuthGroup,
1913 IN AFSObjectInfoCB *ParentObjectInfo,
1914 IN PUNICODE_STRING SourceName,
1915 OUT AFSDirEnumEntry **DirEnumEntry)
1918 NTSTATUS ntStatus = STATUS_SUCCESS;
1919 AFSEvalTargetCB stTargetID;
1920 ULONG ulResultBufferLength;
1921 AFSFileEvalResultCB *pEvalResultCB = NULL;
1922 AFSDirEnumEntry *pDirEnumCB = NULL;
1927 stTargetID.ParentId = ParentObjectInfo->FileId;
1930 // Allocate our response buffer
1933 pEvalResultCB = (AFSFileEvalResultCB *)AFSExAllocatePoolWithTag( PagedPool,
1935 AFS_GENERIC_MEMORY_31_TAG);
1937 if( pEvalResultCB == NULL)
1940 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1944 // Call to the service to evaluate the fid
1947 ulResultBufferLength = PAGE_SIZE;
1949 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_EVAL_TARGET_BY_NAME,
1950 AFS_REQUEST_FLAG_SYNCHRONOUS,
1955 sizeof( AFSEvalTargetCB),
1957 &ulResultBufferLength);
1959 if( ntStatus != STATUS_SUCCESS)
1962 if( ntStatus == STATUS_OBJECT_PATH_INVALID)
1964 SetFlag( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1967 try_return( ntStatus);
1971 // Pass back the dir enum entry
1974 if( DirEnumEntry != NULL)
1977 pDirEnumCB = (AFSDirEnumEntry *)AFSExAllocatePoolWithTag( PagedPool,
1979 AFS_GENERIC_MEMORY_3_TAG);
1981 if( pDirEnumCB == NULL)
1984 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1987 RtlCopyMemory( pDirEnumCB, &pEvalResultCB->DirEnum,
1988 ulResultBufferLength - sizeof( AFSFileEvalResultCB) + sizeof( AFSDirEnumEntry));
1990 *DirEnumEntry = pDirEnumCB;
1995 if( pEvalResultCB != NULL)
1998 AFSExFreePool( pEvalResultCB);
2001 if( !NT_SUCCESS( ntStatus))
2004 if( pDirEnumCB != NULL)
2007 AFSExFreePool( pDirEnumCB);
2010 *DirEnumEntry = NULL;
2018 AFSRetrieveVolumeInformation( IN GUID *AuthGroup,
2019 IN AFSFileID *FileID,
2020 OUT AFSVolumeInfoCB *VolumeInformation)
2023 NTSTATUS ntStatus = STATUS_SUCCESS;
2024 ULONG ulResultLen = 0;
2029 ulResultLen = sizeof( AFSVolumeInfoCB);
2031 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_GET_VOLUME_INFO,
2032 AFS_REQUEST_FLAG_SYNCHRONOUS,
2041 if( ntStatus != STATUS_SUCCESS)
2044 try_return( ntStatus);
2056 AFSNotifyPipeTransceive( IN AFSCcb *Ccb,
2057 IN ULONG InputLength,
2058 IN ULONG OutputLength,
2059 IN void *InputDataBuffer,
2060 OUT void *OutputDataBuffer,
2061 OUT ULONG *BytesReturned)
2064 NTSTATUS ntStatus = STATUS_SUCCESS;
2065 ULONG ulResultLen = 0;
2066 MDL *pInputMdl = NULL, *pOutputMdl = NULL;
2067 void *pInputSystemBuffer = NULL, *pOutputSystemBuffer = NULL;
2068 ULONG ulBufferLength = OutputLength;
2069 AFSPipeIORequestCB *pIoRequest = NULL;
2075 // Map the user buffer to a system address
2078 pInputSystemBuffer = AFSLockUserBuffer( InputDataBuffer,
2082 if( pInputSystemBuffer == NULL)
2085 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2088 pIoRequest = (AFSPipeIORequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2089 sizeof( AFSPipeIORequestCB) +
2091 AFS_GENERIC_MEMORY_4_TAG);
2093 if( pIoRequest == NULL)
2096 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2099 RtlZeroMemory( pIoRequest,
2100 sizeof( AFSPipeIORequestCB) + InputLength);
2102 pIoRequest->RequestId = Ccb->RequestID;
2104 pIoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2106 pIoRequest->BufferLength = InputLength;
2108 RtlCopyMemory( (void *)((char *)pIoRequest + sizeof( AFSPipeIORequestCB)),
2112 pOutputSystemBuffer = AFSLockUserBuffer( OutputDataBuffer,
2116 if( pOutputSystemBuffer == NULL)
2119 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2123 // Send the call to the service
2126 ulResultLen = OutputLength;
2128 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_TRANSCEIVE,
2129 AFS_REQUEST_FLAG_SYNCHRONOUS,
2131 &Ccb->DirectoryCB->NameInformation.FileName,
2134 sizeof( AFSPipeIORequestCB) + InputLength,
2135 pOutputSystemBuffer,
2138 if( ntStatus != STATUS_SUCCESS &&
2139 ntStatus != STATUS_BUFFER_OVERFLOW)
2142 if( NT_SUCCESS( ntStatus))
2145 ntStatus = STATUS_DEVICE_NOT_READY;
2148 try_return( ntStatus);
2152 // Return the bytes processed
2155 *BytesReturned = ulResultLen;
2159 if( pInputMdl != NULL)
2162 MmUnlockPages( pInputMdl);
2164 IoFreeMdl( pInputMdl);
2167 if( pOutputMdl != NULL)
2170 MmUnlockPages( pOutputMdl);
2172 IoFreeMdl( pOutputMdl);
2175 if( pIoRequest != NULL)
2178 AFSExFreePool( pIoRequest);
2186 AFSNotifySetPipeInfo( IN AFSCcb *Ccb,
2187 IN ULONG InformationClass,
2188 IN ULONG InputLength,
2189 IN void *DataBuffer)
2192 NTSTATUS ntStatus = STATUS_SUCCESS;
2193 AFSPipeInfoRequestCB *pInfoRequest = NULL;
2198 pInfoRequest = (AFSPipeInfoRequestCB *)AFSExAllocatePoolWithTag( PagedPool,
2199 sizeof( AFSPipeInfoRequestCB) +
2201 AFS_GENERIC_MEMORY_5_TAG);
2203 if( pInfoRequest == NULL)
2206 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2209 RtlZeroMemory( pInfoRequest,
2210 sizeof( AFSPipeInfoRequestCB) + InputLength);
2212 pInfoRequest->RequestId = Ccb->RequestID;
2214 pInfoRequest->RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2216 pInfoRequest->BufferLength = InputLength;
2218 pInfoRequest->InformationClass = InformationClass;
2220 RtlCopyMemory( (void *)((char *)pInfoRequest + sizeof( AFSPipeInfoRequestCB)),
2225 // Send the call to the service
2228 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_SET_INFO,
2229 AFS_REQUEST_FLAG_SYNCHRONOUS,
2231 &Ccb->DirectoryCB->NameInformation.FileName,
2234 sizeof( AFSPipeInfoRequestCB) + InputLength,
2238 if( ntStatus != STATUS_SUCCESS)
2241 if( NT_SUCCESS( ntStatus))
2244 ntStatus = STATUS_DEVICE_NOT_READY;
2247 try_return( ntStatus);
2252 if( pInfoRequest != NULL)
2255 AFSExFreePool( pInfoRequest);
2263 AFSNotifyQueryPipeInfo( IN AFSCcb *Ccb,
2264 IN ULONG InformationClass,
2265 IN ULONG OutputLength,
2266 IN void *DataBuffer,
2267 OUT ULONG *BytesReturned)
2270 NTSTATUS ntStatus = STATUS_SUCCESS;
2271 AFSPipeInfoRequestCB stInfoRequest;
2272 ULONG ulBytesProcessed = 0;
2277 RtlZeroMemory( &stInfoRequest,
2278 sizeof( AFSPipeInfoRequestCB));
2280 stInfoRequest.RequestId = Ccb->RequestID;
2282 stInfoRequest.RootId = Ccb->DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
2284 stInfoRequest.BufferLength = OutputLength;
2286 stInfoRequest.InformationClass = InformationClass;
2288 ulBytesProcessed = OutputLength;
2291 // Send the call to the service
2294 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_PIPE_QUERY_INFO,
2295 AFS_REQUEST_FLAG_SYNCHRONOUS,
2297 &Ccb->DirectoryCB->NameInformation.FileName,
2300 sizeof( AFSPipeInfoRequestCB),
2304 if( ntStatus != STATUS_SUCCESS)
2307 if( NT_SUCCESS( ntStatus))
2310 ntStatus = STATUS_DEVICE_NOT_READY;
2313 try_return( ntStatus);
2316 *BytesReturned = ulBytesProcessed;
2327 AFSReleaseFid( IN AFSFileID *FileId)
2330 NTSTATUS ntStatus = STATUS_SUCCESS;
2335 ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_RELEASE_FID,
2350 AFSIsExtentRequestQueued( IN AFSFileID *FileID,
2351 IN LARGE_INTEGER *ExtentOffset,
2355 BOOLEAN bRequestQueued = FALSE;
2356 NTSTATUS ntStatus = STATUS_SUCCESS;
2357 AFSDeviceExt *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2358 AFSCommSrvcCB *pCommSrvc = NULL;
2359 AFSPoolEntry *pPoolEntry = NULL;
2360 AFSRequestExtentsCB *pRequestExtents = NULL;
2366 pCommSrvc = &pControlDevExt->Specific.Control.CommServiceCB;
2368 AFSAcquireShared( &pCommSrvc->IrpPoolLock,
2371 pPoolEntry = pCommSrvc->RequestPoolHead;
2373 while( pPoolEntry != NULL)
2376 if( pPoolEntry->RequestType == AFS_REQUEST_TYPE_REQUEST_FILE_EXTENTS)
2379 if( AFSIsEqualFID( &pPoolEntry->FileId, FileID))
2382 pRequestExtents = (AFSRequestExtentsCB *)pPoolEntry->Data;
2384 if( pRequestExtents->ByteOffset.QuadPart == ExtentOffset->QuadPart &&
2385 pRequestExtents->Length == Length)
2388 bRequestQueued = TRUE;
2393 pPoolEntry = pPoolEntry->fLink;
2396 AFSReleaseResource( &pCommSrvc->IrpPoolLock);
2399 return bRequestQueued;