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: AFSNameSupport.cpp
39 #include "AFSCommon.h"
42 AFSLocateNameEntry( IN GUID *AuthGroup,
43 IN PFILE_OBJECT FileObject,
44 IN UNICODE_STRING *RootPathName,
45 IN UNICODE_STRING *ParsedPathName,
46 IN AFSNameArrayHdr *NameArray,
48 OUT AFSVolumeCB **VolumeCB,
49 IN OUT AFSDirectoryCB **ParentDirectoryCB,
50 OUT AFSDirectoryCB **DirectoryCB,
51 OUT PUNICODE_STRING ComponentName)
54 NTSTATUS ntStatus = STATUS_SUCCESS;
55 UNICODE_STRING uniPathName, uniComponentName, uniRemainingPath, uniSearchName, uniFullPathName;
57 AFSDirectoryCB *pDirEntry = NULL, *pParentDirEntry = NULL;
58 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
59 UNICODE_STRING uniSysName;
60 ULONG ulSubstituteIndex = 0;
61 BOOLEAN bSubstituteName = FALSE;
62 AFSNameArrayHdr *pNameArray = NameArray;
63 BOOLEAN bAllocatedSymLinkBuffer = FALSE;
64 UNICODE_STRING uniRelativeName, uniNoOpName;
65 AFSObjectInfoCB *pCurrentObject = NULL;
66 AFSObjectInfoCB *pParentObjectInfo = NULL;
67 AFSVolumeCB *pCurrentVolume = *VolumeCB;
68 BOOLEAN bReleaseCurrentVolume = TRUE;
69 BOOLEAN bSubstitutedName = FALSE;
75 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
76 AFS_TRACE_LEVEL_VERBOSE_2,
77 "AFSLocateNameEntry (FO: %08lX) Processing full name %wZ\n",
81 RtlInitUnicodeString( &uniSysName,
84 RtlInitUnicodeString( &uniRelativeName,
87 RtlInitUnicodeString( &uniNoOpName,
91 // Cleanup some parameters
94 if( ComponentName != NULL)
97 ComponentName->Length = 0;
98 ComponentName->MaximumLength = 0;
99 ComponentName->Buffer = NULL;
103 // We will parse through the filename, locating the directory nodes until we encounter a cache miss
104 // Starting at the root node
107 pParentDirEntry = NULL;
109 pDirEntry = *ParentDirectoryCB;
111 uniPathName = *ParsedPathName;
113 uniFullPathName = *RootPathName;
115 uniComponentName.Length = uniComponentName.MaximumLength = 0;
116 uniComponentName.Buffer = NULL;
118 uniRemainingPath.Length = uniRemainingPath.MaximumLength = 0;
119 uniRemainingPath.Buffer = NULL;
121 uniSearchName.Length = uniSearchName.MaximumLength = 0;
122 uniSearchName.Buffer = NULL;
124 ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
130 // Check our total link count for this name array
133 if( pNameArray->LinkCount >= (LONG)pDevExt->Specific.RDR.MaxLinkCount)
136 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
139 pCurrentObject = pDirEntry->ObjectInformation;
141 KeQueryTickCount( &pCurrentObject->LastAccessCount);
144 // Check that the directory entry is not deleted or pending delete
147 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
150 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
151 AFS_TRACE_LEVEL_ERROR,
152 "AFSLocateNameEntry (FO: %08lX) Deleted parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
154 &pDirEntry->NameInformation.FileName,
155 pCurrentObject->FileId.Cell,
156 pCurrentObject->FileId.Volume,
157 pCurrentObject->FileId.Vnode,
158 pCurrentObject->FileId.Unique,
159 STATUS_FILE_DELETED);
161 try_return( ntStatus = STATUS_FILE_DELETED);
164 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
167 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
168 AFS_TRACE_LEVEL_ERROR,
169 "AFSLocateNameEntry (FO: %08lX) Delete pending on %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
171 &pDirEntry->NameInformation.FileName,
172 pCurrentObject->FileId.Cell,
173 pCurrentObject->FileId.Volume,
174 pCurrentObject->FileId.Vnode,
175 pCurrentObject->FileId.Unique,
176 STATUS_DELETE_PENDING);
178 try_return( ntStatus = STATUS_DELETE_PENDING);
182 // Check if the directory requires verification
185 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
186 ( pCurrentObject->FileType != AFS_FILE_TYPE_DIRECTORY ||
187 !AFSIsEnumerationInProcess( pCurrentObject)))
190 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
191 AFS_TRACE_LEVEL_VERBOSE,
192 "AFSLocateNameEntry (FO: %08lX) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
194 &pDirEntry->NameInformation.FileName,
195 pCurrentObject->FileId.Cell,
196 pCurrentObject->FileId.Volume,
197 pCurrentObject->FileId.Vnode,
198 pCurrentObject->FileId.Unique);
201 // Directory TreeLock should be exclusively held
204 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
207 ntStatus = AFSVerifyEntry( AuthGroup,
210 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
212 if( !NT_SUCCESS( ntStatus))
215 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
216 AFS_TRACE_LEVEL_ERROR,
217 "AFSLocateNameEntry (FO: %08lX) Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
219 &pDirEntry->NameInformation.FileName,
220 pCurrentObject->FileId.Cell,
221 pCurrentObject->FileId.Volume,
222 pCurrentObject->FileId.Vnode,
223 pCurrentObject->FileId.Unique,
226 try_return( ntStatus);
231 // Ensure the parent node has been evaluated, if not then go do it now
234 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) ||
235 pCurrentObject->FileType == AFS_FILE_TYPE_UNKNOWN)
238 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
239 AFS_TRACE_LEVEL_VERBOSE,
240 "AFSLocateNameEntry (FO: %08lX) Evaluating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
242 &pDirEntry->NameInformation.FileName,
243 pCurrentObject->FileId.Cell,
244 pCurrentObject->FileId.Volume,
245 pCurrentObject->FileId.Vnode,
246 pCurrentObject->FileId.Unique);
248 ntStatus = AFSEvaluateNode( AuthGroup,
251 if( !NT_SUCCESS( ntStatus))
254 if ( ntStatus == STATUS_NOT_A_DIRECTORY)
257 if ( pCurrentObject->ParentObjectInformation == NULL)
260 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
261 AFS_TRACE_LEVEL_ERROR,
262 "AFSLocateNameEntry (FO: %08lX) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT NULL Status %08lX\n",
264 &pDirEntry->NameInformation.FileName,
265 pCurrentObject->FileId.Cell,
266 pCurrentObject->FileId.Volume,
267 pCurrentObject->FileId.Vnode,
268 pCurrentObject->FileId.Unique,
274 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
275 AFS_TRACE_LEVEL_ERROR,
276 "AFSLocateNameEntry (FO: %08lX) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT %08lX-%08lX-%08lX-%08lX Status %08lX\n",
278 &pDirEntry->NameInformation.FileName,
279 pCurrentObject->FileId.Cell,
280 pCurrentObject->FileId.Volume,
281 pCurrentObject->FileId.Vnode,
282 pCurrentObject->FileId.Unique,
283 pCurrentObject->ParentObjectInformation->FileId.Cell,
284 pCurrentObject->ParentObjectInformation->FileId.Volume,
285 pCurrentObject->ParentObjectInformation->FileId.Vnode,
286 pCurrentObject->ParentObjectInformation->FileId.Unique,
292 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
293 AFS_TRACE_LEVEL_ERROR,
294 "AFSLocateNameEntry (FO: %08lX) Failed to evaluate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
296 &pDirEntry->NameInformation.FileName,
297 pCurrentObject->FileId.Cell,
298 pCurrentObject->FileId.Volume,
299 pCurrentObject->FileId.Vnode,
300 pCurrentObject->FileId.Unique,
304 try_return( ntStatus);
307 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
311 // If this is a mount point or symlink then go get the real directory node
314 switch( pCurrentObject->FileType)
317 case AFS_FILE_TYPE_SYMLINK:
320 UNICODE_STRING uniTempName;
321 WCHAR *pTmpBuffer = NULL;
325 // Check if the flag is set to NOT evaluate a symlink
326 // and we are done with the parsing
329 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL) &&
330 uniRemainingPath.Length == 0)
334 // Pass back the directory entries
337 *ParentDirectoryCB = pParentDirEntry;
339 *DirectoryCB = pDirEntry;
341 *VolumeCB = pCurrentVolume;
343 *RootPathName = uniFullPathName;
345 try_return( ntStatus);
348 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
351 AFSAcquireExcl( &pDirEntry->NonPaged->Lock,
354 if( pDirEntry->NameInformation.TargetName.Length == 0)
358 // We'll reset the DV to ensure we validate the metadata content
361 pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
363 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
365 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
366 AFS_TRACE_LEVEL_VERBOSE,
367 "AFSLocateNameEntry (FO: %08lX) Verifying symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
369 &pDirEntry->NameInformation.FileName,
370 pCurrentObject->FileId.Cell,
371 pCurrentObject->FileId.Volume,
372 pCurrentObject->FileId.Vnode,
373 pCurrentObject->FileId.Unique);
376 // Directory TreeLock should be exclusively held
379 ntStatus = AFSVerifyEntry( AuthGroup,
382 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
384 if( !NT_SUCCESS( ntStatus))
387 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
388 AFS_TRACE_LEVEL_ERROR,
389 "AFSLocateNameEntry (FO: %08lX) Failed to verify symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
391 &pDirEntry->NameInformation.FileName,
392 pCurrentObject->FileId.Cell,
393 pCurrentObject->FileId.Volume,
394 pCurrentObject->FileId.Vnode,
395 pCurrentObject->FileId.Unique,
398 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
400 try_return( ntStatus);
404 // If the type changed then reprocess this entry
407 if( pCurrentObject->FileType != AFS_FILE_TYPE_SYMLINK)
410 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
418 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
422 // If we were given a zero length target name then deny access to the entry
425 if( pDirEntry->NameInformation.TargetName.Length == 0)
428 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
430 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
431 AFS_TRACE_LEVEL_ERROR,
432 "AFSLocateNameEntry (FO: %08lX) Failed to retrieve target name for symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
434 &pDirEntry->NameInformation.FileName,
435 pCurrentObject->FileId.Cell,
436 pCurrentObject->FileId.Volume,
437 pCurrentObject->FileId.Vnode,
438 pCurrentObject->FileId.Unique,
441 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
443 try_return( ntStatus);
446 if( AFSIsRelativeName( &pDirEntry->NameInformation.TargetName))
449 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
450 AFS_TRACE_LEVEL_VERBOSE,
451 "AFSLocateNameEntry (FO: %08lX) Processing relative symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
453 &pDirEntry->NameInformation.TargetName,
454 &pDirEntry->NameInformation.FileName,
455 pCurrentObject->FileId.Cell,
456 pCurrentObject->FileId.Volume,
457 pCurrentObject->FileId.Vnode,
458 pCurrentObject->FileId.Unique);
461 // We'll substitute this name into the current process name
462 // starting at where we sit in the path
465 uniTempName.Length = 0;
466 uniTempName.MaximumLength = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer) +
467 pDirEntry->NameInformation.TargetName.Length +
469 uniRemainingPath.Length;
471 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
472 uniTempName.MaximumLength,
473 AFS_NAME_BUFFER_ONE_TAG);
475 if( uniTempName.Buffer == NULL)
478 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
480 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
484 // We have so first copy in the portion up to the component
488 RtlCopyMemory( uniTempName.Buffer,
489 uniFullPathName.Buffer,
490 (ULONG)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer));
492 uniTempName.Length = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer);
494 if( bAllocatedSymLinkBuffer ||
498 pTmpBuffer = uniFullPathName.Buffer;
501 bAllocatedSymLinkBuffer = TRUE;
504 // Have we parsed this name yet? Better have at least once ...
507 if( uniComponentName.Length == 0)
513 // Copy in the target name ...
516 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
517 pDirEntry->NameInformation.TargetName.Buffer,
518 pDirEntry->NameInformation.TargetName.Length);
520 uniPathName.Buffer = &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)];
522 uniPathName.Length += pDirEntry->NameInformation.TargetName.Length;
523 uniPathName.MaximumLength = uniTempName.MaximumLength;
525 uniTempName.Length += pDirEntry->NameInformation.TargetName.Length;
528 // And now any remaining portion of the name
531 if( uniRemainingPath.Length > 0)
534 if( uniRemainingPath.Buffer[ 0] != L'\\')
537 uniRemainingPath.Buffer--;
538 uniRemainingPath.Length += sizeof( WCHAR);
540 uniPathName.Length += sizeof( WCHAR);
543 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
544 uniRemainingPath.Buffer,
545 uniRemainingPath.Length);
547 uniTempName.Length += uniRemainingPath.Length;
550 uniFullPathName = uniTempName;
552 if( pTmpBuffer != NULL)
555 AFSExFreePool( pTmpBuffer);
558 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
561 // Dereference the current entry ..
564 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
566 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
567 AFS_TRACE_LEVEL_VERBOSE,
568 "AFSLocateNameEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
569 &pDirEntry->NameInformation.FileName,
575 // OK, need to back up one entry for the correct parent since the current
576 // entry we are on is the symlink itself
579 pDirEntry = AFSBackupEntry( pNameArray);
582 // Increment our reference on this dir entry
585 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
587 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
588 AFS_TRACE_LEVEL_VERBOSE,
589 "AFSLocateNameEntry Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
590 &pDirEntry->NameInformation.FileName,
595 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
598 pParentDirEntry = NULL;
603 pParentDirEntry = AFSGetParentEntry( pNameArray);
605 ASSERT( pParentDirEntry != pDirEntry);
611 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
612 AFS_TRACE_LEVEL_VERBOSE,
613 "AFSLocateNameEntry (FO: %08lX) Processing absolute symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
615 &pDirEntry->NameInformation.TargetName,
616 &pDirEntry->NameInformation.FileName,
617 pCurrentObject->FileId.Cell,
618 pCurrentObject->FileId.Volume,
619 pCurrentObject->FileId.Vnode,
620 pCurrentObject->FileId.Unique);
623 // We'll substitute this name into the current process name
624 // starting at where we sit in the path
627 uniTempName.Length = 0;
628 uniTempName.MaximumLength = pDirEntry->NameInformation.TargetName.Length +
630 uniRemainingPath.Length;
632 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
633 uniTempName.MaximumLength,
634 AFS_NAME_BUFFER_TWO_TAG);
636 if( uniTempName.Buffer == NULL)
639 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
641 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
644 if( bAllocatedSymLinkBuffer ||
648 pTmpBuffer = uniFullPathName.Buffer;
651 bAllocatedSymLinkBuffer = TRUE;
654 // Have we parsed this name yet? Better have at least once ...
657 if( uniComponentName.Length == 0)
663 // Copy in the target name ...
666 RtlCopyMemory( uniTempName.Buffer,
667 pDirEntry->NameInformation.TargetName.Buffer,
668 pDirEntry->NameInformation.TargetName.Length);
670 uniTempName.Length = pDirEntry->NameInformation.TargetName.Length;
673 // And now any remaining portion of the name
676 if( uniRemainingPath.Length > 0)
679 if( uniRemainingPath.Buffer[ 0] != L'\\')
682 uniRemainingPath.Buffer--;
683 uniRemainingPath.Length += sizeof( WCHAR);
686 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
687 uniRemainingPath.Buffer,
688 uniRemainingPath.Length);
690 uniTempName.Length += uniRemainingPath.Length;
693 uniFullPathName = uniTempName;
695 uniPathName = uniTempName;
697 if( pTmpBuffer != NULL)
700 AFSExFreePool( pTmpBuffer);
703 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
706 // If our current volume is not the global root then make it so ...
709 if( pCurrentVolume != AFSGlobalRoot)
712 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
713 AFS_TRACE_LEVEL_VERBOSE,
714 "AFSLocateNameEntry (FO: %08lX) Current volume not global, resetting for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
716 &pDirEntry->NameInformation.FileName,
717 pCurrentObject->FileId.Cell,
718 pCurrentObject->FileId.Volume,
719 pCurrentObject->FileId.Vnode,
720 pCurrentObject->FileId.Unique);
722 lCount = InterlockedDecrement( &pCurrentVolume->VolumeReferenceCount);
724 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
725 AFS_TRACE_LEVEL_VERBOSE,
726 "AFSLocateNameEntry Decrement count on volume %08lX Cnt %d\n",
730 pCurrentVolume = AFSGlobalRoot;
732 lCount = InterlockedIncrement( &pCurrentVolume->VolumeReferenceCount);
734 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
735 AFS_TRACE_LEVEL_VERBOSE,
736 "AFSLocateNameEntry Increment count on volume %08lX Cnt %d\n",
742 // Dereference our current dir entry
745 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
747 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
748 AFS_TRACE_LEVEL_VERBOSE,
749 "AFSLocateNameEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
750 &pDirEntry->NameInformation.FileName,
755 pDirEntry = pCurrentVolume->DirectoryCB;
758 // Reference the new dir entry
761 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
763 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
764 AFS_TRACE_LEVEL_VERBOSE,
765 "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
766 &pDirEntry->NameInformation.FileName,
772 // Reset the name array
773 // Persist the link count in the name array
776 lLinkCount = pNameArray->LinkCount;
778 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
779 AFS_TRACE_LEVEL_VERBOSE,
780 "AFSLocateNameEntry (FO: %08lX) Resetting name array for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
782 &pDirEntry->NameInformation.FileName,
783 pCurrentObject->FileId.Cell,
784 pCurrentObject->FileId.Volume,
785 pCurrentObject->FileId.Vnode,
786 pCurrentObject->FileId.Unique);
788 AFSResetNameArray( pNameArray,
791 pNameArray->LinkCount = lLinkCount;
794 // Process over the \\<Global root> portion of the name
797 FsRtlDissectName( uniPathName,
801 if( RtlCompareUnicodeString( &uniComponentName,
806 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
807 AFS_TRACE_LEVEL_ERROR,
808 "AFSLocateNameEntry Name %wZ contains invalid server name\n",
812 // The correct response would be STATUS_OBJECT_PATH_INVALID
813 // but that prevents cmd.exe from performing a recursive
814 // directory enumeration when opening a directory entry
815 // that represents a symlink to an invalid path is discovered.
817 try_return( ntStatus = STATUS_OBJECT_PATH_NOT_FOUND);
820 uniPathName = uniRemainingPath;
822 pParentDirEntry = NULL;
826 // Increment our link count
829 lCount = InterlockedIncrement( &pNameArray->LinkCount);
834 case AFS_FILE_TYPE_MOUNTPOINT:
838 // Check if the flag is set to NOT evaluate a mount point
839 // and we are done with the parsing
842 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL) &&
843 uniRemainingPath.Length == 0)
847 // Pass back the directory entries
850 *ParentDirectoryCB = pParentDirEntry;
852 *DirectoryCB = pDirEntry;
854 *VolumeCB = pCurrentVolume;
856 *RootPathName = uniFullPathName;
858 try_return( ntStatus);
861 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
862 AFS_TRACE_LEVEL_VERBOSE,
863 "AFSLocateNameEntry (FO: %08lX) Building MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
865 &pDirEntry->NameInformation.FileName,
866 pCurrentObject->FileId.Cell,
867 pCurrentObject->FileId.Volume,
868 pCurrentObject->FileId.Vnode,
869 pCurrentObject->FileId.Unique);
872 // Go retrieve the target entry for this node
873 // Release the current volume cb entry since we would
874 // have lock inversion in the following call
875 // Also decrement the ref count on the volume
878 ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
880 lCount = InterlockedDecrement( &pCurrentVolume->VolumeReferenceCount);
882 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
883 AFS_TRACE_LEVEL_VERBOSE,
884 "AFSLocateNameEntry Decrement2 count on volume %08lX Cnt %d\n",
886 pCurrentVolume->VolumeReferenceCount);
888 ntStatus = AFSBuildMountPointTarget( AuthGroup,
892 if( !NT_SUCCESS( ntStatus))
895 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
896 AFS_TRACE_LEVEL_ERROR,
897 "AFSLocateNameEntry (FO: %08lX) Failed to build MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
899 &pDirEntry->NameInformation.FileName,
900 pCurrentObject->FileId.Cell,
901 pCurrentObject->FileId.Volume,
902 pCurrentObject->FileId.Vnode,
903 pCurrentObject->FileId.Unique,
907 // We already decremented the current volume above
910 bReleaseCurrentVolume = FALSE;
912 try_return( ntStatus);
915 ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
918 // Replace the current name for the mp with the volume root of the target
921 AFSReplaceCurrentElement( pNameArray,
922 pCurrentVolume->DirectoryCB);
925 // We want to restart processing here on the new parent ...
926 // Deref and ref count the entries
929 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
931 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
932 AFS_TRACE_LEVEL_VERBOSE,
933 "AFSLocateNameEntry Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
934 &pDirEntry->NameInformation.FileName,
939 pDirEntry = pCurrentVolume->DirectoryCB;
941 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
943 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
944 AFS_TRACE_LEVEL_VERBOSE,
945 "AFSLocateNameEntry Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
946 &pDirEntry->NameInformation.FileName,
951 pParentDirEntry = NULL;
954 // Increment our link count
957 lCount = InterlockedIncrement( &pNameArray->LinkCount);
962 case AFS_FILE_TYPE_DFSLINK:
965 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL))
969 // Pass back the directory entries
972 *ParentDirectoryCB = pParentDirEntry;
974 *DirectoryCB = pDirEntry;
976 *VolumeCB = pCurrentVolume;
978 *RootPathName = uniFullPathName;
980 try_return( ntStatus);
984 // This is a DFS link so we need to update the file name and return STATUS_REPARSE to the
985 // system for it to reevaluate it
988 if( FileObject != NULL)
991 ntStatus = AFSProcessDFSLink( pDirEntry,
1000 // This is where we have been re-entered from an NP evaluation call via the BuildBranch()
1004 ntStatus = STATUS_INVALID_PARAMETER;
1007 if( ntStatus != STATUS_SUCCESS &&
1008 ntStatus != STATUS_REPARSE)
1011 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1012 AFS_TRACE_LEVEL_ERROR,
1013 "AFSLocateNameEntry (FO: %08lX) Failed to process DFSLink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1015 &pDirEntry->NameInformation.FileName,
1016 pCurrentObject->FileId.Cell,
1017 pCurrentObject->FileId.Volume,
1018 pCurrentObject->FileId.Vnode,
1019 pCurrentObject->FileId.Unique,
1023 try_return( ntStatus);
1026 case AFS_FILE_TYPE_UNKNOWN:
1027 case AFS_FILE_TYPE_INVALID:
1031 // Something was not processed ...
1034 try_return( ntStatus = STATUS_ACCESS_DENIED);
1037 } /* end of switch */
1040 // If the parent is not initialized then do it now
1043 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1044 !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1047 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1048 AFS_TRACE_LEVEL_VERBOSE,
1049 "AFSLocateNameEntry (FO: %08lX) Enumerating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1051 &pDirEntry->NameInformation.FileName,
1052 pCurrentObject->FileId.Cell,
1053 pCurrentObject->FileId.Volume,
1054 pCurrentObject->FileId.Vnode,
1055 pCurrentObject->FileId.Unique);
1057 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1060 if( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1063 ntStatus = AFSEnumerateDirectory( AuthGroup,
1067 if( !NT_SUCCESS( ntStatus))
1070 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1072 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1073 AFS_TRACE_LEVEL_ERROR,
1074 "AFSLocateNameEntry (FO: %08lX) Failed to enumerate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1076 &pDirEntry->NameInformation.FileName,
1077 pCurrentObject->FileId.Cell,
1078 pCurrentObject->FileId.Volume,
1079 pCurrentObject->FileId.Vnode,
1080 pCurrentObject->FileId.Unique,
1083 try_return( ntStatus);
1086 SetFlag( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1089 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1091 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1094 if( uniPathName.Length > 0)
1097 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1098 AFS_TRACE_LEVEL_ERROR,
1099 "AFSLocateNameEntry (FO: %08lX) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1101 &pDirEntry->NameInformation.FileName,
1102 pCurrentObject->FileId.Cell,
1103 pCurrentObject->FileId.Volume,
1104 pCurrentObject->FileId.Vnode,
1105 pCurrentObject->FileId.Unique);
1107 // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1108 // one of the components of the path is not a directory. However, returning
1109 // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1110 // Instead IIS insists on treating the target file as if it is a directory containing
1111 // a potential web.config file. NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1112 // AFS will follow suit.
1114 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1119 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1120 AFS_TRACE_LEVEL_VERBOSE,
1121 "AFSLocateNameEntry (FO: %08lX) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1123 &pDirEntry->NameInformation.FileName,
1124 pCurrentObject->FileId.Cell,
1125 pCurrentObject->FileId.Volume,
1126 pCurrentObject->FileId.Vnode,
1127 pCurrentObject->FileId.Unique);
1130 // Pass back the directory entries
1133 *ParentDirectoryCB = pParentDirEntry;
1135 *DirectoryCB = pDirEntry;
1137 *VolumeCB = pCurrentVolume;
1139 *RootPathName = uniFullPathName;
1142 try_return( ntStatus);
1146 // If we are at the end of the processing, set our returned information and get out
1149 if( uniPathName.Length == 0)
1152 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1153 AFS_TRACE_LEVEL_VERBOSE,
1154 "AFSLocateNameEntry (FO: %08lX) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1156 &pDirEntry->NameInformation.FileName,
1157 pCurrentObject->FileId.Cell,
1158 pCurrentObject->FileId.Volume,
1159 pCurrentObject->FileId.Vnode,
1160 pCurrentObject->FileId.Unique);
1163 // Pass back the directory entries
1166 *ParentDirectoryCB = pParentDirEntry;
1168 *DirectoryCB = pDirEntry;
1170 *VolumeCB = pCurrentVolume;
1172 *RootPathName = uniFullPathName;
1174 try_return( ntStatus);
1178 // We may have returned to the top of the while( TRUE)
1180 if( bSubstituteName &&
1181 uniSearchName.Buffer != NULL)
1184 AFSExFreePool( uniSearchName.Buffer);
1186 bSubstituteName = FALSE;
1188 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1189 uniSearchName.Buffer = NULL;
1192 ulSubstituteIndex = 1;
1194 ntStatus = STATUS_SUCCESS;
1197 // Get the next component name
1200 FsRtlDissectName( uniPathName,
1205 // Check for the . and .. in the path
1208 if( RtlCompareUnicodeString( &uniComponentName,
1213 uniPathName = uniRemainingPath;
1218 if( RtlCompareUnicodeString( &uniComponentName,
1223 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1224 AFS_TRACE_LEVEL_VERBOSE,
1225 "AFSLocateNameEntry (FO: %08lX) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1227 &pDirEntry->NameInformation.FileName,
1228 pCurrentObject->FileId.Cell,
1229 pCurrentObject->FileId.Volume,
1230 pCurrentObject->FileId.Vnode,
1231 pCurrentObject->FileId.Unique);
1234 // Need to back up one entry in the name array
1236 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
1238 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1239 AFS_TRACE_LEVEL_VERBOSE,
1240 "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1241 &pDirEntry->NameInformation.FileName,
1246 pDirEntry = AFSBackupEntry( NameArray);
1248 if( pDirEntry == NULL)
1251 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1252 AFS_TRACE_LEVEL_ERROR,
1253 "AFSLocateNameEntry AFSBackupEntry failed\n");
1255 try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1258 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1260 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1263 pParentDirEntry = NULL;
1268 pParentDirEntry = AFSGetParentEntry( pNameArray);
1270 ASSERT( pParentDirEntry != pDirEntry);
1273 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1274 AFS_TRACE_LEVEL_VERBOSE,
1275 "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1276 &pDirEntry->NameInformation.FileName,
1279 pDirEntry->OpenReferenceCount);
1281 uniPathName = uniRemainingPath;
1287 // Update our pointers
1290 pParentDirEntry = pDirEntry;
1294 uniSearchName = uniComponentName;
1296 while( pDirEntry == NULL)
1300 // If the SearchName contains @SYS then we perform the substitution.
1301 // If there is no substitution we give up.
1304 if( !bSubstituteName &&
1305 FsRtlIsNameInExpression( &uniSysName,
1311 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1312 AFS_TRACE_LEVEL_VERBOSE_2,
1313 "AFSLocateNameEntry (FO: %08lX) Processing @SYS substitution for %wZ Index %08lX\n",
1318 ntStatus = AFSSubstituteSysName( &uniComponentName,
1322 if ( NT_SUCCESS( ntStatus))
1325 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1326 AFS_TRACE_LEVEL_VERBOSE_2,
1327 "AFSLocateNameEntry (FO: %08lX) Located substitution %wZ for %wZ Index %08lX\n",
1334 // Go reparse the name again
1337 bSubstituteName = TRUE;
1339 ulSubstituteIndex++; // For the next entry, if needed
1341 continue; // while( pDirEntry == NULL)
1346 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1347 AFS_TRACE_LEVEL_ERROR,
1348 "AFSLocateNameEntry (FO: %08lX) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1354 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1358 // Pass back the directory entries
1361 *ParentDirectoryCB = pParentDirEntry;
1363 *DirectoryCB = NULL;
1365 *VolumeCB = pCurrentVolume;
1367 if( ComponentName != NULL)
1370 *ComponentName = uniComponentName;
1373 *RootPathName = uniFullPathName;
1377 // We can't possibly have a pDirEntry since the lookup failed
1379 try_return( ntStatus);
1384 // Generate the CRC on the node and perform a case sensitive lookup
1387 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1388 AFS_TRACE_LEVEL_VERBOSE_2,
1389 "AFSLocateNameEntry (FO: %08lX) Searching for entry %wZ case sensitive\n",
1393 ulCRC = AFSGenerateCRC( &uniSearchName,
1396 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1399 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1403 if( pDirEntry == NULL)
1407 // Missed so perform a case insensitive lookup
1410 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1411 AFS_TRACE_LEVEL_VERBOSE_2,
1412 "AFSLocateNameEntry (FO: %08lX) Searching for entry %wZ case insensitive\n",
1416 ulCRC = AFSGenerateCRC( &uniSearchName,
1419 AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1423 if( pDirEntry == NULL)
1427 // OK, if this component is a valid short name then try
1428 // a lookup in the short name tree
1431 if( RtlIsNameLegalDOS8Dot3( &uniSearchName,
1436 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1437 AFS_TRACE_LEVEL_VERBOSE_2,
1438 "AFSLocateNameEntry (FO: %08lX) Searching for entry %wZ short name\n",
1442 AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1447 if( pDirEntry == NULL)
1451 // If we substituted a name then reset our search name and try again
1454 if( bSubstituteName)
1457 AFSExFreePool( uniSearchName.Buffer);
1459 uniSearchName = uniComponentName;
1461 bSubstituteName = FALSE;
1463 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1465 continue; // while( pDirEntry == NULL)
1468 if( uniRemainingPath.Length > 0)
1471 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1476 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1478 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1479 AFS_TRACE_LEVEL_VERBOSE,
1480 "AFSLocateNameEntry (FO: %08lX) Returning name not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1483 pCurrentObject->FileId.Cell,
1484 pCurrentObject->FileId.Volume,
1485 pCurrentObject->FileId.Vnode,
1486 pCurrentObject->FileId.Unique);
1489 // Pass back the directory entries
1492 *ParentDirectoryCB = pParentDirEntry;
1494 *DirectoryCB = NULL;
1496 *VolumeCB = pCurrentVolume;
1498 if( ComponentName != NULL)
1501 *ComponentName = uniComponentName;
1504 *RootPathName = uniFullPathName;
1507 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1510 // Node name not found so get out
1513 try_return( ntStatus); // while( pDirEntry == NULL)
1520 // Here we have a match on the case insensitive lookup for the name. If there
1521 // Is more than one link entry for this node then fail the lookup request
1524 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1525 pDirEntry->CaseInsensitiveList.fLink != NULL)
1528 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1530 try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1535 if( pDirEntry != NULL)
1539 // If the verify flag is set on the parent and the current entry is deleted
1540 // revalidate the parent and search again.
1543 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1544 BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1547 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1549 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1550 AFS_TRACE_LEVEL_VERBOSE,
1551 "AFSLocateNameEntry (FO: %08lX) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1553 &pParentDirEntry->NameInformation.FileName,
1554 pParentDirEntry->ObjectInformation->FileId.Cell,
1555 pParentDirEntry->ObjectInformation->FileId.Volume,
1556 pParentDirEntry->ObjectInformation->FileId.Vnode,
1557 pParentDirEntry->ObjectInformation->FileId.Unique);
1560 // Directory TreeLock should be exclusively held
1563 AFSAcquireExcl( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1566 ntStatus = AFSVerifyEntry( AuthGroup,
1569 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1571 if( !NT_SUCCESS( ntStatus))
1574 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1575 AFS_TRACE_LEVEL_ERROR,
1576 "AFSLocateNameEntry (FO: %08lX) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1578 &pParentDirEntry->NameInformation.FileName,
1579 pParentDirEntry->ObjectInformation->FileId.Cell,
1580 pParentDirEntry->ObjectInformation->FileId.Volume,
1581 pParentDirEntry->ObjectInformation->FileId.Vnode,
1582 pParentDirEntry->ObjectInformation->FileId.Unique,
1585 try_return( ntStatus);
1588 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1589 AFS_TRACE_LEVEL_VERBOSE,
1590 "AFSLocateNameEntry (FO: %08lX) Reprocessing component %wZ in parent %wZ\n",
1593 &pParentDirEntry->NameInformation.FileName);
1602 // Increment our dir entry ref count
1605 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1607 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1608 AFS_TRACE_LEVEL_VERBOSE,
1609 "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1610 &pDirEntry->NameInformation.FileName,
1616 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1618 } // End while( pDirEntry == NULL)
1621 // If we have a dirEntry for this component, perform some basic validation on it
1624 if( pDirEntry != NULL &&
1625 BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1628 pCurrentObject = pDirEntry->ObjectInformation;
1630 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1631 AFS_TRACE_LEVEL_ERROR,
1632 "AFSLocateNameEntry (FO: %08lX) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1634 &pDirEntry->NameInformation.FileName,
1635 pCurrentObject->FileId.Cell,
1636 pCurrentObject->FileId.Volume,
1637 pCurrentObject->FileId.Vnode,
1638 pCurrentObject->FileId.Unique);
1641 // This entry was deleted through the invalidation call back so perform cleanup
1645 ASSERT( pCurrentObject->ParentObjectInformation != NULL);
1647 AFSAcquireExcl( pCurrentObject->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1650 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1653 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
1658 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1659 AFS_TRACE_LEVEL_VERBOSE,
1660 "AFSLocateNameEntry Deleting dir entry %08lX (%08lX) for %wZ\n",
1663 &pDirEntry->NameInformation.FileName);
1666 // Remove and delete the directory entry from the parent list
1669 AFSDeleteDirEntry( pCurrentObject->ParentObjectInformation,
1672 if( pCurrentObject->ObjectReferenceCount == 0)
1675 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
1678 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1679 AFS_TRACE_LEVEL_VERBOSE,
1680 "AFSLocateNameEntry Removing object %08lX from volume tree\n",
1683 AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
1684 &pCurrentObject->TreeEntry);
1686 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
1693 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1694 AFS_TRACE_LEVEL_VERBOSE,
1695 "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
1697 &pDirEntry->NameInformation.FileName);
1699 SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
1701 AFSRemoveNameEntry( pCurrentObject->ParentObjectInformation,
1705 AFSReleaseResource( pCurrentObject->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1707 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
1710 // We deleted the dir entry so check if there is any remaining portion
1711 // of the name to process.
1714 if( uniRemainingPath.Length > 0)
1716 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1721 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1723 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1724 AFS_TRACE_LEVEL_VERBOSE,
1725 "AFSLocateNameEntry (FO: %08lX) Returning name not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1728 pCurrentObject->FileId.Cell,
1729 pCurrentObject->FileId.Volume,
1730 pCurrentObject->FileId.Vnode,
1731 pCurrentObject->FileId.Unique);
1734 // Pass back the directory entries
1737 *ParentDirectoryCB = pParentDirEntry;
1739 *DirectoryCB = NULL;
1741 *VolumeCB = pCurrentVolume;
1743 if( ComponentName != NULL)
1746 *ComponentName = uniComponentName;
1749 *RootPathName = uniFullPathName;
1753 if( ntStatus != STATUS_SUCCESS)
1756 try_return( ntStatus);
1760 // Decrement the previous parent
1763 lCount = InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
1765 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1766 AFS_TRACE_LEVEL_VERBOSE,
1767 "AFSLocateNameEntry Decrement5 count on Parent %wZ DE %p Ccb %p Cnt %d\n",
1768 &pParentDirEntry->NameInformation.FileName,
1774 // If we ended up substituting a name in the component then update
1775 // the full path and update the pointers
1778 if( bSubstituteName)
1781 BOOLEAN bRelativeOpen = FALSE;
1783 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1784 AFS_TRACE_LEVEL_VERBOSE_2,
1785 "AFSLocateNameEntry (FO: %08lX) Substituting %wZ into %wZ Index %08lX\n",
1791 if( FileObject != NULL &&
1792 FileObject->RelatedFileObject != NULL)
1795 bRelativeOpen = TRUE;
1799 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
1800 // and free the prior Buffer contents but only if the fourth
1801 // parameter is TRUE.
1804 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
1809 bAllocatedSymLinkBuffer ||
1812 if( !NT_SUCCESS( ntStatus))
1815 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1816 AFS_TRACE_LEVEL_ERROR,
1817 "AFSLocateNameEntry (FO: %08lX) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
1824 try_return( ntStatus);
1828 // We have substituted a name into the buffer so if we do this again for this
1829 // path, we need to free up the buffer we allocated.
1832 bSubstitutedName = TRUE;
1836 // Update the search parameters
1839 uniPathName = uniRemainingPath;
1842 // Check if the is a SymLink entry but has no Target FileID or Name. In this
1843 // case it might be a DFS Link so let's go and evaluate it to be sure
1846 if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
1847 pCurrentObject->TargetFileId.Vnode == 0 &&
1848 pCurrentObject->TargetFileId.Unique == 0 &&
1849 pDirEntry->NameInformation.TargetName.Length == 0)
1852 ntStatus = AFSValidateSymLink( AuthGroup,
1855 if( !NT_SUCCESS( ntStatus))
1858 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1859 AFS_TRACE_LEVEL_ERROR,
1860 "AFSLocateNameEntry (FO: %08lX) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1862 &pDirEntry->NameInformation.FileName,
1863 pCurrentObject->FileId.Cell,
1864 pCurrentObject->FileId.Volume,
1865 pCurrentObject->FileId.Vnode,
1866 pCurrentObject->FileId.Unique,
1869 try_return( ntStatus);
1874 // Update the name array
1877 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1878 AFS_TRACE_LEVEL_VERBOSE,
1879 "AFSLocateNameEntry (FO: %08lX) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1881 &pDirEntry->NameInformation.FileName,
1882 pCurrentObject->FileId.Cell,
1883 pCurrentObject->FileId.Volume,
1884 pCurrentObject->FileId.Vnode,
1885 pCurrentObject->FileId.Unique);
1887 ntStatus = AFSInsertNextElement( pNameArray,
1890 if( !NT_SUCCESS( ntStatus))
1893 try_return( ntStatus);
1899 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1900 AFS_TRACE_LEVEL_VERBOSE,
1901 "AFSLocateNameEntry (FO: %08lX) Completed processing %wZ Status %08lX\n",
1906 if( ( !NT_SUCCESS( ntStatus) &&
1907 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
1908 ntStatus == STATUS_REPARSE)
1911 if( pDirEntry != NULL)
1914 lCount = InterlockedDecrement( &pDirEntry->OpenReferenceCount);
1916 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1917 AFS_TRACE_LEVEL_VERBOSE,
1918 "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
1919 &pDirEntry->NameInformation.FileName,
1924 else if( pParentDirEntry != NULL)
1927 lCount = InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
1929 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1930 AFS_TRACE_LEVEL_VERBOSE,
1931 "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
1932 &pParentDirEntry->NameInformation.FileName,
1938 if( bReleaseCurrentVolume)
1941 ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
1943 lCount = InterlockedDecrement( &pCurrentVolume->VolumeReferenceCount);
1945 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1946 AFS_TRACE_LEVEL_VERBOSE,
1947 "AFSLocateNameEntry Decrement3 count on volume %08lX Cnt %d\n",
1952 if( RootPathName->Buffer != uniFullPathName.Buffer)
1955 AFSExFreePool( uniFullPathName.Buffer);
1961 if( *ParentDirectoryCB != NULL)
1964 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1965 AFS_TRACE_LEVEL_VERBOSE,
1966 "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
1967 &(*ParentDirectoryCB)->NameInformation.FileName,
1970 (*ParentDirectoryCB)->OpenReferenceCount);
1973 if( *DirectoryCB != NULL)
1976 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1977 AFS_TRACE_LEVEL_VERBOSE,
1978 "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
1979 &(*DirectoryCB)->NameInformation.FileName,
1982 (*DirectoryCB)->OpenReferenceCount);
1986 if( bSubstituteName &&
1987 uniSearchName.Buffer != NULL)
1990 AFSExFreePool( uniSearchName.Buffer);
1998 AFSCreateDirEntry( IN GUID *AuthGroup,
1999 IN AFSObjectInfoCB *ParentObjectInfo,
2000 IN AFSDirectoryCB *ParentDirCB,
2001 IN PUNICODE_STRING FileName,
2002 IN PUNICODE_STRING ComponentName,
2003 IN ULONG Attributes,
2004 IN OUT AFSDirectoryCB **DirEntry)
2007 NTSTATUS ntStatus = STATUS_SUCCESS;
2008 AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
2009 UNICODE_STRING uniShortName;
2010 LARGE_INTEGER liFileSize = {0,0};
2016 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2017 AFS_TRACE_LEVEL_VERBOSE_2,
2018 "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
2019 &ParentDirCB->NameInformation.FileName,
2020 ParentObjectInfo->FileId.Cell,
2021 ParentObjectInfo->FileId.Volume,
2022 ParentObjectInfo->FileId.Vnode,
2023 ParentObjectInfo->FileId.Unique,
2028 // OK, before inserting the node into the parent tree, issue
2029 // the request to the service for node creation
2030 // We will need to drop the lock on the parent node since the create
2031 // could cause a callback into the file system to invalidate it's cache
2034 ntStatus = AFSNotifyFileCreate( AuthGroup,
2042 // If the returned status is STATUS_REPARSE then the entry exists
2043 // and we raced, get out.
2045 if( ntStatus == STATUS_REPARSE)
2048 *DirEntry = pDirNode;
2050 try_return( ntStatus = STATUS_SUCCESS);
2053 if( !NT_SUCCESS( ntStatus))
2056 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2057 AFS_TRACE_LEVEL_ERROR,
2058 "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
2059 &ParentDirCB->NameInformation.FileName,
2060 ParentObjectInfo->FileId.Cell,
2061 ParentObjectInfo->FileId.Volume,
2062 ParentObjectInfo->FileId.Vnode,
2063 ParentObjectInfo->FileId.Unique,
2068 try_return( ntStatus);
2071 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2075 // Before attempting to insert the new entry, check if we need to validate the parent
2078 if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2081 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2082 AFS_TRACE_LEVEL_VERBOSE,
2083 "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2084 &ParentDirCB->NameInformation.FileName,
2085 ParentObjectInfo->FileId.Cell,
2086 ParentObjectInfo->FileId.Volume,
2087 ParentObjectInfo->FileId.Vnode,
2088 ParentObjectInfo->FileId.Unique);
2090 ntStatus = AFSVerifyEntry( AuthGroup,
2093 if( !NT_SUCCESS( ntStatus))
2096 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2097 AFS_TRACE_LEVEL_ERROR,
2098 "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2099 &ParentDirCB->NameInformation.FileName,
2100 ParentObjectInfo->FileId.Cell,
2101 ParentObjectInfo->FileId.Volume,
2102 ParentObjectInfo->FileId.Vnode,
2103 ParentObjectInfo->FileId.Unique,
2106 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2108 try_return( ntStatus);
2113 // Check for the entry in the event we raced with some other thread
2116 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2117 (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2120 if( pExistingDirNode != NULL)
2122 if (AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2123 &pExistingDirNode->ObjectInformation->FileId))
2126 AFSDeleteDirEntry( ParentObjectInfo,
2129 lCount = InterlockedIncrement( &pExistingDirNode->OpenReferenceCount);
2131 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2132 AFS_TRACE_LEVEL_VERBOSE,
2133 "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2134 &pExistingDirNode->NameInformation.FileName,
2138 *DirEntry = pExistingDirNode;
2140 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2142 try_return( ntStatus = STATUS_SUCCESS);
2148 // Need to tear down this entry and rebuild it below
2151 if( pExistingDirNode->OpenReferenceCount == 0)
2154 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2155 AFS_TRACE_LEVEL_VERBOSE,
2156 "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2158 &pExistingDirNode->NameInformation.FileName,
2159 pExistingDirNode->ObjectInformation->FileId.Cell,
2160 pExistingDirNode->ObjectInformation->FileId.Volume,
2161 pExistingDirNode->ObjectInformation->FileId.Vnode,
2162 pExistingDirNode->ObjectInformation->FileId.Unique,
2163 pDirNode->ObjectInformation->FileId.Cell,
2164 pDirNode->ObjectInformation->FileId.Volume,
2165 pDirNode->ObjectInformation->FileId.Vnode,
2166 pDirNode->ObjectInformation->FileId.Unique);
2168 AFSDeleteDirEntry( ParentObjectInfo,
2174 SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2176 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2177 AFS_TRACE_LEVEL_VERBOSE,
2178 "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2180 &pExistingDirNode->NameInformation.FileName,
2181 pExistingDirNode->ObjectInformation->FileId.Cell,
2182 pExistingDirNode->ObjectInformation->FileId.Volume,
2183 pExistingDirNode->ObjectInformation->FileId.Vnode,
2184 pExistingDirNode->ObjectInformation->FileId.Unique,
2185 pDirNode->ObjectInformation->FileId.Cell,
2186 pDirNode->ObjectInformation->FileId.Volume,
2187 pDirNode->ObjectInformation->FileId.Vnode,
2188 pDirNode->ObjectInformation->FileId.Unique);
2190 AFSRemoveNameEntry( ParentObjectInfo,
2197 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2198 AFS_TRACE_LEVEL_VERBOSE_2,
2199 "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2200 &ParentDirCB->NameInformation.FileName,
2201 ParentObjectInfo->FileId.Cell,
2202 ParentObjectInfo->FileId.Volume,
2203 ParentObjectInfo->FileId.Vnode,
2204 ParentObjectInfo->FileId.Unique,
2208 // Insert the directory node
2211 AFSInsertDirectoryNode( ParentObjectInfo,
2215 lCount = InterlockedIncrement( &pDirNode->OpenReferenceCount);
2217 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2218 AFS_TRACE_LEVEL_VERBOSE,
2219 "AFSCreateDirEntry Increment2 count on %wZ DE %p Cnt %d\n",
2220 &pDirNode->NameInformation.FileName,
2225 // Pass back the dir entry
2228 *DirEntry = pDirNode;
2230 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2241 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2242 IN AFSDirectoryCB *DirEntry,
2243 IN BOOLEAN InsertInEnumList)
2251 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2254 // Insert the node into the directory node tree
2257 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2258 AFS_TRACE_LEVEL_VERBOSE,
2259 "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2261 &DirEntry->NameInformation.FileName);
2263 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2265 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2268 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2270 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2271 AFS_TRACE_LEVEL_VERBOSE,
2272 "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2274 &DirEntry->NameInformation.FileName);
2279 AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2282 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2283 AFS_TRACE_LEVEL_VERBOSE,
2284 "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2286 &DirEntry->NameInformation.FileName);
2289 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2292 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2294 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2296 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2297 AFS_TRACE_LEVEL_VERBOSE,
2298 "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2300 &DirEntry->NameInformation.FileName);
2305 AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2308 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2309 AFS_TRACE_LEVEL_VERBOSE,
2310 "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2312 &DirEntry->NameInformation.FileName);
2316 // Into the shortname tree
2319 if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2322 if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2325 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2327 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2328 AFS_TRACE_LEVEL_VERBOSE,
2329 "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2331 &DirEntry->NameInformation.FileName);
2333 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2338 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2341 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2342 AFS_TRACE_LEVEL_VERBOSE,
2343 "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2345 &DirEntry->NameInformation.FileName);
2349 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2351 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2352 AFS_TRACE_LEVEL_VERBOSE,
2353 "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2355 &DirEntry->NameInformation.FileName);
2360 if( InsertInEnumList)
2364 // And insert the node into the directory list
2367 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2368 AFS_TRACE_LEVEL_VERBOSE,
2369 "AFSInsertDirectoryNode Inserting entry %08lX %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2371 &DirEntry->NameInformation.FileName,
2372 DirEntry->ObjectInformation->FileId.Cell,
2373 DirEntry->ObjectInformation->FileId.Volume,
2374 DirEntry->ObjectInformation->FileId.Vnode,
2375 DirEntry->ObjectInformation->FileId.Unique);
2377 if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2380 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2385 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2387 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2390 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2392 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2394 lCount = InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2396 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2397 AFS_TRACE_LEVEL_VERBOSE,
2398 "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2399 &DirEntry->NameInformation.FileName,
2401 ParentObjectInfo->FileId.Cell,
2402 ParentObjectInfo->FileId.Volume,
2403 ParentObjectInfo->FileId.Vnode,
2404 ParentObjectInfo->FileId.Unique);
2412 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2413 IN AFSDirectoryCB *DirEntry)
2416 NTSTATUS ntStatus = STATUS_SUCCESS;
2422 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2423 AFS_TRACE_LEVEL_VERBOSE,
2424 "AFSDeleteDirEntry Deleting dir entry in parent %08lX Entry %08lX %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2427 &DirEntry->NameInformation.FileName,
2428 DirEntry->ObjectInformation->FileId.Cell,
2429 DirEntry->ObjectInformation->FileId.Volume,
2430 DirEntry->ObjectInformation->FileId.Vnode,
2431 DirEntry->ObjectInformation->FileId.Unique);
2433 AFSRemoveDirNodeFromParent( ParentObjectInfo,
2438 // Free up the name buffer if it was reallocated
2441 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2444 AFSExFreePool( DirEntry->NameInformation.FileName.Buffer);
2447 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2450 AFSExFreePool( DirEntry->NameInformation.TargetName.Buffer);
2454 // Dereference the object for this dir entry
2457 ASSERT( DirEntry->ObjectInformation->ObjectReferenceCount > 0);
2459 lCount = InterlockedDecrement( &DirEntry->ObjectInformation->ObjectReferenceCount);
2463 SetFlag( DirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2466 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2467 AFS_TRACE_LEVEL_VERBOSE,
2468 "AFSDeleteDirEntry Decrement count on object %08lX Cnt %d\n",
2469 DirEntry->ObjectInformation,
2470 DirEntry->ObjectInformation->ObjectReferenceCount);
2472 ExDeleteResourceLite( &DirEntry->NonPaged->Lock);
2474 AFSExFreePool( DirEntry->NonPaged);
2477 // Free up the dir entry
2480 AFSExFreePool( DirEntry);
2487 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2488 IN AFSDirectoryCB *DirEntry,
2489 IN BOOLEAN RemoveFromEnumList)
2492 NTSTATUS ntStatus = STATUS_SUCCESS;
2499 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2501 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2502 AFS_TRACE_LEVEL_VERBOSE,
2503 "AFSRemoveDirNodeFromParent Removing DirEntry %08lX %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %08lX\n",
2505 &DirEntry->NameInformation.FileName,
2506 DirEntry->ObjectInformation->FileId.Cell,
2507 DirEntry->ObjectInformation->FileId.Volume,
2508 DirEntry->ObjectInformation->FileId.Vnode,
2509 DirEntry->ObjectInformation->FileId.Unique,
2512 if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2515 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2516 AFS_TRACE_LEVEL_VERBOSE,
2517 "AFSRemoveDirNodeFromParent Removing DirEntry %08lX name %wZ\n",
2519 &DirEntry->NameInformation.FileName);
2521 AFSRemoveNameEntry( ParentObjectInfo,
2527 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2528 AFS_TRACE_LEVEL_VERBOSE,
2529 "AFSRemoveDirNodeFromParent DE %p for %wZ NOT removing entry due to flag set\n",
2531 &DirEntry->NameInformation.FileName);
2535 if( RemoveFromEnumList &&
2536 BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST))
2540 // And remove the entry from the enumeration list
2543 if( DirEntry->ListEntry.fLink == NULL)
2546 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = (AFSDirectoryCB *)DirEntry->ListEntry.bLink;
2551 ((AFSDirectoryCB *)DirEntry->ListEntry.fLink)->ListEntry.bLink = DirEntry->ListEntry.bLink;
2554 if( DirEntry->ListEntry.bLink == NULL)
2557 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = (AFSDirectoryCB *)DirEntry->ListEntry.fLink;
2562 ((AFSDirectoryCB *)DirEntry->ListEntry.bLink)->ListEntry.fLink = DirEntry->ListEntry.fLink;
2565 ASSERT( ParentObjectInfo->Specific.Directory.DirectoryNodeCount > 0);
2567 lCount = InterlockedDecrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2569 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2571 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2572 AFS_TRACE_LEVEL_VERBOSE,
2573 "AFSRemoveDirNodeFromParent Removing entry %wZ Dec Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2574 &DirEntry->NameInformation.FileName,
2576 ParentObjectInfo->FileId.Cell,
2577 ParentObjectInfo->FileId.Volume,
2578 ParentObjectInfo->FileId.Vnode,
2579 ParentObjectInfo->FileId.Unique);
2581 DirEntry->ListEntry.fLink = NULL;
2582 DirEntry->ListEntry.bLink = NULL;
2590 AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
2591 IN OUT PUNICODE_STRING TargetFileName)
2594 NTSTATUS ntStatus = STATUS_SUCCESS;
2595 UNICODE_STRING uniFileName;
2601 // We will process backwards from the end of the name looking
2602 // for the first \ we encounter
2605 uniFileName.Length = FileName->Length;
2606 uniFileName.MaximumLength = FileName->MaximumLength;
2608 uniFileName.Buffer = FileName->Buffer;
2613 if( uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
2617 // Subtract one more character off of the filename if it is not the root
2620 if( uniFileName.Length > sizeof( WCHAR))
2623 uniFileName.Length -= sizeof( WCHAR);
2627 // Now build up the target name
2630 TargetFileName->Length = FileName->Length - uniFileName.Length;
2633 // If we are not on the root then fixup the name
2636 if( uniFileName.Length > sizeof( WCHAR))
2639 TargetFileName->Length -= sizeof( WCHAR);
2641 TargetFileName->Buffer = &uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) + 1];
2646 TargetFileName->Buffer = &uniFileName.Buffer[ uniFileName.Length/sizeof( WCHAR)];
2650 // Fixup the passed back filename length
2653 FileName->Length = uniFileName.Length;
2655 TargetFileName->MaximumLength = TargetFileName->Length;
2660 uniFileName.Length -= sizeof( WCHAR);
2668 AFSParseName( IN PIRP Irp,
2670 OUT PUNICODE_STRING FileName,
2671 OUT PUNICODE_STRING ParsedFileName,
2672 OUT PUNICODE_STRING RootFileName,
2673 OUT ULONG *ParseFlags,
2674 OUT AFSVolumeCB **VolumeCB,
2675 OUT AFSDirectoryCB **ParentDirectoryCB,
2676 OUT AFSNameArrayHdr **NameArray)
2679 NTSTATUS ntStatus = STATUS_SUCCESS;
2680 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2681 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2682 UNICODE_STRING uniFullName, uniComponentName, uniRemainingPath;
2684 AFSDirectoryCB *pDirEntry = NULL, *pShareDirEntry = NULL, *pTargetDirEntry = NULL;
2685 USHORT usIndex = 0, usDriveIndex = 0;
2686 AFSCcb *pRelatedCcb = NULL;
2687 AFSNameArrayHdr *pNameArray = NULL, *pRelatedNameArray = NULL;
2688 USHORT usComponentIndex = 0;
2689 USHORT usComponentLength = 0;
2690 AFSVolumeCB *pVolumeCB = NULL;
2691 AFSFcb *pRelatedFcb = NULL;
2692 BOOLEAN bReleaseTreeLock = FALSE;
2693 BOOLEAN bIsAllShare = FALSE;
2700 // Indicate we are opening a root ...
2703 *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
2705 if( pIrpSp->FileObject->RelatedFileObject != NULL)
2708 pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
2710 pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
2712 pRelatedNameArray = pRelatedCcb->NameArray;
2714 uniFullName = pIrpSp->FileObject->FileName;
2716 ASSERT( pRelatedFcb != NULL);
2719 // No wild cards in the name
2722 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2723 AFS_TRACE_LEVEL_VERBOSE_2,
2724 "AFSParseName (%08lX) Relative open for %wZ FID %08lX-%08lX-%08lX-%08lX component %wZ\n",
2726 &pRelatedCcb->DirectoryCB->NameInformation.FileName,
2727 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Cell,
2728 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Volume,
2729 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
2730 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Unique,
2733 if( FsRtlDoesNameContainWildCards( &uniFullName))
2736 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2737 AFS_TRACE_LEVEL_ERROR,
2738 "AFSParseName (%08lX) Component %wZ contains wild cards\n",
2742 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
2745 pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
2747 pDirEntry = pRelatedCcb->DirectoryCB;
2749 *FileName = pIrpSp->FileObject->FileName;
2752 // Grab the root node while checking state
2755 AFSAcquireShared( pVolumeCB->VolumeLock,
2758 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
2759 BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
2763 // The volume has been taken off line so fail the access
2766 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2767 AFS_TRACE_LEVEL_ERROR,
2768 "AFSParseName (%08lX) Volume %08lX:%08lX OFFLINE/INVALID\n",
2770 pVolumeCB->ObjectInformation.FileId.Cell,
2771 pVolumeCB->ObjectInformation.FileId.Volume);
2773 AFSReleaseResource( pVolumeCB->VolumeLock);
2775 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
2778 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
2781 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2782 AFS_TRACE_LEVEL_VERBOSE,
2783 "AFSParseName (%08lX) Verifying root of volume %08lX:%08lX\n",
2785 pVolumeCB->ObjectInformation.FileId.Cell,
2786 pVolumeCB->ObjectInformation.FileId.Volume);
2788 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
2791 if( !NT_SUCCESS( ntStatus))
2794 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2795 AFS_TRACE_LEVEL_ERROR,
2796 "AFSParseName (%08lX) Failed verification of root Status %08lX\n",
2800 AFSReleaseResource( pVolumeCB->VolumeLock);
2802 try_return( ntStatus);
2806 AFSReleaseResource( pVolumeCB->VolumeLock);
2808 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
2811 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2812 AFS_TRACE_LEVEL_VERBOSE,
2813 "AFSParseName (%08lX) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2815 &pDirEntry->NameInformation.FileName,
2816 pDirEntry->ObjectInformation->FileId.Cell,
2817 pDirEntry->ObjectInformation->FileId.Volume,
2818 pDirEntry->ObjectInformation->FileId.Vnode,
2819 pDirEntry->ObjectInformation->FileId.Unique);
2822 // Directory TreeLock should be exclusively held
2825 AFSAcquireExcl( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
2828 ntStatus = AFSVerifyEntry( AuthGroup,
2831 AFSReleaseResource( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2833 if( !NT_SUCCESS( ntStatus))
2836 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2837 AFS_TRACE_LEVEL_VERBOSE,
2838 "AFSParseName (%08lX) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2840 &pDirEntry->NameInformation.FileName,
2841 pDirEntry->ObjectInformation->FileId.Cell,
2842 pDirEntry->ObjectInformation->FileId.Volume,
2843 pDirEntry->ObjectInformation->FileId.Vnode,
2844 pDirEntry->ObjectInformation->FileId.Unique,
2847 try_return( ntStatus);
2852 // Create our full path name buffer
2855 uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length +
2857 pIrpSp->FileObject->FileName.Length +
2860 uniFullName.Length = 0;
2862 uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2863 uniFullName.MaximumLength,
2864 AFS_NAME_BUFFER_THREE_TAG);
2866 if( uniFullName.Buffer == NULL)
2869 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2870 AFS_TRACE_LEVEL_ERROR,
2871 "AFSParseName (%08lX) Failed to allocate full name buffer\n",
2874 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2877 RtlZeroMemory( uniFullName.Buffer,
2878 uniFullName.MaximumLength);
2880 RtlCopyMemory( uniFullName.Buffer,
2881 pRelatedCcb->FullFileName.Buffer,
2882 pRelatedCcb->FullFileName.Length);
2884 uniFullName.Length = pRelatedCcb->FullFileName.Length;
2886 usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
2888 usComponentLength = pIrpSp->FileObject->FileName.Length;
2890 if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
2891 pIrpSp->FileObject->FileName.Length > 0 &&
2892 pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
2893 pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
2896 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
2898 uniFullName.Length += sizeof( WCHAR);
2900 usComponentLength += sizeof( WCHAR);
2903 if( pIrpSp->FileObject->FileName.Length > 0)
2906 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
2907 pIrpSp->FileObject->FileName.Buffer,
2908 pIr
\epSp->FileObject->FileName.Length);
2910 uniFullName.Length += pIrpSp->FileObject->FileName.Length;
2913 *RootFileName = uniFullName;
2916 // We populate up to the current parent
2919 if( pRelatedNameArray == NULL)
2923 // Init and populate our name array
2926 pNameArray = AFSInitNameArray( NULL,
2929 if( pNameArray == NULL)
2932 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2933 AFS_TRACE_LEVEL_VERBOSE,
2934 "AFSParseName (%08lX) Failed to initialize name array\n",
2937 AFSExFreePool( uniFullName.Buffer);
2939 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2942 ntStatus = AFSPopulateNameArray( pNameArray,
2944 pRelatedCcb->DirectoryCB);
2950 // Init and populate our name array
2953 pNameArray = AFSInitNameArray( NULL,
2954 pRelatedNameArray->MaxElementCount);
2956 if( pNameArray == NULL)
2959 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2960 AFS_TRACE_LEVEL_VERBOSE,
2961 "AFSParseName (%08lX) Failed to initialize name array\n",
2964 AFSExFreePool( uniFullName.Buffer);
2966 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2969 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
2971 pRelatedCcb->DirectoryCB);
2974 if( !NT_SUCCESS( ntStatus))
2977 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2978 AFS_TRACE_LEVEL_VERBOSE,
2979 "AFSParseName (%08lX) Failed to populate name array\n",
2982 AFSExFreePool( uniFullName.Buffer);
2984 try_return( ntStatus);
2987 ParsedFileName->Length = usComponentLength;
2988 ParsedFileName->MaximumLength = uniFullName.MaximumLength;
2990 ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
2993 // Indicate to caller that RootFileName must be freed
2996 SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
2998 *NameArray = pNameArray;
3000 *VolumeCB = pVolumeCB;
3003 // Increment our volume reference count
3006 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
3008 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3009 AFS_TRACE_LEVEL_VERBOSE,
3010 "AFSParseName Increment count on volume %08lX Cnt %d\n",
3014 *ParentDirectoryCB = pDirEntry;
3016 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
3018 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3019 AFS_TRACE_LEVEL_VERBOSE,
3020 "AFSParseName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
3021 &pDirEntry->NameInformation.FileName,
3026 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3027 AFS_TRACE_LEVEL_VERBOSE_2,
3028 "AFSParseName (%08lX) Returning full name %wZ\n",
3032 try_return( ntStatus);
3036 // No wild cards in the name
3039 uniFullName = pIrpSp->FileObject->FileName;
3041 if( FsRtlDoesNameContainWildCards( &uniFullName) ||
3042 uniFullName.Length < AFSServerName.Length)
3045 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3046 AFS_TRACE_LEVEL_ERROR,
3047 "AFSParseName (%08lX) Name %wZ contains wild cards or too short\n",
3051 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3055 // The name is a fully qualified name. Parse out the server/share names and
3056 // point to the root qualified name
3057 // First thing is to locate the server name
3060 FsRtlDissectName( uniFullName,
3064 uniFullName = uniRemainingPath;
3067 // This component is the server name we are serving
3070 if( RtlCompareUnicodeString( &uniComponentName,
3076 // Drive letter based name?
3079 uniFullName = pIrpSp->FileObject->FileName;
3081 while( usIndex < uniFullName.Length/sizeof( WCHAR))
3084 if( uniFullName.Buffer[ usIndex] == L':')
3087 uniFullName.Buffer = &uniFullName.Buffer[ usIndex + 2];
3089 uniFullName.Length -= (usIndex + 2) * sizeof( WCHAR);
3091 usDriveIndex = usIndex - 1;
3100 // Do we have the right server name now?
3103 FsRtlDissectName( uniFullName,
3107 uniFullName = uniRemainingPath;
3110 // This component is the server name we are serving
3113 if( RtlCompareUnicodeString( &uniComponentName,
3118 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3119 AFS_TRACE_LEVEL_ERROR,
3120 "AFSParseName (%08lX) Name %wZ does not have server name\n",
3122 &pIrpSp->FileObject->FileName);
3124 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3128 // Validate this drive letter is actively mapped
3131 if( usDriveIndex > 0 &&
3132 !AFSIsDriveMapped( pIrpSp->FileObject->FileName.Buffer[ usDriveIndex]))
3135 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3136 AFS_TRACE_LEVEL_ERROR,
3137 "AFSParseName (%08lX) Name %wZ contains invalid drive mapping\n",
3139 &pIrpSp->FileObject->FileName);
3141 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3145 if( FsRtlDoesNameContainWildCards( &uniFullName))
3148 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3149 AFS_TRACE_LEVEL_ERROR,
3150 "AFSParseName (%08lX) Component %wZ contains wild cards\n",
3154 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3157 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3158 AFS_TRACE_LEVEL_VERBOSE_2,
3159 "AFSParseName (%08lX) Processing full name %wZ\n",
3163 if( uniFullName.Length > 0 &&
3164 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] == L'\\')
3167 uniFullName.Length -= sizeof( WCHAR);
3171 // Be sure we are online and ready to go
3174 AFSAcquireShared( AFSGlobalRoot->VolumeLock,
3177 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3178 BooleanFlagOn( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3182 // The volume has been taken off line so fail the access
3185 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3186 AFS_TRACE_LEVEL_ERROR,
3187 "AFSParseName (%08lX) Volume %08lX:%08lX OFFLINE/INVALID\n",
3189 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3190 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3192 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3194 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3197 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3200 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3201 AFS_TRACE_LEVEL_VERBOSE,
3202 "AFSParseName (%08lX) Verifying root of volume %08lX:%08lX\n",
3204 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3205 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3207 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3210 if( !NT_SUCCESS( ntStatus))
3213 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3214 AFS_TRACE_LEVEL_ERROR,
3215 "AFSParseName (%08lX) Failed verification of root Status %08lX\n",
3219 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3221 try_return( ntStatus);
3225 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3227 if( !BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3230 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3231 AFS_TRACE_LEVEL_VERBOSE,
3232 "AFSParseName (%08lX) Enumerating global root of volume %08lX:%08lX\n",
3234 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3235 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3237 ntStatus = AFSEnumerateGlobalRoot( AuthGroup);
3239 if( !NT_SUCCESS( ntStatus))
3242 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3243 AFS_TRACE_LEVEL_ERROR,
3244 "AFSParseName (%08lX) Failed enumeraiton of root Status %08lX\n",
3248 try_return( ntStatus);
3253 // Check for the \\Server access and return it as though it where \\Server\Globalroot
3256 if( uniRemainingPath.Buffer == NULL ||
3257 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3258 uniRemainingPath.Buffer[ 0] == L'\\'))
3261 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3262 AFS_TRACE_LEVEL_VERBOSE_2,
3263 "AFSParseName (%08lX) Returning global root access\n",
3266 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3268 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3269 AFS_TRACE_LEVEL_VERBOSE,
3270 "AFSParseName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3271 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3272 AFSGlobalRoot->DirectoryCB,
3278 FileName->Length = 0;
3279 FileName->MaximumLength = 0;
3280 FileName->Buffer = NULL;
3282 try_return( ntStatus = STATUS_SUCCESS);
3285 *RootFileName = uniFullName;
3288 // Include the starting \ in the root name
3291 if( RootFileName->Buffer[ 0] != L'\\')
3293 RootFileName->Buffer--;
3294 RootFileName->Length += sizeof( WCHAR);
3295 RootFileName->MaximumLength += sizeof( WCHAR);
3299 // Get the 'share' name
3302 FsRtlDissectName( uniFullName,
3306 if( FsRtlDoesNameContainWildCards( &uniFullName))
3309 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3310 AFS_TRACE_LEVEL_ERROR,
3311 "AFSParseName (%08lX) Component %wZ contains wild cards\n",
3315 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3319 // If this is the ALL access then perform some additional processing
3322 if( uniComponentName.Length == 0 ||
3323 RtlCompareUnicodeString( &uniComponentName,
3331 // If there is nothing else then get out
3334 if( uniRemainingPath.Buffer == NULL ||
3335 uniRemainingPath.Length == 0 ||
3336 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3337 uniRemainingPath.Buffer[ 0] == L'\\'))
3340 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3341 AFS_TRACE_LEVEL_VERBOSE_2,
3342 "AFSParseName (%08lX) Returning global root access\n",
3345 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3347 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3348 AFS_TRACE_LEVEL_VERBOSE,
3349 "AFSParseName Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
3350 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3351 AFSGlobalRoot->DirectoryCB,
3357 FileName->Length = 0;
3358 FileName->MaximumLength = 0;
3359 FileName->Buffer = NULL;
3361 try_return( ntStatus = STATUS_SUCCESS);
3365 // Process the name again to strip off the ALL portion
3368 uniFullName = uniRemainingPath;
3370 FsRtlDissectName( uniFullName,
3375 // Check for the PIOCtl name
3378 if( RtlCompareUnicodeString( &uniComponentName,
3383 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3384 AFS_TRACE_LEVEL_VERBOSE_2,
3385 "AFSParseName (%08lX) Returning root PIOCtl access\n",
3388 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3390 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3391 AFS_TRACE_LEVEL_VERBOSE,
3392 "AFSParseName Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
3393 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3394 AFSGlobalRoot->DirectoryCB,
3398 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3402 *FileName = AFSPIOCtlName;
3404 try_return( ntStatus = STATUS_SUCCESS);
3407 else if( (pDirEntry = AFSGetSpecialShareNameEntry( &uniComponentName,
3408 &uniRemainingPath)) != NULL)
3411 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3412 AFS_TRACE_LEVEL_VERBOSE_2,
3413 "AFSParseName (%08lX) Returning root share name %wZ access\n",
3418 // Add in the full share name to pass back
3421 if( uniRemainingPath.Buffer != NULL)
3425 // This routine strips off the leading slash so add it back in
3428 uniRemainingPath.Buffer--;
3429 uniRemainingPath.Length += sizeof( WCHAR);
3430 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3433 // And the cell name
3436 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3437 uniRemainingPath.Length += uniComponentName.Length;
3438 uniRemainingPath.MaximumLength += uniComponentName.Length;
3440 uniComponentName = uniRemainingPath;
3445 *FileName = uniComponentName;
3447 *ParentDirectoryCB = pDirEntry;
3449 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3451 lCount = InterlockedIncrement( &pDirEntry->OpenReferenceCount);
3453 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3454 AFS_TRACE_LEVEL_VERBOSE,
3455 "AFSParseName Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
3456 &pDirEntry->NameInformation.FileName,
3461 try_return( ntStatus = STATUS_SUCCESS);
3465 // Determine the 'share' we are accessing
3468 ulCRC = AFSGenerateCRC( &uniComponentName,
3471 AFSAcquireShared( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3474 bReleaseTreeLock = TRUE;
3476 AFSLocateCaseSensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
3480 if( pDirEntry == NULL)
3483 ulCRC = AFSGenerateCRC( &uniComponentName,
3486 AFSLocateCaseInsensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
3490 if( pDirEntry == NULL)
3494 // OK, if this component is a valid short name then try
3495 // a lookup in the short name tree
3498 if( RtlIsNameLegalDOS8Dot3( &uniComponentName,
3503 AFSLocateShortNameDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.ShortNameTree,
3508 if( pDirEntry == NULL)
3512 // Check with the service whether it is a valid cell name
3515 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3517 bReleaseTreeLock = FALSE;
3519 ntStatus = AFSCheckCellName( AuthGroup,
3523 if( !NT_SUCCESS( ntStatus))
3527 uniRemainingPath.Length == 0 &&
3528 ntStatus == STATUS_OBJECT_PATH_NOT_FOUND)
3531 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
3534 try_return( ntStatus);
3540 if( bReleaseTreeLock)
3542 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3546 // Be sure we are starting from the correct volume
3549 if( pDirEntry->ObjectInformation->VolumeCB != AFSGlobalRoot)
3553 // We dropped the global root in the CheckCellName routine which is the
3554 // only way we can be here
3557 pVolumeCB = pDirEntry->ObjectInformation->VolumeCB;
3560 // In this case don't add back in the 'share' name since that is where we are
3561 // starting. Just put the leading slash back in
3564 if( uniRemainingPath.Buffer != NULL)
3567 uniRemainingPath.Buffer--;
3568 uniRemainingPath.Length += sizeof( WCHAR);
3569 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3571 if( uniRemainingPath.Length > sizeof( WCHAR))
3574 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3578 // Pass back the parent being the root of the volume
3581 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3587 // Pass back a root slash
3590 uniRemainingPath = uniComponentName;
3592 uniRemainingPath.Buffer--;
3593 uniRemainingPath.Length = sizeof( WCHAR);
3594 uniRemainingPath.MaximumLength = sizeof( WCHAR);
3597 // This is a root open so pass back no parent
3600 *ParentDirectoryCB = NULL;
3606 pVolumeCB = AFSGlobalRoot;
3609 // Add back in the 'share' portion of the name since we will parse it out on return
3612 if( uniRemainingPath.Buffer != NULL)
3616 // This routine strips off the leading slash so add it back in
3619 uniRemainingPath.Buffer--;
3620 uniRemainingPath.Length += sizeof( WCHAR);
3621 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3623 if( uniRemainingPath.Length > sizeof( WCHAR))
3626 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3630 // And the cell name
3633 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3634 uniRemainingPath.Length += uniComponentName.Length;
3635 uniRemainingPath.MaximumLength += uniComponentName.Length;
3640 uniRemainingPath = uniComponentName;
3644 // And the leading slash again ...
3647 uniRemainingPath.Buffer--;
3648 uniRemainingPath.Length += sizeof( WCHAR);
3649 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3651 lCount = InterlockedIncrement( &pVolumeCB->DirectoryCB->OpenReferenceCount);
3653 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3654 AFS_TRACE_LEVEL_VERBOSE,
3655 "AFSParseName Increment6 count on %wZ DE %p Ccb %p Cnt %d\n",
3656 &pVolumeCB->DirectoryCB->NameInformation.FileName,
3657 pVolumeCB->DirectoryCB,
3659 lCount = pVolumeCB->DirectoryCB->OpenReferenceCount);
3662 // Pass back the parent being the volume root
3665 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3669 // Init our name array
3672 pNameArray = AFSInitNameArray( pVolumeCB->DirectoryCB,
3675 if( pNameArray == NULL)
3678 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3679 AFS_TRACE_LEVEL_VERBOSE,
3680 "AFSParseName (%08lX) Failed to initialize name array\n",
3683 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3687 // Return the remaining portion as the file name
3690 *FileName = uniRemainingPath;
3692 *ParsedFileName = uniRemainingPath;
3694 *NameArray = pNameArray;
3696 *VolumeCB = pVolumeCB;
3699 // Increment our reference on the volume
3702 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
3704 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3705 AFS_TRACE_LEVEL_VERBOSE,
3706 "AFSParseName Increment2 count on global volume %08lX Cnt %d\n",
3712 if( NT_SUCCESS( ntStatus))
3715 if( *ParentDirectoryCB != NULL)
3718 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3719 AFS_TRACE_LEVEL_VERBOSE,
3720 "AFSParseName Count on %wZ DE %p Ccb %p Cnt %d\n",
3721 &(*ParentDirectoryCB)->NameInformation.FileName,
3724 (*ParentDirectoryCB)->OpenReferenceCount);
3728 if( *VolumeCB != NULL)
3730 ASSERT( (*VolumeCB)->VolumeReferenceCount > 1);
3733 if( ntStatus != STATUS_SUCCESS)
3736 if( pNameArray != NULL)
3739 AFSFreeNameArray( pNameArray);
3748 AFSCheckCellName( IN GUID *AuthGroup,
3749 IN UNICODE_STRING *CellName,
3750 OUT AFSDirectoryCB **ShareDirEntry)
3753 NTSTATUS ntStatus = STATUS_SUCCESS;
3754 UNICODE_STRING uniName;
3755 AFSDirEnumEntry *pDirEnumEntry = NULL;
3756 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3757 AFSDirHdr *pDirHdr = &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr;
3758 AFSDirectoryCB *pDirNode = NULL;
3759 UNICODE_STRING uniDirName, uniTargetName;
3760 AFSVolumeCB *pVolumeCB = NULL;
3767 // Look for some default names we will not handle
3770 RtlInitUnicodeString( &uniName,
3773 if( RtlCompareUnicodeString( &uniName,
3778 try_return( ntStatus = STATUS_NO_SUCH_FILE);
3781 RtlInitUnicodeString( &uniName,
3784 if( RtlCompareUnicodeString( &uniName,
3789 try_return( ntStatus = STATUS_NO_SUCH_FILE);
3792 RtlInitUnicodeString( &uniName,
3795 if( RtlCompareUnicodeString( &uniName,
3800 try_return( ntStatus = STATUS_NO_SUCH_FILE);
3803 RtlInitUnicodeString( &uniName,
3806 if( RtlCompareUnicodeString( &uniName,
3811 try_return( ntStatus = STATUS_NO_SUCH_FILE);
3815 // OK, ask the CM about this component name
3818 ntStatus = AFSEvaluateTargetByName( AuthGroup,
3819 &AFSGlobalRoot->ObjectInformation,
3823 if( !NT_SUCCESS( ntStatus))
3826 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3827 AFS_TRACE_LEVEL_WARNING,
3828 "AFSCheckCellName entry %wZ does not exist parent FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3830 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3831 AFSGlobalRoot->ObjectInformation.FileId.Volume,
3832 AFSGlobalRoot->ObjectInformation.FileId.Vnode,
3833 AFSGlobalRoot->ObjectInformation.FileId.Unique,
3836 try_return( ntStatus);
3840 // OK, we have a dir enum entry back so add it to the root node
3843 uniDirName = *CellName;
3845 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
3846 uniTargetName.MaximumLength = uniTargetName.Length;
3847 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
3850 // Is this entry a root volume entry?
3853 if( pDirEnumEntry->FileId.Cell != AFSGlobalRoot->ObjectInformation.FileId.Cell ||
3854 pDirEnumEntry->FileId.Volume != AFSGlobalRoot->ObjectInformation.FileId.Volume)
3858 // Build the root volume entry
3861 ntStatus = AFSBuildRootVolume( AuthGroup,
3862 &pDirEnumEntry->FileId,
3865 if( !NT_SUCCESS( ntStatus))
3867 try_return( ntStatus);
3870 *ShareDirEntry = pVolumeCB->DirectoryCB;
3872 lCount = InterlockedIncrement( &pVolumeCB->DirectoryCB->OpenReferenceCount);
3874 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3875 AFS_TRACE_LEVEL_VERBOSE,
3876 "AFSCheckCellName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
3877 &pVolumeCB->DirectoryCB->NameInformation.FileName,
3878 pVolumeCB->DirectoryCB,
3882 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
3887 lCount = InterlockedIncrement( &pDirHdr->ContentIndex);
3889 pDirNode = AFSInitDirEntry( &AFSGlobalRoot->ObjectInformation,
3895 if( pDirNode == NULL)
3898 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3902 // Init the short name if we have one
3905 if( pDirEnumEntry->ShortNameLength > 0)
3908 pDirNode->NameInformation.ShortNameLength = pDirEnumEntry->ShortNameLength;
3910 RtlCopyMemory( pDirNode->NameInformation.ShortName,
3911 pDirEnumEntry->ShortName,
3912 pDirNode->NameInformation.ShortNameLength);
3915 AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3919 // Insert the node into the name tree
3922 ASSERT( ExIsResourceAcquiredExclusiveLite( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock));
3924 if( pDirHdr->CaseSensitiveTreeHead == NULL)
3927 pDirHdr->CaseSensitiveTreeHead = pDirNode;
3932 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( pDirHdr->CaseSensitiveTreeHead,
3936 AFSDeleteDirEntry( &AFSGlobalRoot->ObjectInformation,
3939 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3941 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3945 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
3947 if( pDirHdr->CaseInsensitiveTreeHead == NULL)
3950 pDirHdr->CaseInsensitiveTreeHead = pDirNode;
3952 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
3957 AFSInsertCaseInsensitiveDirEntry( pDirHdr->CaseInsensitiveTreeHead,
3961 if( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead == NULL)
3964 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead = pDirNode;
3969 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
3971 pDirNode->ListEntry.bLink = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail;
3974 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail = pDirNode;
3976 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
3978 lCount = InterlockedIncrement( &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeCount);
3980 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
3981 AFS_TRACE_LEVEL_VERBOSE,
3982 "AFSCheckCellName Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
3983 &pDirNode->NameInformation.FileName,
3985 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3986 AFSGlobalRoot->ObjectInformation.FileId.Volume,
3987 AFSGlobalRoot->ObjectInformation.FileId.Vnode,
3988 AFSGlobalRoot->ObjectInformation.FileId.Unique);
3990 lCount = InterlockedIncrement( &pDirNode->OpenReferenceCount);
3992 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3993 AFS_TRACE_LEVEL_VERBOSE,
3994 "AFSCheckCellName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3995 &pDirNode->NameInformation.FileName,
4000 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4003 // Pass back the dir node
4006 *ShareDirEntry = pDirNode;
4011 if( pDirEnumEntry != NULL)
4014 AFSExFreePool( pDirEnumEntry);
4022 AFSBuildMountPointTarget( IN GUID *AuthGroup,
4023 IN AFSDirectoryCB *DirectoryCB,
4024 OUT AFSVolumeCB **TargetVolumeCB)
4027 NTSTATUS ntStatus = STATUS_SUCCESS;
4028 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4029 AFSDirEnumEntry *pDirEntry = NULL;
4030 AFSDirectoryCB *pDirNode = NULL;
4031 UNICODE_STRING uniDirName, uniTargetName;
4032 ULONGLONG ullIndex = 0;
4033 AFSVolumeCB *pVolumeCB = NULL;
4034 AFSFileID stTargetFileID;
4041 // Loop on each entry, building the chain until we encounter the final target
4044 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4045 AFS_TRACE_LEVEL_VERBOSE_2,
4046 "AFSBuildMountPointTarget Building target directory for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4047 &DirectoryCB->NameInformation.FileName,
4048 DirectoryCB->ObjectInformation->FileId.Cell,
4049 DirectoryCB->ObjectInformation->FileId.Volume,
4050 DirectoryCB->ObjectInformation->FileId.Vnode,
4051 DirectoryCB->ObjectInformation->FileId.Unique);
4054 // Do we need to evaluate the node?
4057 //if( DirectoryCB->ObjectInformation->TargetFileId.Vnode == 0 &&
4058 // DirectoryCB->ObjectInformation->TargetFileId.Unique == 0)
4062 // Go evaluate the current target to get the target fid
4065 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4066 AFS_TRACE_LEVEL_VERBOSE_2,
4067 "AFSBuildMountPointTarget Evaluating target %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4068 &DirectoryCB->NameInformation.FileName,
4069 DirectoryCB->ObjectInformation->FileId.Cell,
4070 DirectoryCB->ObjectInformation->FileId.Volume,
4071 DirectoryCB->ObjectInformation->FileId.Vnode,
4072 DirectoryCB->ObjectInformation->FileId.Unique);
4074 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
4079 if( !NT_SUCCESS( ntStatus))
4082 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4083 AFS_TRACE_LEVEL_ERROR,
4084 "AFSBuildMountPointTarget Failed to evaluate target %wZ Status %08lX\n",
4085 &DirectoryCB->NameInformation.FileName,
4087 try_return( ntStatus);
4090 if( pDirEntry->TargetFileId.Vnode == 0 &&
4091 pDirEntry->TargetFileId.Unique == 0)
4094 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4095 AFS_TRACE_LEVEL_ERROR,
4096 "AFSBuildMountPointTarget Target %wZ FID %08lX-%08lX-%08lX-%08lX service returned zero FID\n",
4097 &DirectoryCB->NameInformation.FileName,
4098 DirectoryCB->ObjectInformation->FileId.Cell,
4099 DirectoryCB->ObjectInformation->FileId.Volume,
4100 DirectoryCB->ObjectInformation->FileId.Vnode,
4101 DirectoryCB->ObjectInformation->FileId.Unique);
4103 try_return( ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED);
4106 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
4109 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
4110 &DirectoryCB->Flags,
4111 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4112 (USHORT)pDirEntry->TargetNameLength);
4114 if( !NT_SUCCESS( ntStatus))
4117 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4119 try_return( ntStatus);
4122 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4124 DirectoryCB->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
4127 stTargetFileID = DirectoryCB->ObjectInformation->TargetFileId;
4130 // Try to locate this FID. First the volume then the
4134 ullIndex = AFSCreateHighIndex( &stTargetFileID);
4136 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4137 AFS_TRACE_LEVEL_VERBOSE,
4138 "AFSBuildMountPointTarget Acquiring RDR VolumeTreeLock lock %08lX EXCL %08lX\n",
4139 &pDevExt->Specific.RDR.VolumeTreeLock,
4140 PsGetCurrentThread());
4142 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4145 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4146 AFS_TRACE_LEVEL_VERBOSE_2,
4147 "AFSBuildMountPointTarget Locating volume for target %I64X\n",
4150 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4152 (AFSBTreeEntry **)&pVolumeCB);
4155 // We can be processing a request for a target that is on a volume
4156 // we have never seen before.
4159 if( pVolumeCB == NULL)
4163 // Locking is held correctly in init routine
4166 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4169 // Go init the root of the volume
4172 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4173 AFS_TRACE_LEVEL_VERBOSE_2,
4174 "AFSBuildMountPointTarget Initializing root for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4175 &DirectoryCB->NameInformation.FileName,
4176 DirectoryCB->ObjectInformation->FileId.Cell,
4177 DirectoryCB->ObjectInformation->FileId.Volume,
4178 DirectoryCB->ObjectInformation->FileId.Vnode,
4179 DirectoryCB->ObjectInformation->FileId.Unique);
4181 ntStatus = AFSInitVolume( AuthGroup,
4185 if( !NT_SUCCESS( ntStatus))
4188 try_return( ntStatus);
4195 // Check if this volume has been deleted or taken offline
4198 if( BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
4201 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4203 try_return( ntStatus = STATUS_FILE_IS_OFFLINE);
4207 // Just to ensure that things don't get torn down AND we don't create a
4208 // deadlock with invalidation
4211 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
4213 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4215 AFSAcquireExcl( pVolumeCB->VolumeLock,
4218 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
4221 if( pVolumeCB->RootFcb == NULL)
4225 // Initialize the root fcb for this volume
4228 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4231 if( !NT_SUCCESS( ntStatus))
4234 AFSReleaseResource( pVolumeCB->VolumeLock);
4236 try_return( ntStatus);
4240 // Drop the lock acquired above
4243 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4246 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4247 AFS_TRACE_LEVEL_VERBOSE_2,
4248 "AFSBuildMountPointTarget Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4249 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4250 pVolumeCB->ObjectInformation.FileId.Cell,
4251 pVolumeCB->ObjectInformation.FileId.Volume,
4252 pVolumeCB->ObjectInformation.FileId.Vnode,
4253 pVolumeCB->ObjectInformation.FileId.Unique);
4255 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
4257 AFSReleaseResource( pVolumeCB->VolumeLock);
4259 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4260 AFS_TRACE_LEVEL_VERBOSE,
4261 "AFSBuildMountPointTarget Increment count on volume %08lX Cnt %d\n",
4265 *TargetVolumeCB = pVolumeCB;
4272 AFSExFreePool( pDirEntry);
4280 AFSBuildRootVolume( IN GUID *AuthGroup,
4281 IN AFSFileID *FileId,
4282 OUT AFSVolumeCB **TargetVolumeCB)
4285 NTSTATUS ntStatus = STATUS_SUCCESS;
4286 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4287 AFSDirectoryCB *pDirNode = NULL;
4288 UNICODE_STRING uniDirName, uniTargetName;
4289 ULONGLONG ullIndex = 0;
4290 AFSVolumeCB *pVolumeCB = NULL;
4296 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4297 AFS_TRACE_LEVEL_VERBOSE_2,
4298 "AFSBuildRootVolume Building target volume for FID %08lX-%08lX-%08lX-%08lX\n",
4304 ullIndex = AFSCreateHighIndex( FileId);
4306 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4307 AFS_TRACE_LEVEL_VERBOSE,
4308 "AFSBuildRootVolume Acquiring RDR VolumeTreeLock lock %08lX EXCL %08lX\n",
4309 &pDevExt->Specific.RDR.VolumeTreeLock,
4310 PsGetCurrentThread());
4312 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4315 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4316 AFS_TRACE_LEVEL_VERBOSE_2,
4317 "AFSBuildRootVolume Locating volume for target %I64X\n",
4320 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4322 (AFSBTreeEntry **)&pVolumeCB);
4325 // We can be processing a request for a target that is on a volume
4326 // we have never seen before.
4329 if( pVolumeCB == NULL)
4333 // Locking is held correctly in init routine
4336 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4339 // Go init the root of the volume
4342 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4343 AFS_TRACE_LEVEL_VERBOSE_2,
4344 "AFSBuildRootVolume Initializing root for FID %08lX-%08lX-%08lX-%08lX\n",
4350 ntStatus = AFSInitVolume( AuthGroup,
4354 if( !NT_SUCCESS( ntStatus))
4357 try_return( ntStatus);
4364 // Just to ensure that things don't get torn down AND we don't create a
4365 // deadlock with invalidation
4368 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
4370 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4372 AFSAcquireExcl( pVolumeCB->VolumeLock,
4375 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
4379 if( pVolumeCB->RootFcb == NULL)
4383 // Initialize the root fcb for this volume
4386 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4389 if( !NT_SUCCESS( ntStatus))
4392 AFSReleaseResource( pVolumeCB->VolumeLock);
4394 try_return( ntStatus);
4398 // Drop the lock acquired above
4401 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4404 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4405 AFS_TRACE_LEVEL_VERBOSE_2,
4406 "AFSBuildRootVolume Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4407 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4408 pVolumeCB->ObjectInformation.FileId.Cell,
4409 pVolumeCB->ObjectInformation.FileId.Volume,
4410 pVolumeCB->ObjectInformation.FileId.Vnode,
4411 pVolumeCB->ObjectInformation.FileId.Unique);
4413 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
4415 AFSReleaseResource( pVolumeCB->VolumeLock);
4417 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4418 AFS_TRACE_LEVEL_VERBOSE,
4419 "AFSBuildRootVolume Increment count on volume %08lX Cnt %d\n",
4423 *TargetVolumeCB = pVolumeCB;
4434 AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
4435 IN PFILE_OBJECT FileObject,
4436 IN UNICODE_STRING *RemainingPath,
4440 NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
4441 UNICODE_STRING uniReparseName;
4442 UNICODE_STRING uniMUPDeviceName;
4443 AFSDirEnumEntry *pDirEntry = NULL;
4449 // Build up the name to reparse
4452 RtlInitUnicodeString( &uniMUPDeviceName,
4455 uniReparseName.Length = 0;
4456 uniReparseName.Buffer = NULL;
4459 // Be sure we have a target name
4462 if( DirEntry->NameInformation.TargetName.Length == 0)
4465 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
4470 if( !NT_SUCCESS( ntStatus) ||
4471 pDirEntry->TargetNameLength == 0)
4474 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4475 AFS_TRACE_LEVEL_ERROR,
4476 "AFSProcessDFSLink EvaluateTargetByID failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4477 &DirEntry->NameInformation.FileName,
4478 DirEntry->ObjectInformation->FileId.Cell,
4479 DirEntry->ObjectInformation->FileId.Volume,
4480 DirEntry->ObjectInformation->FileId.Vnode,
4481 DirEntry->ObjectInformation->FileId.Unique,
4484 if( NT_SUCCESS( ntStatus))
4487 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
4490 try_return( ntStatus);
4494 // Update the target name
4497 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
4500 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
4502 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4503 (USHORT)pDirEntry->TargetNameLength);
4505 if( !NT_SUCCESS( ntStatus))
4508 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4509 AFS_TRACE_LEVEL_ERROR,
4510 "AFSProcessDFSLink UpdateTargetName failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4511 &DirEntry->NameInformation.FileName,
4512 DirEntry->ObjectInformation->FileId.Cell,
4513 DirEntry->ObjectInformation->FileId.Volume,
4514 DirEntry->ObjectInformation->FileId.Vnode,
4515 DirEntry->ObjectInformation->FileId.Unique,
4518 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4520 try_return( ntStatus);
4523 AFSConvertToShared( &DirEntry->NonPaged->Lock);
4527 AFSAcquireShared( &DirEntry->NonPaged->Lock,
4531 uniReparseName.MaximumLength = uniMUPDeviceName.Length +
4533 DirEntry->NameInformation.TargetName.Length +
4536 if( RemainingPath != NULL &&
4537 RemainingPath->Length > 0)
4540 uniReparseName.MaximumLength += RemainingPath->Length;
4544 // Allocate the reparse buffer
4547 uniReparseName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4548 uniReparseName.MaximumLength,
4549 AFS_REPARSE_NAME_TAG);
4551 if( uniReparseName.Buffer == NULL)
4554 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4555 AFS_TRACE_LEVEL_ERROR,
4556 "AFSProcessDFSLink uniReparseName.Buffer == NULL Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4557 &DirEntry->NameInformation.FileName,
4558 DirEntry->ObjectInformation->FileId.Cell,
4559 DirEntry->ObjectInformation->FileId.Volume,
4560 DirEntry->ObjectInformation->FileId.Vnode,
4561 DirEntry->ObjectInformation->FileId.Unique,
4562 STATUS_INSUFFICIENT_RESOURCES);
4564 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4566 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4570 // Start building the name
4573 RtlCopyMemory( uniReparseName.Buffer,
4574 uniMUPDeviceName.Buffer,
4575 uniMUPDeviceName.Length);
4577 uniReparseName.Length = uniMUPDeviceName.Length;
4579 if( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\')
4582 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
4584 uniReparseName.Length += sizeof( WCHAR);
4587 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
4588 DirEntry->NameInformation.TargetName.Buffer,
4589 DirEntry->NameInformation.TargetName.Length);
4591 uniReparseName.Length += DirEntry->NameInformation.TargetName.Length;
4593 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4595 if( RemainingPath != NULL &&
4596 RemainingPath->Length > 0)
4599 if( uniReparseName.Buffer[ (uniReparseName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
4600 RemainingPath->Buffer[ 0] != L'\\')
4603 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
4605 uniReparseName.Length += sizeof( WCHAR);
4608 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
4609 RemainingPath->Buffer,
4610 RemainingPath->Length);
4612 uniReparseName.Length += RemainingPath->Length;
4616 // Update the name in the file object
4619 if( FileObject->FileName.Buffer != NULL)
4622 AFSExFreePool( FileObject->FileName.Buffer);
4625 FileObject->FileName = uniReparseName;
4627 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4628 AFS_TRACE_LEVEL_VERBOSE,
4629 "AFSProcessDFSLink Reparsing access to Fcb %wZ FID %08lX-%08lX-%08lX-%08lX to %wZ\n",
4630 &DirEntry->NameInformation.FileName,
4631 DirEntry->ObjectInformation->FileId.Cell,
4632 DirEntry->ObjectInformation->FileId.Volume,
4633 DirEntry->ObjectInformation->FileId.Vnode,
4634 DirEntry->ObjectInformation->FileId.Unique,
4638 // Return status reparse ...
4641 ntStatus = STATUS_REPARSE;
4648 AFSExFreePool( pDirEntry);