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"
44 // On entry, *VolumeCB must have a held ReferenceCount provided by
45 // the caller which will not be released. On successful exit, *OutVolumeCB
46 // will be assigned the new current volume with a held ReferenceCount.
48 // On entry, *ParentDirectoryCB must have a held DirOpenReferenceCount
49 // provided by the caller. This reference will not be released.
50 // On exit, if OutParentDirectoryCB is set, it will have a new reference.
52 // On exit, if OutDirectoryCB is set, it will have a reference.
56 AFSLocateNameEntry( IN GUID *AuthGroup,
57 IN PFILE_OBJECT FileObject,
58 IN OUT UNICODE_STRING *RootPathName,
59 IN UNICODE_STRING *ParsedPathName,
60 IN AFSNameArrayHdr *NameArray,
62 IN AFSVolumeCB *VolumeCB,
63 IN AFSDirectoryCB *ParentDirectoryCB,
64 OUT AFSVolumeCB **OutVolumeCB,
65 OUT LONG *OutVolumeReferenceReason,
66 OUT AFSDirectoryCB **OutParentDirectoryCB,
67 OUT AFSDirectoryCB **OutDirectoryCB,
68 OUT PUNICODE_STRING ComponentName)
71 NTSTATUS ntStatus = STATUS_SUCCESS;
72 UNICODE_STRING uniPathName, uniComponentName, uniRemainingPath, uniSearchName, uniFullPathName;
74 AFSDirectoryCB *pDirEntry = NULL, *pParentDirEntry = NULL;
75 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
76 UNICODE_STRING uniSysName;
77 ULONG ulSubstituteIndex = 0;
78 BOOLEAN bSubstituteName = FALSE;
79 AFSNameArrayHdr *pNameArray = NameArray;
80 BOOLEAN bAllocatedSymLinkBuffer = FALSE;
81 UNICODE_STRING uniRelativeName, uniNoOpName;
82 AFSObjectInfoCB *pCurrentObject = NULL;
83 AFSObjectInfoCB *pParentObjectInfo = NULL;
84 AFSVolumeCB *pCurrentVolume = NULL;
85 AFSVolumeCB *pTargetVolume = NULL;
86 BOOLEAN bReleaseCurrentVolume = FALSE;
87 LONG VolumeReferenceReason;
88 BOOLEAN bSubstitutedName = FALSE;
94 ASSERT( *OutVolumeCB != VolumeCB);
96 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
97 AFS_TRACE_LEVEL_VERBOSE_2,
98 "AFSLocateNameEntry (FO: %p) Processing full name %wZ\n",
102 RtlInitUnicodeString( &uniSysName,
105 RtlInitUnicodeString( &uniRelativeName,
108 RtlInitUnicodeString( &uniNoOpName,
112 // Cleanup some parameters
115 if( ComponentName != NULL)
118 ComponentName->Length = 0;
119 ComponentName->MaximumLength = 0;
120 ComponentName->Buffer = NULL;
124 // We will parse through the filename, locating the directory nodes until we encounter a cache miss
125 // Starting at the root node
128 pParentDirEntry = NULL;
130 pDirEntry = ParentDirectoryCB;
133 // Increment our reference on this dir entry
136 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
138 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
139 AFS_TRACE_LEVEL_VERBOSE,
140 "AFSLocateNameEntry Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
141 &pDirEntry->NameInformation.FileName,
146 pCurrentVolume = VolumeCB;
148 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
150 lCount = AFSVolumeIncrement( pCurrentVolume,
151 VolumeReferenceReason);
153 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
154 AFS_TRACE_LEVEL_VERBOSE,
155 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
157 VolumeReferenceReason,
160 bReleaseCurrentVolume = TRUE;
162 uniPathName = *ParsedPathName;
164 uniFullPathName = *RootPathName;
166 uniComponentName.Length = uniComponentName.MaximumLength = 0;
167 uniComponentName.Buffer = NULL;
169 uniRemainingPath.Length = uniRemainingPath.MaximumLength = 0;
170 uniRemainingPath.Buffer = NULL;
172 uniSearchName.Length = uniSearchName.MaximumLength = 0;
173 uniSearchName.Buffer = NULL;
178 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
180 ASSERT( pDirEntry->DirOpenReferenceCount > 0);
183 // Check our total link count for this name array
186 if( pNameArray->LinkCount >= (LONG)pDevExt->Specific.RDR.MaxLinkCount)
189 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
192 pCurrentObject = pDirEntry->ObjectInformation;
194 KeQueryTickCount( &pCurrentObject->LastAccessCount);
197 // Check that the directory entry is not deleted or pending delete
200 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
203 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
204 AFS_TRACE_LEVEL_ERROR,
205 "AFSLocateNameEntry (FO: %p) Deleted parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
207 &pDirEntry->NameInformation.FileName,
208 pCurrentObject->FileId.Cell,
209 pCurrentObject->FileId.Volume,
210 pCurrentObject->FileId.Vnode,
211 pCurrentObject->FileId.Unique,
212 STATUS_FILE_DELETED));
214 try_return( ntStatus = STATUS_FILE_DELETED);
217 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
220 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
221 AFS_TRACE_LEVEL_ERROR,
222 "AFSLocateNameEntry (FO: %p) Delete pending on %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
224 &pDirEntry->NameInformation.FileName,
225 pCurrentObject->FileId.Cell,
226 pCurrentObject->FileId.Volume,
227 pCurrentObject->FileId.Vnode,
228 pCurrentObject->FileId.Unique,
229 STATUS_DELETE_PENDING));
231 try_return( ntStatus = STATUS_DELETE_PENDING);
235 // Check if the directory requires verification
238 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
239 ( pCurrentObject->FileType != AFS_FILE_TYPE_DIRECTORY ||
240 !AFSIsEnumerationInProcess( pCurrentObject)))
243 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
244 AFS_TRACE_LEVEL_VERBOSE,
245 "AFSLocateNameEntry (FO: %p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
247 &pDirEntry->NameInformation.FileName,
248 pCurrentObject->FileId.Cell,
249 pCurrentObject->FileId.Volume,
250 pCurrentObject->FileId.Vnode,
251 pCurrentObject->FileId.Unique));
254 // Directory TreeLock should be exclusively held
257 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
260 ntStatus = AFSVerifyEntry( AuthGroup,
263 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
265 if( !NT_SUCCESS( ntStatus))
268 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
269 AFS_TRACE_LEVEL_ERROR,
270 "AFSLocateNameEntry (FO: %p) Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
272 &pDirEntry->NameInformation.FileName,
273 pCurrentObject->FileId.Cell,
274 pCurrentObject->FileId.Volume,
275 pCurrentObject->FileId.Vnode,
276 pCurrentObject->FileId.Unique,
279 try_return( ntStatus);
284 // Ensure the parent node has been evaluated, if not then go do it now
287 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) ||
288 pCurrentObject->FileType == AFS_FILE_TYPE_UNKNOWN)
291 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
292 AFS_TRACE_LEVEL_VERBOSE,
293 "AFSLocateNameEntry (FO: %p) Evaluating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
295 &pDirEntry->NameInformation.FileName,
296 pCurrentObject->FileId.Cell,
297 pCurrentObject->FileId.Volume,
298 pCurrentObject->FileId.Vnode,
299 pCurrentObject->FileId.Unique));
301 ntStatus = AFSEvaluateNode( AuthGroup,
304 if( !NT_SUCCESS( ntStatus))
307 if ( ntStatus == STATUS_NOT_A_DIRECTORY)
310 if ( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
313 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
314 AFS_TRACE_LEVEL_ERROR,
315 "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT NULL Status %08lX\n",
317 &pDirEntry->NameInformation.FileName,
318 pCurrentObject->FileId.Cell,
319 pCurrentObject->FileId.Volume,
320 pCurrentObject->FileId.Vnode,
321 pCurrentObject->FileId.Unique,
327 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
328 AFS_TRACE_LEVEL_ERROR,
329 "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT %08lX-%08lX-%08lX-%08lX Status %08lX\n",
331 &pDirEntry->NameInformation.FileName,
332 pCurrentObject->FileId.Cell,
333 pCurrentObject->FileId.Volume,
334 pCurrentObject->FileId.Vnode,
335 pCurrentObject->FileId.Unique,
336 pCurrentObject->ParentFileId.Cell,
337 pCurrentObject->ParentFileId.Volume,
338 pCurrentObject->ParentFileId.Vnode,
339 pCurrentObject->ParentFileId.Unique,
345 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
346 AFS_TRACE_LEVEL_ERROR,
347 "AFSLocateNameEntry (FO: %p) Failed to evaluate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
349 &pDirEntry->NameInformation.FileName,
350 pCurrentObject->FileId.Cell,
351 pCurrentObject->FileId.Volume,
352 pCurrentObject->FileId.Vnode,
353 pCurrentObject->FileId.Unique,
357 try_return( ntStatus);
360 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
364 // If this is a mount point or symlink then go get the real directory node
367 switch( pCurrentObject->FileType)
370 case AFS_FILE_TYPE_SYMLINK:
373 UNICODE_STRING uniTempName;
374 WCHAR *pTmpBuffer = NULL;
378 // Check if the flag is set to NOT evaluate a symlink
379 // and we are done with the parsing
382 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL) &&
383 uniRemainingPath.Length == 0)
387 // Pass back the directory entries
390 *OutParentDirectoryCB = pParentDirEntry;
392 pParentDirEntry = NULL;
394 *OutDirectoryCB = pDirEntry;
398 *OutVolumeCB = pCurrentVolume;
400 *OutVolumeReferenceReason = VolumeReferenceReason;
402 bReleaseCurrentVolume = FALSE;
404 *RootPathName = uniFullPathName;
406 try_return( ntStatus);
409 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
412 AFSAcquireExcl( &pDirEntry->NonPaged->Lock,
415 if( pDirEntry->NameInformation.TargetName.Length == 0)
419 // We'll reset the DV to ensure we validate the metadata content
422 pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
424 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
426 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
427 AFS_TRACE_LEVEL_VERBOSE,
428 "AFSLocateNameEntry (FO: %p) Verifying symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
430 &pDirEntry->NameInformation.FileName,
431 pCurrentObject->FileId.Cell,
432 pCurrentObject->FileId.Volume,
433 pCurrentObject->FileId.Vnode,
434 pCurrentObject->FileId.Unique));
437 // Directory TreeLock should be exclusively held
440 ntStatus = AFSVerifyEntry( AuthGroup,
443 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
445 if( !NT_SUCCESS( ntStatus))
448 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
449 AFS_TRACE_LEVEL_ERROR,
450 "AFSLocateNameEntry (FO: %p) Failed to verify symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
452 &pDirEntry->NameInformation.FileName,
453 pCurrentObject->FileId.Cell,
454 pCurrentObject->FileId.Volume,
455 pCurrentObject->FileId.Vnode,
456 pCurrentObject->FileId.Unique,
459 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
461 try_return( ntStatus);
465 // If the type changed then reprocess this entry
468 if( pCurrentObject->FileType != AFS_FILE_TYPE_SYMLINK)
471 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
479 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
483 // If we were given a zero length target name then deny access to the entry
486 if( pDirEntry->NameInformation.TargetName.Length == 0)
489 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
491 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
492 AFS_TRACE_LEVEL_ERROR,
493 "AFSLocateNameEntry (FO: %p) Failed to retrieve target name for symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
495 &pDirEntry->NameInformation.FileName,
496 pCurrentObject->FileId.Cell,
497 pCurrentObject->FileId.Volume,
498 pCurrentObject->FileId.Vnode,
499 pCurrentObject->FileId.Unique,
502 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
504 try_return( ntStatus);
507 if( AFSIsRelativeName( &pDirEntry->NameInformation.TargetName))
510 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
511 AFS_TRACE_LEVEL_VERBOSE,
512 "AFSLocateNameEntry (FO: %p) Processing relative symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
514 &pDirEntry->NameInformation.TargetName,
515 &pDirEntry->NameInformation.FileName,
516 pCurrentObject->FileId.Cell,
517 pCurrentObject->FileId.Volume,
518 pCurrentObject->FileId.Vnode,
519 pCurrentObject->FileId.Unique));
522 // We'll substitute this name into the current process name
523 // starting at where we sit in the path
526 uniTempName.Length = 0;
527 uniTempName.MaximumLength = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer) +
528 pDirEntry->NameInformation.TargetName.Length +
530 uniRemainingPath.Length;
532 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
533 uniTempName.MaximumLength,
534 AFS_NAME_BUFFER_ONE_TAG);
536 if( uniTempName.Buffer == NULL)
539 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
541 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
545 // We have so first copy in the portion up to the component
549 RtlCopyMemory( uniTempName.Buffer,
550 uniFullPathName.Buffer,
551 (ULONG)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer));
553 uniTempName.Length = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer);
555 if( bAllocatedSymLinkBuffer ||
559 pTmpBuffer = uniFullPathName.Buffer;
562 bAllocatedSymLinkBuffer = TRUE;
565 // Have we parsed this name yet? Better have at least once ...
568 if( uniComponentName.Length == 0)
574 // Copy in the target name ...
577 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
578 pDirEntry->NameInformation.TargetName.Buffer,
579 pDirEntry->NameInformation.TargetName.Length);
581 uniPathName.Buffer = &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)];
583 uniPathName.Length += pDirEntry->NameInformation.TargetName.Length;
584 uniPathName.MaximumLength = uniTempName.MaximumLength;
586 uniTempName.Length += pDirEntry->NameInformation.TargetName.Length;
589 // And now any remaining portion of the name
592 if( uniRemainingPath.Length > 0)
595 if( uniRemainingPath.Buffer[ 0] != L'\\')
598 uniRemainingPath.Buffer--;
599 uniRemainingPath.Length += sizeof( WCHAR);
601 uniPathName.Length += sizeof( WCHAR);
604 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
605 uniRemainingPath.Buffer,
606 uniRemainingPath.Length);
608 uniTempName.Length += uniRemainingPath.Length;
611 uniFullPathName = uniTempName;
613 if( pTmpBuffer != NULL)
616 AFSExFreePoolWithTag( pTmpBuffer, 0);
619 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
622 // Dereference the current entry ..
625 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
627 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
628 AFS_TRACE_LEVEL_VERBOSE,
629 "AFSLocateNameEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
630 &pDirEntry->NameInformation.FileName,
635 ASSERT( lCount >= 0);
638 // OK, need to back up one entry for the correct parent since the current
639 // entry we are on is the symlink itself
642 pDirEntry = AFSBackupEntry( pNameArray);
644 pCurrentObject = pDirEntry->ObjectInformation;
647 // Increment our reference on this dir entry
650 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
652 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
653 AFS_TRACE_LEVEL_VERBOSE,
654 "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
655 &pDirEntry->NameInformation.FileName,
660 if ( pParentDirEntry)
663 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
665 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
666 AFS_TRACE_LEVEL_VERBOSE,
667 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
668 &pParentDirEntry->NameInformation.FileName,
673 pParentDirEntry = NULL;
676 if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
679 pParentDirEntry = AFSGetParentEntry( pNameArray);
681 ASSERT( pParentDirEntry != pDirEntry);
683 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
685 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
686 AFS_TRACE_LEVEL_VERBOSE,
687 "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
688 &pParentDirEntry->NameInformation.FileName,
694 if ( pDirEntry->ObjectInformation->VolumeCB != pCurrentVolume)
697 lCount = AFSVolumeDecrement( pCurrentVolume,
698 VolumeReferenceReason);
700 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
701 AFS_TRACE_LEVEL_VERBOSE,
702 "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
704 VolumeReferenceReason,
707 pCurrentVolume = pDirEntry->ObjectInformation->VolumeCB;
709 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
711 lCount = AFSVolumeIncrement( pCurrentVolume,
712 VolumeReferenceReason);
714 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
715 AFS_TRACE_LEVEL_VERBOSE,
716 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
718 VolumeReferenceReason,
725 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
726 AFS_TRACE_LEVEL_VERBOSE,
727 "AFSLocateNameEntry (FO: %p) Processing absolute symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
729 &pDirEntry->NameInformation.TargetName,
730 &pDirEntry->NameInformation.FileName,
731 pCurrentObject->FileId.Cell,
732 pCurrentObject->FileId.Volume,
733 pCurrentObject->FileId.Vnode,
734 pCurrentObject->FileId.Unique));
736 if ( !AFSIsAbsoluteAFSName( &pDirEntry->NameInformation.TargetName))
739 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
740 AFS_TRACE_LEVEL_ERROR,
741 "AFSLocateNameEntry Name %wZ contains invalid server name\n",
742 &pDirEntry->NameInformation.TargetName));
745 // The correct response would be STATUS_OBJECT_PATH_INVALID
746 // but that prevents cmd.exe from performing a recursive
747 // directory enumeration when opening a directory entry
748 // that represents a symlink to an invalid path is discovered.
751 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
753 try_return( ntStatus = STATUS_OBJECT_PATH_NOT_FOUND);
757 // We'll substitute this name into the current process name
758 // starting at where we sit in the path
761 uniTempName.Length = 0;
762 uniTempName.MaximumLength = pDirEntry->NameInformation.TargetName.Length +
764 uniRemainingPath.Length;
766 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
767 uniTempName.MaximumLength,
768 AFS_NAME_BUFFER_TWO_TAG);
770 if( uniTempName.Buffer == NULL)
773 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
775 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
778 if( bAllocatedSymLinkBuffer ||
782 pTmpBuffer = uniFullPathName.Buffer;
785 bAllocatedSymLinkBuffer = TRUE;
788 // Have we parsed this name yet? Better have at least once ...
791 if( uniComponentName.Length == 0)
797 // Copy in the target name ...
800 RtlCopyMemory( uniTempName.Buffer,
801 &pDirEntry->NameInformation.TargetName.Buffer[ AFSMountRootName.Length/sizeof( WCHAR)],
802 pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length);
804 uniTempName.Length = pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length;
807 // And now any remaining portion of the name
810 if( uniRemainingPath.Length > 0)
813 if( uniRemainingPath.Buffer[ 0] != L'\\')
816 uniRemainingPath.Buffer--;
817 uniRemainingPath.Length += sizeof( WCHAR);
820 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
821 uniRemainingPath.Buffer,
822 uniRemainingPath.Length);
824 uniTempName.Length += uniRemainingPath.Length;
827 uniFullPathName = uniTempName;
829 uniPathName = uniTempName;
831 if( pTmpBuffer != NULL)
834 AFSExFreePoolWithTag( pTmpBuffer, 0);
837 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
840 // If our current volume is not the global root then make it so ...
843 if( pCurrentVolume != AFSGlobalRoot)
846 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
847 AFS_TRACE_LEVEL_VERBOSE,
848 "AFSLocateNameEntry (FO: %p) Current volume not global, resetting for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
850 &pDirEntry->NameInformation.FileName,
851 pCurrentObject->FileId.Cell,
852 pCurrentObject->FileId.Volume,
853 pCurrentObject->FileId.Vnode,
854 pCurrentObject->FileId.Unique));
856 lCount = AFSVolumeDecrement( pCurrentVolume,
857 VolumeReferenceReason);
859 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
860 AFS_TRACE_LEVEL_VERBOSE,
861 "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
863 VolumeReferenceReason,
866 pCurrentVolume = AFSGlobalRoot;
868 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
870 lCount = AFSVolumeIncrement( pCurrentVolume,
871 VolumeReferenceReason);
873 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
874 AFS_TRACE_LEVEL_VERBOSE,
875 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
877 VolumeReferenceReason,
882 // Dereference our current dir entry
885 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
887 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
888 AFS_TRACE_LEVEL_VERBOSE,
889 "AFSLocateNameEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
890 &pDirEntry->NameInformation.FileName,
895 ASSERT( lCount >= 0);
897 pDirEntry = pCurrentVolume->DirectoryCB;
899 pCurrentObject = pDirEntry->ObjectInformation;
902 // Reference the new dir entry
905 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
907 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
908 AFS_TRACE_LEVEL_VERBOSE,
909 "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
910 &pDirEntry->NameInformation.FileName,
916 // Reset the name array
917 // Persist the link count in the name array
920 lLinkCount = pNameArray->LinkCount;
922 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
923 AFS_TRACE_LEVEL_VERBOSE,
924 "AFSLocateNameEntry (FO: %p) Resetting name array for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
926 &pDirEntry->NameInformation.FileName,
927 pCurrentObject->FileId.Cell,
928 pCurrentObject->FileId.Volume,
929 pCurrentObject->FileId.Vnode,
930 pCurrentObject->FileId.Unique));
932 AFSResetNameArray( pNameArray,
935 pNameArray->LinkCount = lLinkCount;
937 if ( pParentDirEntry)
940 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
942 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
943 AFS_TRACE_LEVEL_VERBOSE,
944 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
945 &pParentDirEntry->NameInformation.FileName,
950 pParentDirEntry = NULL;
955 // Increment our link count
958 lCount = InterlockedIncrement( &pNameArray->LinkCount);
963 case AFS_FILE_TYPE_MOUNTPOINT:
967 // Check if the flag is set to NOT evaluate a mount point
968 // and we are done with the parsing
971 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL) &&
972 uniRemainingPath.Length == 0)
976 // Pass back the directory entries
979 *OutParentDirectoryCB = pParentDirEntry;
981 pParentDirEntry = NULL;
983 *OutDirectoryCB = pDirEntry;
987 *OutVolumeCB = pCurrentVolume;
989 *OutVolumeReferenceReason = VolumeReferenceReason;
991 bReleaseCurrentVolume = FALSE;
993 *RootPathName = uniFullPathName;
995 try_return( ntStatus);
998 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
999 AFS_TRACE_LEVEL_VERBOSE,
1000 "AFSLocateNameEntry (FO: %p) Building MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1002 &pDirEntry->NameInformation.FileName,
1003 pCurrentObject->FileId.Cell,
1004 pCurrentObject->FileId.Volume,
1005 pCurrentObject->FileId.Vnode,
1006 pCurrentObject->FileId.Unique));
1009 // Go retrieve the target entry for this node
1010 // Release the current volume cb entry since we would
1011 // have lock inversion in the following call
1012 // Also decrement the ref count on the volume
1015 ntStatus = AFSBuildMountPointTarget( AuthGroup,
1019 if( !NT_SUCCESS( ntStatus))
1022 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1023 AFS_TRACE_LEVEL_ERROR,
1024 "AFSLocateNameEntry (FO: %p) Failed to build MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1026 &pDirEntry->NameInformation.FileName,
1027 pCurrentObject->FileId.Cell,
1028 pCurrentObject->FileId.Volume,
1029 pCurrentObject->FileId.Vnode,
1030 pCurrentObject->FileId.Unique,
1033 try_return( ntStatus);
1036 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
1038 lCount = AFSVolumeDecrement( pCurrentVolume,
1039 VolumeReferenceReason);
1041 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1042 AFS_TRACE_LEVEL_VERBOSE,
1043 "AFSLocateNameEntry Decrement2 count on volume %p Reason %u Cnt %d\n",
1045 VolumeReferenceReason,
1048 pCurrentVolume = pTargetVolume;
1050 pTargetVolume = NULL;
1052 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
1054 VolumeReferenceReason = AFS_VOLUME_REFERENCE_MOUNTPT;
1057 // We want to restart processing here on the new parent ...
1058 // Deref and ref count the entries
1061 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1063 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1064 AFS_TRACE_LEVEL_VERBOSE,
1065 "AFSLocateNameEntry Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
1066 &pDirEntry->NameInformation.FileName,
1071 ASSERT( lCount >= 0);
1073 pDirEntry = pCurrentVolume->DirectoryCB;
1075 pCurrentObject = pDirEntry->ObjectInformation;
1077 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1079 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1080 AFS_TRACE_LEVEL_VERBOSE,
1081 "AFSLocateNameEntry Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
1082 &pDirEntry->NameInformation.FileName,
1088 // The name array stores both the mount point and the target.
1089 // Insert the target.
1092 AFSInsertNextElement( pNameArray,
1095 if ( pParentDirEntry)
1098 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1100 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1101 AFS_TRACE_LEVEL_VERBOSE,
1102 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1103 &pParentDirEntry->NameInformation.FileName,
1108 pParentDirEntry = NULL;
1112 // Increment our link count
1115 lCount = InterlockedIncrement( &pNameArray->LinkCount);
1120 case AFS_FILE_TYPE_DFSLINK:
1123 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL))
1127 // Pass back the directory entries
1130 *OutParentDirectoryCB = pParentDirEntry;
1132 pParentDirEntry = NULL;
1134 *OutDirectoryCB = pDirEntry;
1138 *OutVolumeCB = pCurrentVolume;
1140 *OutVolumeReferenceReason = VolumeReferenceReason;
1142 bReleaseCurrentVolume = FALSE;
1144 *RootPathName = uniFullPathName;
1146 try_return( ntStatus);
1150 // This is a DFS link so we need to update the file name and return STATUS_REPARSE to the
1151 // system for it to reevaluate it
1154 if( FileObject != NULL)
1157 ntStatus = AFSProcessDFSLink( pDirEntry,
1166 // This is where we have been re-entered from an NP evaluation call via the BuildBranch()
1170 ntStatus = STATUS_INVALID_PARAMETER;
1173 if( ntStatus != STATUS_SUCCESS &&
1174 ntStatus != STATUS_REPARSE)
1177 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1178 AFS_TRACE_LEVEL_ERROR,
1179 "AFSLocateNameEntry (FO: %p) Failed to process DFSLink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1181 &pDirEntry->NameInformation.FileName,
1182 pCurrentObject->FileId.Cell,
1183 pCurrentObject->FileId.Volume,
1184 pCurrentObject->FileId.Vnode,
1185 pCurrentObject->FileId.Unique,
1189 try_return( ntStatus);
1192 case AFS_FILE_TYPE_UNKNOWN:
1193 case AFS_FILE_TYPE_INVALID:
1197 // Something was not processed ...
1200 try_return( ntStatus = STATUS_ACCESS_DENIED);
1203 } /* end of switch */
1206 // If the parent is not initialized then do it now
1209 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1210 !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED) &&
1211 uniPathName.Length > 0)
1214 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1215 AFS_TRACE_LEVEL_VERBOSE,
1216 "AFSLocateNameEntry (FO: %p) Enumerating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1218 &pDirEntry->NameInformation.FileName,
1219 pCurrentObject->FileId.Cell,
1220 pCurrentObject->FileId.Volume,
1221 pCurrentObject->FileId.Vnode,
1222 pCurrentObject->FileId.Unique));
1224 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1227 if( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1230 ntStatus = AFSEnumerateDirectory( AuthGroup,
1234 if( !NT_SUCCESS( ntStatus))
1237 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1239 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1240 AFS_TRACE_LEVEL_ERROR,
1241 "AFSLocateNameEntry (FO: %p) Failed to enumerate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1243 &pDirEntry->NameInformation.FileName,
1244 pCurrentObject->FileId.Cell,
1245 pCurrentObject->FileId.Volume,
1246 pCurrentObject->FileId.Vnode,
1247 pCurrentObject->FileId.Unique,
1250 try_return( ntStatus);
1254 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1256 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1259 if( uniPathName.Length > 0)
1262 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1263 AFS_TRACE_LEVEL_ERROR,
1264 "AFSLocateNameEntry (FO: %p) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1266 &pDirEntry->NameInformation.FileName,
1267 pCurrentObject->FileId.Cell,
1268 pCurrentObject->FileId.Volume,
1269 pCurrentObject->FileId.Vnode,
1270 pCurrentObject->FileId.Unique));
1272 // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1273 // one of the components of the path is not a directory. However, returning
1274 // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1275 // Instead IIS insists on treating the target file as if it is a directory containing
1276 // a potential web.config file. NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1277 // AFS will follow suit.
1279 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1284 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1285 AFS_TRACE_LEVEL_VERBOSE,
1286 "AFSLocateNameEntry (FO: %p) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1288 &pDirEntry->NameInformation.FileName,
1289 pCurrentObject->FileId.Cell,
1290 pCurrentObject->FileId.Volume,
1291 pCurrentObject->FileId.Vnode,
1292 pCurrentObject->FileId.Unique));
1295 // Pass back the directory entries
1298 *OutParentDirectoryCB = pParentDirEntry;
1300 pParentDirEntry = NULL;
1302 *OutDirectoryCB = pDirEntry;
1306 *OutVolumeCB = pCurrentVolume;
1308 *OutVolumeReferenceReason = VolumeReferenceReason;
1310 bReleaseCurrentVolume = FALSE;
1312 *RootPathName = uniFullPathName;
1315 try_return( ntStatus);
1319 // If we are at the end of the processing, set our returned information and get out
1322 if( uniPathName.Length == 0)
1325 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1326 AFS_TRACE_LEVEL_VERBOSE,
1327 "AFSLocateNameEntry (FO: %p) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1329 &pDirEntry->NameInformation.FileName,
1330 pCurrentObject->FileId.Cell,
1331 pCurrentObject->FileId.Volume,
1332 pCurrentObject->FileId.Vnode,
1333 pCurrentObject->FileId.Unique));
1336 // Pass back the directory entries
1339 *OutParentDirectoryCB = pParentDirEntry;
1341 pParentDirEntry = NULL;
1343 *OutDirectoryCB = pDirEntry;
1347 *OutVolumeCB = pCurrentVolume;
1349 *OutVolumeReferenceReason = VolumeReferenceReason;
1351 bReleaseCurrentVolume = FALSE;
1353 *RootPathName = uniFullPathName;
1355 try_return( ntStatus);
1359 // We may have returned to the top of the while( TRUE)
1361 if( bSubstituteName &&
1362 uniSearchName.Buffer != NULL)
1365 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1367 bSubstituteName = FALSE;
1369 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1370 uniSearchName.Buffer = NULL;
1373 ulSubstituteIndex = 1;
1375 ntStatus = STATUS_SUCCESS;
1378 // Get the next component name
1381 FsRtlDissectName( uniPathName,
1386 // Check for the . and .. in the path
1389 if( RtlCompareUnicodeString( &uniComponentName,
1394 uniPathName = uniRemainingPath;
1399 if( RtlCompareUnicodeString( &uniComponentName,
1404 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1405 AFS_TRACE_LEVEL_VERBOSE,
1406 "AFSLocateNameEntry (FO: %p) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1408 &pDirEntry->NameInformation.FileName,
1409 pCurrentObject->FileId.Cell,
1410 pCurrentObject->FileId.Volume,
1411 pCurrentObject->FileId.Vnode,
1412 pCurrentObject->FileId.Unique));
1415 // Need to back up one entry in the name array
1417 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1419 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1420 AFS_TRACE_LEVEL_VERBOSE,
1421 "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1422 &pDirEntry->NameInformation.FileName,
1427 ASSERT( lCount >= 0);
1429 pDirEntry = AFSBackupEntry( NameArray);
1431 if( pDirEntry == NULL)
1434 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1435 AFS_TRACE_LEVEL_ERROR,
1436 "AFSLocateNameEntry AFSBackupEntry failed\n"));
1438 try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1441 pCurrentObject = pDirEntry->ObjectInformation;
1443 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1445 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1446 AFS_TRACE_LEVEL_VERBOSE,
1447 "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1448 &pDirEntry->NameInformation.FileName,
1453 if ( pParentDirEntry)
1456 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1458 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1459 AFS_TRACE_LEVEL_VERBOSE,
1460 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1461 &pParentDirEntry->NameInformation.FileName,
1466 pParentDirEntry = NULL;
1469 if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1472 pParentDirEntry = AFSGetParentEntry( pNameArray);
1474 ASSERT( pParentDirEntry != pDirEntry);
1476 if ( pParentDirEntry)
1479 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
1481 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1482 AFS_TRACE_LEVEL_VERBOSE,
1483 "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
1484 &pParentDirEntry->NameInformation.FileName,
1491 if ( pDirEntry->ObjectInformation->VolumeCB != pCurrentVolume)
1494 lCount = AFSVolumeDecrement( pCurrentVolume,
1495 VolumeReferenceReason);
1497 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1498 AFS_TRACE_LEVEL_VERBOSE,
1499 "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
1501 VolumeReferenceReason,
1504 pCurrentVolume = pDirEntry->ObjectInformation->VolumeCB;
1506 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
1508 lCount = AFSVolumeIncrement( pCurrentVolume,
1509 VolumeReferenceReason);
1511 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1512 AFS_TRACE_LEVEL_VERBOSE,
1513 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
1515 VolumeReferenceReason,
1519 uniPathName = uniRemainingPath;
1525 // Update our pointers
1528 if ( pParentDirEntry)
1531 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1533 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1534 AFS_TRACE_LEVEL_VERBOSE,
1535 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1536 &pParentDirEntry->NameInformation.FileName,
1542 pParentDirEntry = pDirEntry;
1546 pCurrentObject = NULL;
1548 uniSearchName = uniComponentName;
1550 while( pDirEntry == NULL)
1554 // If the SearchName contains @SYS then we perform the substitution.
1555 // If there is no substitution we give up.
1558 if( !bSubstituteName &&
1559 FsRtlIsNameInExpression( &uniSysName,
1565 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1566 AFS_TRACE_LEVEL_VERBOSE_2,
1567 "AFSLocateNameEntry (FO: %p) Processing @SYS substitution for %wZ Index %08lX\n",
1570 ulSubstituteIndex));
1572 ntStatus = AFSSubstituteSysName( &uniComponentName,
1576 if ( NT_SUCCESS( ntStatus))
1579 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1580 AFS_TRACE_LEVEL_VERBOSE_2,
1581 "AFSLocateNameEntry (FO: %p) Located substitution %wZ for %wZ Index %08lX\n",
1585 ulSubstituteIndex));
1588 // Go reparse the name again
1591 bSubstituteName = TRUE;
1593 ulSubstituteIndex++; // For the next entry, if needed
1595 continue; // while( pDirEntry == NULL)
1600 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1601 AFS_TRACE_LEVEL_ERROR,
1602 "AFSLocateNameEntry (FO: %p) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1608 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1612 // Pass back the directory entries
1615 *OutParentDirectoryCB = pParentDirEntry;
1617 pParentDirEntry = NULL;
1619 *OutDirectoryCB = NULL;
1621 *OutVolumeCB = pCurrentVolume;
1623 *OutVolumeReferenceReason = VolumeReferenceReason;
1625 bReleaseCurrentVolume = FALSE;
1627 if( ComponentName != NULL)
1630 *ComponentName = uniComponentName;
1633 *RootPathName = uniFullPathName;
1637 // We can't possibly have a pDirEntry since the lookup failed
1639 try_return( ntStatus);
1644 // Generate the CRC on the node and perform a case sensitive lookup
1647 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1648 AFS_TRACE_LEVEL_VERBOSE_2,
1649 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case sensitive\n",
1653 ulCRC = AFSGenerateCRC( &uniSearchName,
1656 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1659 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1663 if( pDirEntry == NULL)
1667 // Missed so perform a case insensitive lookup
1670 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1671 AFS_TRACE_LEVEL_VERBOSE_2,
1672 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case insensitive\n",
1676 ulCRC = AFSGenerateCRC( &uniSearchName,
1679 AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1683 if( pDirEntry == NULL)
1687 // OK, if this component is a valid short name then try
1688 // a lookup in the short name tree
1691 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1692 RtlIsNameLegalDOS8Dot3( &uniSearchName,
1697 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1698 AFS_TRACE_LEVEL_VERBOSE_2,
1699 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ short name\n",
1703 AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1708 if ( pDirEntry == NULL &&
1709 pParentDirEntry->ObjectInformation->VolumeCB == AFSGlobalRoot)
1713 // Check with the service to see if this is a valid cell name
1714 // that can be automatically resolved. Drop the shared TreeLock
1715 // since AFSCheckCellName must acquire it exclusively.
1718 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1720 ntStatus = AFSCheckCellName( AuthGroup,
1724 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1728 if( pDirEntry == NULL)
1732 // If we substituted a name then reset our search name and try again
1735 if( bSubstituteName)
1738 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1740 uniSearchName = uniComponentName;
1742 bSubstituteName = FALSE;
1744 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1746 continue; // while( pDirEntry == NULL)
1750 // Node name not found so get out
1753 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1755 if( uniRemainingPath.Length > 0)
1758 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1760 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1761 AFS_TRACE_LEVEL_VERBOSE,
1762 "AFSLocateNameEntry (FO: %p) Returning path not found for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
1765 pParentDirEntry->ObjectInformation->FileId.Cell,
1766 pParentDirEntry->ObjectInformation->FileId.Volume,
1767 pParentDirEntry->ObjectInformation->FileId.Vnode,
1768 pParentDirEntry->ObjectInformation->FileId.Unique));
1773 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1775 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1776 AFS_TRACE_LEVEL_VERBOSE,
1777 "AFSLocateNameEntry (FO: %p) Returning name not found for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
1780 pParentDirEntry->ObjectInformation->FileId.Cell,
1781 pParentDirEntry->ObjectInformation->FileId.Volume,
1782 pParentDirEntry->ObjectInformation->FileId.Vnode,
1783 pParentDirEntry->ObjectInformation->FileId.Unique));
1786 // Pass back the directory entries
1789 *OutParentDirectoryCB = pParentDirEntry;
1791 pParentDirEntry = NULL;
1793 *OutDirectoryCB = NULL;
1795 *OutVolumeCB = pCurrentVolume;
1797 *OutVolumeReferenceReason = VolumeReferenceReason;
1799 bReleaseCurrentVolume = FALSE;
1801 if( ComponentName != NULL)
1804 *ComponentName = uniComponentName;
1807 *RootPathName = uniFullPathName;
1810 try_return( ntStatus);
1817 // Here we have a match on the case insensitive lookup for the name. If there
1818 // Is more than one link entry for this node then fail the lookup request
1821 pCurrentObject = pDirEntry->ObjectInformation;
1823 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1824 pDirEntry->CaseInsensitiveList.fLink != NULL)
1828 // Increment our dir entry ref count since we will decrement it on exit
1831 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1833 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1834 AFS_TRACE_LEVEL_VERBOSE,
1835 "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1836 &pDirEntry->NameInformation.FileName,
1841 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1843 try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1848 if( pDirEntry != NULL)
1852 // If the verify flag is set on the parent and the current entry is deleted
1853 // revalidate the parent and search again.
1856 pCurrentObject = pDirEntry->ObjectInformation;
1858 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1859 BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1862 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1864 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1865 AFS_TRACE_LEVEL_VERBOSE,
1866 "AFSLocateNameEntry (FO: %p) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1868 &pParentDirEntry->NameInformation.FileName,
1869 pParentDirEntry->ObjectInformation->FileId.Cell,
1870 pParentDirEntry->ObjectInformation->FileId.Volume,
1871 pParentDirEntry->ObjectInformation->FileId.Vnode,
1872 pParentDirEntry->ObjectInformation->FileId.Unique));
1875 // Directory TreeLock should be exclusively held
1878 AFSAcquireExcl( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1881 ntStatus = AFSVerifyEntry( AuthGroup,
1884 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1886 if( !NT_SUCCESS( ntStatus))
1889 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1890 AFS_TRACE_LEVEL_ERROR,
1891 "AFSLocateNameEntry (FO: %p) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1893 &pParentDirEntry->NameInformation.FileName,
1894 pParentDirEntry->ObjectInformation->FileId.Cell,
1895 pParentDirEntry->ObjectInformation->FileId.Volume,
1896 pParentDirEntry->ObjectInformation->FileId.Vnode,
1897 pParentDirEntry->ObjectInformation->FileId.Unique,
1900 try_return( ntStatus);
1903 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1904 AFS_TRACE_LEVEL_VERBOSE,
1905 "AFSLocateNameEntry (FO: %p) Reprocessing component %wZ in parent %wZ\n",
1908 &pParentDirEntry->NameInformation.FileName));
1913 pCurrentObject = NULL;
1919 // Increment our dir entry ref count
1922 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1924 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1925 AFS_TRACE_LEVEL_VERBOSE,
1926 "AFSLocateNameEntry Increment6 count on %wZ DE %p Ccb %p Cnt %d\n",
1927 &pDirEntry->NameInformation.FileName,
1933 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1935 } // End while( pDirEntry == NULL)
1938 // If we have a dirEntry for this component, perform some basic validation on it
1941 if( pDirEntry != NULL)
1944 pCurrentObject = pDirEntry->ObjectInformation;
1946 if (BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1949 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1950 AFS_TRACE_LEVEL_ERROR,
1951 "AFSLocateNameEntry (FO: %p) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1953 &pDirEntry->NameInformation.FileName,
1954 pCurrentObject->FileId.Cell,
1955 pCurrentObject->FileId.Volume,
1956 pCurrentObject->FileId.Vnode,
1957 pCurrentObject->FileId.Unique));
1960 // This entry was deleted through the invalidation call back so perform cleanup
1964 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1967 pParentObjectInfo = AFSFindObjectInfo( pCurrentObject->VolumeCB,
1968 &pCurrentObject->ParentFileId,
1972 ASSERT( pParentObjectInfo != NULL);
1974 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1977 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1980 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1982 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1983 AFS_TRACE_LEVEL_VERBOSE,
1984 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1985 &pDirEntry->NameInformation.FileName,
1990 ASSERT( lCount >= 0);
1993 pDirEntry->NameArrayReferenceCount <= 0)
1996 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1997 AFS_TRACE_LEVEL_VERBOSE,
1998 "AFSLocateNameEntry Deleting dir entry %p (%p) for %wZ\n",
2001 &pDirEntry->NameInformation.FileName));
2004 // Remove and delete the directory entry from the parent list
2007 AFSDeleteDirEntry( pParentObjectInfo,
2010 AFSAcquireShared( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
2013 if( pCurrentObject->ObjectReferenceCount <= 0)
2016 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
2019 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2020 AFS_TRACE_LEVEL_VERBOSE,
2021 "AFSLocateNameEntry Removing object %p from volume tree\n",
2024 AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
2025 &pCurrentObject->TreeEntry);
2027 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
2031 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
2036 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2037 AFS_TRACE_LEVEL_VERBOSE,
2038 "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
2040 &pDirEntry->NameInformation.FileName));
2042 SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
2044 AFSRemoveNameEntry( pParentObjectInfo,
2048 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2050 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
2053 // We deleted the dir entry so check if there is any remaining portion
2054 // of the name to process.
2057 if( uniRemainingPath.Length > 0)
2060 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
2062 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2063 AFS_TRACE_LEVEL_VERBOSE,
2064 "AFSLocateNameEntry (FO: %p) Returning path not found(2) for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
2067 pParentObjectInfo->FileId.Cell,
2068 pParentObjectInfo->FileId.Volume,
2069 pParentObjectInfo->FileId.Vnode,
2070 pParentObjectInfo->FileId.Unique));
2072 AFSReleaseObjectInfo( &pParentObjectInfo);
2077 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
2079 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2080 AFS_TRACE_LEVEL_VERBOSE,
2081 "AFSLocateNameEntry (FO: %p) Returning name not found(2) for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
2084 pParentObjectInfo->FileId.Cell,
2085 pParentObjectInfo->FileId.Volume,
2086 pParentObjectInfo->FileId.Vnode,
2087 pParentObjectInfo->FileId.Unique));
2089 AFSReleaseObjectInfo( &pParentObjectInfo);
2092 // Pass back the directory entries
2095 *OutParentDirectoryCB = pParentDirEntry;
2097 pParentDirEntry = NULL;
2099 *OutDirectoryCB = NULL;
2101 *OutVolumeCB = pCurrentVolume;
2103 *OutVolumeReferenceReason = VolumeReferenceReason;
2105 bReleaseCurrentVolume = FALSE;
2107 if( ComponentName != NULL)
2110 *ComponentName = uniComponentName;
2113 *RootPathName = uniFullPathName;
2118 if( ntStatus != STATUS_SUCCESS)
2121 try_return( ntStatus);
2125 // If we ended up substituting a name in the component then update
2126 // the full path and update the pointers
2129 if( bSubstituteName)
2132 BOOLEAN bRelativeOpen = FALSE;
2134 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2135 AFS_TRACE_LEVEL_VERBOSE_2,
2136 "AFSLocateNameEntry (FO: %p) Substituting %wZ into %wZ Index %08lX\n",
2140 ulSubstituteIndex));
2142 if( FileObject != NULL &&
2143 FileObject->RelatedFileObject != NULL)
2146 bRelativeOpen = TRUE;
2150 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
2151 // and free the prior Buffer contents but only if the fourth
2152 // parameter is TRUE.
2155 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
2160 bAllocatedSymLinkBuffer ||
2163 if( !NT_SUCCESS( ntStatus))
2166 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2167 AFS_TRACE_LEVEL_ERROR,
2168 "AFSLocateNameEntry (FO: %p) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
2175 try_return( ntStatus);
2179 // We have substituted a name into the buffer so if we do this again for this
2180 // path, we need to free up the buffer we allocated.
2183 bSubstitutedName = TRUE;
2187 // Update the search parameters
2190 uniPathName = uniRemainingPath;
2193 // Check if the is a SymLink entry but has no Target FileID or Name. In this
2194 // case it might be a DFS Link so let's go and evaluate it to be sure
2197 if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
2198 ( pCurrentObject->TargetFileId.Vnode == 0 ||
2199 pDirEntry->NameInformation.TargetName.Length == 0))
2202 ntStatus = AFSValidateSymLink( AuthGroup,
2205 if( !NT_SUCCESS( ntStatus))
2208 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2209 AFS_TRACE_LEVEL_ERROR,
2210 "AFSLocateNameEntry (FO: %p) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2212 &pDirEntry->NameInformation.FileName,
2213 pCurrentObject->FileId.Cell,
2214 pCurrentObject->FileId.Volume,
2215 pCurrentObject->FileId.Vnode,
2216 pCurrentObject->FileId.Unique,
2219 try_return( ntStatus);
2224 // Update the name array
2227 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2228 AFS_TRACE_LEVEL_VERBOSE,
2229 "AFSLocateNameEntry (FO: %p) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2231 &pDirEntry->NameInformation.FileName,
2232 pCurrentObject->FileId.Cell,
2233 pCurrentObject->FileId.Volume,
2234 pCurrentObject->FileId.Vnode,
2235 pCurrentObject->FileId.Unique));
2237 ntStatus = AFSInsertNextElement( pNameArray,
2240 if( !NT_SUCCESS( ntStatus))
2243 try_return( ntStatus);
2249 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2250 AFS_TRACE_LEVEL_VERBOSE,
2251 "AFSLocateNameEntry (FO: %p) Completed processing %wZ Status %08lX\n",
2256 if( ( !NT_SUCCESS( ntStatus) &&
2257 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
2258 ntStatus == STATUS_REPARSE)
2260 if( RootPathName->Buffer != uniFullPathName.Buffer)
2263 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
2269 if( *OutParentDirectoryCB != NULL)
2272 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2273 AFS_TRACE_LEVEL_VERBOSE,
2274 "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
2275 &(*OutParentDirectoryCB)->NameInformation.FileName,
2276 *OutParentDirectoryCB,
2278 (*OutParentDirectoryCB)->DirOpenReferenceCount));
2281 if( *OutDirectoryCB != NULL)
2284 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2285 AFS_TRACE_LEVEL_VERBOSE,
2286 "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
2287 &(*OutDirectoryCB)->NameInformation.FileName,
2290 (*OutDirectoryCB)->DirOpenReferenceCount));
2294 if( pDirEntry != NULL)
2297 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
2299 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2300 AFS_TRACE_LEVEL_VERBOSE,
2301 "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
2302 &pDirEntry->NameInformation.FileName,
2307 ASSERT( lCount >= 0);
2310 if( pParentDirEntry != NULL)
2313 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
2315 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2316 AFS_TRACE_LEVEL_VERBOSE,
2317 "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
2318 &pParentDirEntry->NameInformation.FileName,
2323 ASSERT( lCount >= 0);
2326 if( bReleaseCurrentVolume)
2329 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
2331 lCount = AFSVolumeDecrement( pCurrentVolume,
2332 VolumeReferenceReason);
2334 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2335 AFS_TRACE_LEVEL_VERBOSE,
2336 "AFSLocateNameEntry Decrement7 count on volume %p Reason %u Cnt %d\n",
2338 VolumeReferenceReason,
2341 bReleaseCurrentVolume = FALSE;
2344 if( bSubstituteName &&
2345 uniSearchName.Buffer != NULL)
2348 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
2356 AFSCreateDirEntry( IN GUID *AuthGroup,
2357 IN AFSObjectInfoCB *ParentObjectInfo,
2358 IN AFSDirectoryCB *ParentDirCB,
2359 IN PUNICODE_STRING FileName,
2360 IN PUNICODE_STRING ComponentName,
2361 IN ULONG Attributes,
2362 IN OUT AFSDirectoryCB **DirEntry)
2365 UNREFERENCED_PARAMETER(FileName);
2366 NTSTATUS ntStatus = STATUS_SUCCESS;
2367 AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
2368 LARGE_INTEGER liFileSize = {0,0};
2374 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2375 AFS_TRACE_LEVEL_VERBOSE_2,
2376 "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
2377 &ParentDirCB->NameInformation.FileName,
2378 ParentObjectInfo->FileId.Cell,
2379 ParentObjectInfo->FileId.Volume,
2380 ParentObjectInfo->FileId.Vnode,
2381 ParentObjectInfo->FileId.Unique,
2386 // OK, before inserting the node into the parent tree, issue
2387 // the request to the service for node creation
2388 // We will need to drop the lock on the parent node since the create
2389 // could cause a callback into the file system to invalidate it's cache
2392 ntStatus = AFSNotifyFileCreate( AuthGroup,
2400 // If the returned status is STATUS_REPARSE then the entry exists
2401 // and we raced, get out.
2403 if( ntStatus == STATUS_REPARSE)
2406 *DirEntry = pDirNode;
2408 try_return( ntStatus = STATUS_SUCCESS);
2411 if( !NT_SUCCESS( ntStatus))
2414 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2415 AFS_TRACE_LEVEL_ERROR,
2416 "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
2417 &ParentDirCB->NameInformation.FileName,
2418 ParentObjectInfo->FileId.Cell,
2419 ParentObjectInfo->FileId.Volume,
2420 ParentObjectInfo->FileId.Vnode,
2421 ParentObjectInfo->FileId.Unique,
2426 try_return( ntStatus);
2430 // If AFSNotifyFileCreate returns pDirNode != NULL, then its
2431 // DirOpenReferenceCount is held.
2434 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2438 // Before attempting to insert the new entry, check if we need to validate the parent
2441 if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2444 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2445 AFS_TRACE_LEVEL_VERBOSE,
2446 "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2447 &ParentDirCB->NameInformation.FileName,
2448 ParentObjectInfo->FileId.Cell,
2449 ParentObjectInfo->FileId.Volume,
2450 ParentObjectInfo->FileId.Vnode,
2451 ParentObjectInfo->FileId.Unique));
2453 ntStatus = AFSVerifyEntry( AuthGroup,
2456 if( !NT_SUCCESS( ntStatus))
2459 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2460 AFS_TRACE_LEVEL_ERROR,
2461 "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2462 &ParentDirCB->NameInformation.FileName,
2463 ParentObjectInfo->FileId.Cell,
2464 ParentObjectInfo->FileId.Volume,
2465 ParentObjectInfo->FileId.Vnode,
2466 ParentObjectInfo->FileId.Unique,
2469 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2471 try_return( ntStatus);
2476 // Check for the entry in the event we raced with some other thread
2479 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2480 (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2483 if( pExistingDirNode != NULL)
2485 if (AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2486 &pExistingDirNode->ObjectInformation->FileId))
2489 if ( pExistingDirNode != pDirNode)
2492 lCount = InterlockedDecrement( &pDirNode->DirOpenReferenceCount);
2494 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2495 AFS_TRACE_LEVEL_VERBOSE,
2496 "AFSCreateDirEntry Decrement count on %wZ DE %p Cnt %d\n",
2497 &pDirNode->NameInformation.FileName,
2501 AFSDeleteDirEntry( ParentObjectInfo,
2504 lCount = InterlockedIncrement( &pExistingDirNode->DirOpenReferenceCount);
2506 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2507 AFS_TRACE_LEVEL_VERBOSE,
2508 "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2509 &pExistingDirNode->NameInformation.FileName,
2513 *DirEntry = pExistingDirNode;
2516 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2518 try_return( ntStatus = STATUS_SUCCESS);
2524 // Need to tear down this entry and rebuild it below
2527 if( pExistingDirNode->DirOpenReferenceCount <= 0 &&
2528 pExistingDirNode->NameArrayReferenceCount <= 0)
2531 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2532 AFS_TRACE_LEVEL_VERBOSE,
2533 "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2535 &pExistingDirNode->NameInformation.FileName,
2536 pExistingDirNode->ObjectInformation->FileId.Cell,
2537 pExistingDirNode->ObjectInformation->FileId.Volume,
2538 pExistingDirNode->ObjectInformation->FileId.Vnode,
2539 pExistingDirNode->ObjectInformation->FileId.Unique,
2540 pDirNode->ObjectInformation->FileId.Cell,
2541 pDirNode->ObjectInformation->FileId.Volume,
2542 pDirNode->ObjectInformation->FileId.Vnode,
2543 pDirNode->ObjectInformation->FileId.Unique));
2545 AFSDeleteDirEntry( ParentObjectInfo,
2551 SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2553 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2554 AFS_TRACE_LEVEL_VERBOSE,
2555 "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2557 &pExistingDirNode->NameInformation.FileName,
2558 pExistingDirNode->ObjectInformation->FileId.Cell,
2559 pExistingDirNode->ObjectInformation->FileId.Volume,
2560 pExistingDirNode->ObjectInformation->FileId.Vnode,
2561 pExistingDirNode->ObjectInformation->FileId.Unique,
2562 pDirNode->ObjectInformation->FileId.Cell,
2563 pDirNode->ObjectInformation->FileId.Volume,
2564 pDirNode->ObjectInformation->FileId.Vnode,
2565 pDirNode->ObjectInformation->FileId.Unique));
2567 AFSRemoveNameEntry( ParentObjectInfo,
2573 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2574 AFS_TRACE_LEVEL_VERBOSE_2,
2575 "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2576 &ParentDirCB->NameInformation.FileName,
2577 ParentObjectInfo->FileId.Cell,
2578 ParentObjectInfo->FileId.Volume,
2579 ParentObjectInfo->FileId.Vnode,
2580 ParentObjectInfo->FileId.Unique,
2584 // Insert the directory node
2587 AFSInsertDirectoryNode( ParentObjectInfo,
2592 // Pass back the dir entry
2595 *DirEntry = pDirNode;
2597 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2608 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2609 IN AFSDirectoryCB *DirEntry,
2610 IN BOOLEAN InsertInEnumList)
2618 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2621 // Insert the node into the directory node tree
2624 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2625 AFS_TRACE_LEVEL_VERBOSE,
2626 "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2628 &DirEntry->NameInformation.FileName));
2630 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2632 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2635 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2637 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2638 AFS_TRACE_LEVEL_VERBOSE,
2639 "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2641 &DirEntry->NameInformation.FileName));
2646 AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2649 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2650 AFS_TRACE_LEVEL_VERBOSE,
2651 "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2653 &DirEntry->NameInformation.FileName));
2656 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2659 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2661 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2663 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2664 AFS_TRACE_LEVEL_VERBOSE,
2665 "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2667 &DirEntry->NameInformation.FileName));
2672 AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2675 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2676 AFS_TRACE_LEVEL_VERBOSE,
2677 "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2679 &DirEntry->NameInformation.FileName));
2683 // Into the shortname tree
2686 if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2689 if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2692 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2694 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2695 AFS_TRACE_LEVEL_VERBOSE,
2696 "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2698 &DirEntry->NameInformation.FileName));
2700 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2705 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2708 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2709 AFS_TRACE_LEVEL_VERBOSE,
2710 "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2712 &DirEntry->NameInformation.FileName));
2716 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2718 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2719 AFS_TRACE_LEVEL_VERBOSE,
2720 "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2722 &DirEntry->NameInformation.FileName));
2727 if( InsertInEnumList)
2731 // And insert the node into the directory list
2734 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2735 AFS_TRACE_LEVEL_VERBOSE,
2736 "AFSInsertDirectoryNode Inserting entry %p %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2738 &DirEntry->NameInformation.FileName,
2739 DirEntry->ObjectInformation->FileId.Cell,
2740 DirEntry->ObjectInformation->FileId.Volume,
2741 DirEntry->ObjectInformation->FileId.Vnode,
2742 DirEntry->ObjectInformation->FileId.Unique));
2744 if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2747 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2752 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2754 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2757 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2759 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2761 lCount = InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2763 AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2764 AFS_TRACE_LEVEL_VERBOSE,
2765 "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2766 &DirEntry->NameInformation.FileName,
2768 ParentObjectInfo->FileId.Cell,
2769 ParentObjectInfo->FileId.Volume,
2770 ParentObjectInfo->FileId.Vnode,
2771 ParentObjectInfo->FileId.Unique));
2779 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2780 IN AFSDirectoryCB **ppDirEntry)