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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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 AFSDbgLogMsg( 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);
645 // Increment our reference on this dir entry
648 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
650 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
651 AFS_TRACE_LEVEL_VERBOSE,
652 "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
653 &pDirEntry->NameInformation.FileName,
658 if ( pParentDirEntry)
661 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
663 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
664 AFS_TRACE_LEVEL_VERBOSE,
665 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
666 &pParentDirEntry->NameInformation.FileName,
671 pParentDirEntry = NULL;
674 if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
677 pParentDirEntry = AFSGetParentEntry( pNameArray);
679 ASSERT( pParentDirEntry != pDirEntry);
681 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
683 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
684 AFS_TRACE_LEVEL_VERBOSE,
685 "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
686 &pParentDirEntry->NameInformation.FileName,
695 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
696 AFS_TRACE_LEVEL_VERBOSE,
697 "AFSLocateNameEntry (FO: %p) Processing absolute symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
699 &pDirEntry->NameInformation.TargetName,
700 &pDirEntry->NameInformation.FileName,
701 pCurrentObject->FileId.Cell,
702 pCurrentObject->FileId.Volume,
703 pCurrentObject->FileId.Vnode,
704 pCurrentObject->FileId.Unique);
706 if ( !AFSIsAbsoluteAFSName( &pDirEntry->NameInformation.TargetName))
709 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
710 AFS_TRACE_LEVEL_ERROR,
711 "AFSLocateNameEntry Name %wZ contains invalid server name\n",
712 &pDirEntry->NameInformation.TargetName);
715 // The correct response would be STATUS_OBJECT_PATH_INVALID
716 // but that prevents cmd.exe from performing a recursive
717 // directory enumeration when opening a directory entry
718 // that represents a symlink to an invalid path is discovered.
721 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
723 try_return( ntStatus = STATUS_OBJECT_PATH_NOT_FOUND);
727 // We'll substitute this name into the current process name
728 // starting at where we sit in the path
731 uniTempName.Length = 0;
732 uniTempName.MaximumLength = pDirEntry->NameInformation.TargetName.Length +
734 uniRemainingPath.Length;
736 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
737 uniTempName.MaximumLength,
738 AFS_NAME_BUFFER_TWO_TAG);
740 if( uniTempName.Buffer == NULL)
743 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
745 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
748 if( bAllocatedSymLinkBuffer ||
752 pTmpBuffer = uniFullPathName.Buffer;
755 bAllocatedSymLinkBuffer = TRUE;
758 // Have we parsed this name yet? Better have at least once ...
761 if( uniComponentName.Length == 0)
767 // Copy in the target name ...
770 RtlCopyMemory( uniTempName.Buffer,
771 &pDirEntry->NameInformation.TargetName.Buffer[ AFSMountRootName.Length/sizeof( WCHAR)],
772 pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length);
774 uniTempName.Length = pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length;
777 // And now any remaining portion of the name
780 if( uniRemainingPath.Length > 0)
783 if( uniRemainingPath.Buffer[ 0] != L'\\')
786 uniRemainingPath.Buffer--;
787 uniRemainingPath.Length += sizeof( WCHAR);
790 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
791 uniRemainingPath.Buffer,
792 uniRemainingPath.Length);
794 uniTempName.Length += uniRemainingPath.Length;
797 uniFullPathName = uniTempName;
799 uniPathName = uniTempName;
801 if( pTmpBuffer != NULL)
804 AFSExFreePoolWithTag( pTmpBuffer, 0);
807 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
810 // If our current volume is not the global root then make it so ...
813 if( pCurrentVolume != AFSGlobalRoot)
816 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
817 AFS_TRACE_LEVEL_VERBOSE,
818 "AFSLocateNameEntry (FO: %p) Current volume not global, resetting for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
820 &pDirEntry->NameInformation.FileName,
821 pCurrentObject->FileId.Cell,
822 pCurrentObject->FileId.Volume,
823 pCurrentObject->FileId.Vnode,
824 pCurrentObject->FileId.Unique);
826 lCount = AFSVolumeDecrement( pCurrentVolume,
827 VolumeReferenceReason);
829 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
830 AFS_TRACE_LEVEL_VERBOSE,
831 "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
833 VolumeReferenceReason,
836 pCurrentVolume = AFSGlobalRoot;
838 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
840 lCount = AFSVolumeIncrement( pCurrentVolume,
841 VolumeReferenceReason);
843 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
844 AFS_TRACE_LEVEL_VERBOSE,
845 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
847 VolumeReferenceReason,
852 // Dereference our current dir entry
855 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
857 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
858 AFS_TRACE_LEVEL_VERBOSE,
859 "AFSLocateNameEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
860 &pDirEntry->NameInformation.FileName,
865 ASSERT( lCount >= 0);
867 pDirEntry = pCurrentVolume->DirectoryCB;
870 // Reference the new dir entry
873 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
875 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
876 AFS_TRACE_LEVEL_VERBOSE,
877 "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
878 &pDirEntry->NameInformation.FileName,
884 // Reset the name array
885 // Persist the link count in the name array
888 lLinkCount = pNameArray->LinkCount;
890 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
891 AFS_TRACE_LEVEL_VERBOSE,
892 "AFSLocateNameEntry (FO: %p) Resetting name array for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
894 &pDirEntry->NameInformation.FileName,
895 pCurrentObject->FileId.Cell,
896 pCurrentObject->FileId.Volume,
897 pCurrentObject->FileId.Vnode,
898 pCurrentObject->FileId.Unique);
900 AFSResetNameArray( pNameArray,
903 pNameArray->LinkCount = lLinkCount;
905 if ( pParentDirEntry)
908 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
910 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
911 AFS_TRACE_LEVEL_VERBOSE,
912 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
913 &pParentDirEntry->NameInformation.FileName,
918 pParentDirEntry = NULL;
923 // Increment our link count
926 lCount = InterlockedIncrement( &pNameArray->LinkCount);
931 case AFS_FILE_TYPE_MOUNTPOINT:
935 // Check if the flag is set to NOT evaluate a mount point
936 // and we are done with the parsing
939 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL) &&
940 uniRemainingPath.Length == 0)
944 // Pass back the directory entries
947 *OutParentDirectoryCB = pParentDirEntry;
949 pParentDirEntry = NULL;
951 *OutDirectoryCB = pDirEntry;
955 *OutVolumeCB = pCurrentVolume;
957 *OutVolumeReferenceReason = VolumeReferenceReason;
959 bReleaseCurrentVolume = FALSE;
961 *RootPathName = uniFullPathName;
963 try_return( ntStatus);
966 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
967 AFS_TRACE_LEVEL_VERBOSE,
968 "AFSLocateNameEntry (FO: %p) Building MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
970 &pDirEntry->NameInformation.FileName,
971 pCurrentObject->FileId.Cell,
972 pCurrentObject->FileId.Volume,
973 pCurrentObject->FileId.Vnode,
974 pCurrentObject->FileId.Unique);
977 // Go retrieve the target entry for this node
978 // Release the current volume cb entry since we would
979 // have lock inversion in the following call
980 // Also decrement the ref count on the volume
983 ntStatus = AFSBuildMountPointTarget( AuthGroup,
987 if( !NT_SUCCESS( ntStatus))
990 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
991 AFS_TRACE_LEVEL_ERROR,
992 "AFSLocateNameEntry (FO: %p) Failed to build MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
994 &pDirEntry->NameInformation.FileName,
995 pCurrentObject->FileId.Cell,
996 pCurrentObject->FileId.Volume,
997 pCurrentObject->FileId.Vnode,
998 pCurrentObject->FileId.Unique,
1001 try_return( ntStatus);
1004 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
1006 lCount = AFSVolumeDecrement( pCurrentVolume,
1007 VolumeReferenceReason);
1009 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1010 AFS_TRACE_LEVEL_VERBOSE,
1011 "AFSLocateNameEntry Decrement2 count on volume %p Reason %u Cnt %d\n",
1013 VolumeReferenceReason,
1016 pCurrentVolume = pTargetVolume;
1018 pTargetVolume = NULL;
1020 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
1022 VolumeReferenceReason = AFS_VOLUME_REFERENCE_MOUNTPT;
1025 // We want to restart processing here on the new parent ...
1026 // Deref and ref count the entries
1029 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1031 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1032 AFS_TRACE_LEVEL_VERBOSE,
1033 "AFSLocateNameEntry Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
1034 &pDirEntry->NameInformation.FileName,
1039 ASSERT( lCount >= 0);
1041 pDirEntry = pCurrentVolume->DirectoryCB;
1043 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1045 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1046 AFS_TRACE_LEVEL_VERBOSE,
1047 "AFSLocateNameEntry Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
1048 &pDirEntry->NameInformation.FileName,
1054 // The name array stores both the mount point and the target.
1055 // Insert the target.
1058 AFSInsertNextElement( pNameArray,
1061 if ( pParentDirEntry)
1064 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1066 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1067 AFS_TRACE_LEVEL_VERBOSE,
1068 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1069 &pParentDirEntry->NameInformation.FileName,
1074 pParentDirEntry = NULL;
1078 // Increment our link count
1081 lCount = InterlockedIncrement( &pNameArray->LinkCount);
1086 case AFS_FILE_TYPE_DFSLINK:
1089 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL))
1093 // Pass back the directory entries
1096 *OutParentDirectoryCB = pParentDirEntry;
1098 pParentDirEntry = NULL;
1100 *OutDirectoryCB = pDirEntry;
1104 *OutVolumeCB = pCurrentVolume;
1106 *OutVolumeReferenceReason = VolumeReferenceReason;
1108 bReleaseCurrentVolume = FALSE;
1110 *RootPathName = uniFullPathName;
1112 try_return( ntStatus);
1116 // This is a DFS link so we need to update the file name and return STATUS_REPARSE to the
1117 // system for it to reevaluate it
1120 if( FileObject != NULL)
1123 ntStatus = AFSProcessDFSLink( pDirEntry,
1132 // This is where we have been re-entered from an NP evaluation call via the BuildBranch()
1136 ntStatus = STATUS_INVALID_PARAMETER;
1139 if( ntStatus != STATUS_SUCCESS &&
1140 ntStatus != STATUS_REPARSE)
1143 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1144 AFS_TRACE_LEVEL_ERROR,
1145 "AFSLocateNameEntry (FO: %p) Failed to process DFSLink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1147 &pDirEntry->NameInformation.FileName,
1148 pCurrentObject->FileId.Cell,
1149 pCurrentObject->FileId.Volume,
1150 pCurrentObject->FileId.Vnode,
1151 pCurrentObject->FileId.Unique,
1155 try_return( ntStatus);
1158 case AFS_FILE_TYPE_UNKNOWN:
1159 case AFS_FILE_TYPE_INVALID:
1163 // Something was not processed ...
1166 try_return( ntStatus = STATUS_ACCESS_DENIED);
1169 } /* end of switch */
1172 // If the parent is not initialized then do it now
1175 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1176 !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1179 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1180 AFS_TRACE_LEVEL_VERBOSE,
1181 "AFSLocateNameEntry (FO: %p) Enumerating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1183 &pDirEntry->NameInformation.FileName,
1184 pCurrentObject->FileId.Cell,
1185 pCurrentObject->FileId.Volume,
1186 pCurrentObject->FileId.Vnode,
1187 pCurrentObject->FileId.Unique);
1189 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1192 if( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1195 ntStatus = AFSEnumerateDirectory( AuthGroup,
1199 if( !NT_SUCCESS( ntStatus))
1202 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1204 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1205 AFS_TRACE_LEVEL_ERROR,
1206 "AFSLocateNameEntry (FO: %p) Failed to enumerate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1208 &pDirEntry->NameInformation.FileName,
1209 pCurrentObject->FileId.Cell,
1210 pCurrentObject->FileId.Volume,
1211 pCurrentObject->FileId.Vnode,
1212 pCurrentObject->FileId.Unique,
1215 try_return( ntStatus);
1218 SetFlag( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1221 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1223 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1226 if( uniPathName.Length > 0)
1229 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1230 AFS_TRACE_LEVEL_ERROR,
1231 "AFSLocateNameEntry (FO: %p) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1233 &pDirEntry->NameInformation.FileName,
1234 pCurrentObject->FileId.Cell,
1235 pCurrentObject->FileId.Volume,
1236 pCurrentObject->FileId.Vnode,
1237 pCurrentObject->FileId.Unique);
1239 // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1240 // one of the components of the path is not a directory. However, returning
1241 // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1242 // Instead IIS insists on treating the target file as if it is a directory containing
1243 // a potential web.config file. NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1244 // AFS will follow suit.
1246 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1251 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1252 AFS_TRACE_LEVEL_VERBOSE,
1253 "AFSLocateNameEntry (FO: %p) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1255 &pDirEntry->NameInformation.FileName,
1256 pCurrentObject->FileId.Cell,
1257 pCurrentObject->FileId.Volume,
1258 pCurrentObject->FileId.Vnode,
1259 pCurrentObject->FileId.Unique);
1262 // Pass back the directory entries
1265 *OutParentDirectoryCB = pParentDirEntry;
1267 pParentDirEntry = NULL;
1269 *OutDirectoryCB = pDirEntry;
1273 *OutVolumeCB = pCurrentVolume;
1275 *OutVolumeReferenceReason = VolumeReferenceReason;
1277 bReleaseCurrentVolume = FALSE;
1279 *RootPathName = uniFullPathName;
1282 try_return( ntStatus);
1286 // If we are at the end of the processing, set our returned information and get out
1289 if( uniPathName.Length == 0)
1292 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1293 AFS_TRACE_LEVEL_VERBOSE,
1294 "AFSLocateNameEntry (FO: %p) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1296 &pDirEntry->NameInformation.FileName,
1297 pCurrentObject->FileId.Cell,
1298 pCurrentObject->FileId.Volume,
1299 pCurrentObject->FileId.Vnode,
1300 pCurrentObject->FileId.Unique);
1303 // Pass back the directory entries
1306 *OutParentDirectoryCB = pParentDirEntry;
1308 pParentDirEntry = NULL;
1310 *OutDirectoryCB = pDirEntry;
1314 *OutVolumeCB = pCurrentVolume;
1316 *OutVolumeReferenceReason = VolumeReferenceReason;
1318 bReleaseCurrentVolume = FALSE;
1320 *RootPathName = uniFullPathName;
1322 try_return( ntStatus);
1326 // We may have returned to the top of the while( TRUE)
1328 if( bSubstituteName &&
1329 uniSearchName.Buffer != NULL)
1332 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1334 bSubstituteName = FALSE;
1336 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1337 uniSearchName.Buffer = NULL;
1340 ulSubstituteIndex = 1;
1342 ntStatus = STATUS_SUCCESS;
1345 // Get the next component name
1348 FsRtlDissectName( uniPathName,
1353 // Check for the . and .. in the path
1356 if( RtlCompareUnicodeString( &uniComponentName,
1361 uniPathName = uniRemainingPath;
1366 if( RtlCompareUnicodeString( &uniComponentName,
1371 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1372 AFS_TRACE_LEVEL_VERBOSE,
1373 "AFSLocateNameEntry (FO: %p) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1375 &pDirEntry->NameInformation.FileName,
1376 pCurrentObject->FileId.Cell,
1377 pCurrentObject->FileId.Volume,
1378 pCurrentObject->FileId.Vnode,
1379 pCurrentObject->FileId.Unique);
1382 // Need to back up one entry in the name array
1384 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1386 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1387 AFS_TRACE_LEVEL_VERBOSE,
1388 "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1389 &pDirEntry->NameInformation.FileName,
1394 ASSERT( lCount >= 0);
1396 pDirEntry = AFSBackupEntry( NameArray);
1398 if( pDirEntry == NULL)
1401 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1402 AFS_TRACE_LEVEL_ERROR,
1403 "AFSLocateNameEntry AFSBackupEntry failed\n");
1405 try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1408 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1410 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1411 AFS_TRACE_LEVEL_VERBOSE,
1412 "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1413 &pDirEntry->NameInformation.FileName,
1418 if ( pParentDirEntry)
1421 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1423 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1424 AFS_TRACE_LEVEL_VERBOSE,
1425 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1426 &pParentDirEntry->NameInformation.FileName,
1431 pParentDirEntry = NULL;
1434 if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1437 pParentDirEntry = AFSGetParentEntry( pNameArray);
1439 ASSERT( pParentDirEntry != pDirEntry);
1441 if ( pParentDirEntry)
1444 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
1446 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1447 AFS_TRACE_LEVEL_VERBOSE,
1448 "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
1449 &pParentDirEntry->NameInformation.FileName,
1456 uniPathName = uniRemainingPath;
1462 // Update our pointers
1465 if ( pParentDirEntry)
1468 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1470 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1471 AFS_TRACE_LEVEL_VERBOSE,
1472 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1473 &pParentDirEntry->NameInformation.FileName,
1479 pParentDirEntry = pDirEntry;
1483 uniSearchName = uniComponentName;
1485 while( pDirEntry == NULL)
1489 // If the SearchName contains @SYS then we perform the substitution.
1490 // If there is no substitution we give up.
1493 if( !bSubstituteName &&
1494 FsRtlIsNameInExpression( &uniSysName,
1500 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1501 AFS_TRACE_LEVEL_VERBOSE_2,
1502 "AFSLocateNameEntry (FO: %p) Processing @SYS substitution for %wZ Index %08lX\n",
1507 ntStatus = AFSSubstituteSysName( &uniComponentName,
1511 if ( NT_SUCCESS( ntStatus))
1514 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1515 AFS_TRACE_LEVEL_VERBOSE_2,
1516 "AFSLocateNameEntry (FO: %p) Located substitution %wZ for %wZ Index %08lX\n",
1523 // Go reparse the name again
1526 bSubstituteName = TRUE;
1528 ulSubstituteIndex++; // For the next entry, if needed
1530 continue; // while( pDirEntry == NULL)
1535 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1536 AFS_TRACE_LEVEL_ERROR,
1537 "AFSLocateNameEntry (FO: %p) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1543 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1547 // Pass back the directory entries
1550 *OutParentDirectoryCB = pParentDirEntry;
1552 pParentDirEntry = NULL;
1554 *OutDirectoryCB = NULL;
1556 *OutVolumeCB = pCurrentVolume;
1558 *OutVolumeReferenceReason = VolumeReferenceReason;
1560 bReleaseCurrentVolume = FALSE;
1562 if( ComponentName != NULL)
1565 *ComponentName = uniComponentName;
1568 *RootPathName = uniFullPathName;
1572 // We can't possibly have a pDirEntry since the lookup failed
1574 try_return( ntStatus);
1579 // Generate the CRC on the node and perform a case sensitive lookup
1582 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1583 AFS_TRACE_LEVEL_VERBOSE_2,
1584 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case sensitive\n",
1588 ulCRC = AFSGenerateCRC( &uniSearchName,
1591 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1594 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1598 if( pDirEntry == NULL)
1602 // Missed so perform a case insensitive lookup
1605 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1606 AFS_TRACE_LEVEL_VERBOSE_2,
1607 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case insensitive\n",
1611 ulCRC = AFSGenerateCRC( &uniSearchName,
1614 AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1618 if( pDirEntry == NULL)
1622 // OK, if this component is a valid short name then try
1623 // a lookup in the short name tree
1626 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1627 RtlIsNameLegalDOS8Dot3( &uniSearchName,
1632 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1633 AFS_TRACE_LEVEL_VERBOSE_2,
1634 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ short name\n",
1638 AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1643 if ( pDirEntry == NULL &&
1644 pParentDirEntry->ObjectInformation->VolumeCB == AFSGlobalRoot)
1648 // Check with the service to see if this is a valid cell name
1649 // that can be automatically resolved. Drop the shared TreeLock
1650 // since AFSCheckCellName must acquire it exclusively.
1653 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1655 ntStatus = AFSCheckCellName( AuthGroup,
1659 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1663 if( pDirEntry == NULL)
1667 // If we substituted a name then reset our search name and try again
1670 if( bSubstituteName)
1673 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1675 uniSearchName = uniComponentName;
1677 bSubstituteName = FALSE;
1679 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1681 continue; // while( pDirEntry == NULL)
1685 // Node name not found so get out
1688 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1690 if( uniRemainingPath.Length > 0)
1693 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1695 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1696 AFS_TRACE_LEVEL_VERBOSE,
1697 "AFSLocateNameEntry (FO: %p) Returning path not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1700 pCurrentObject->FileId.Cell,
1701 pCurrentObject->FileId.Volume,
1702 pCurrentObject->FileId.Vnode,
1703 pCurrentObject->FileId.Unique);
1708 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1710 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1711 AFS_TRACE_LEVEL_VERBOSE,
1712 "AFSLocateNameEntry (FO: %p) Returning name not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1715 pCurrentObject->FileId.Cell,
1716 pCurrentObject->FileId.Volume,
1717 pCurrentObject->FileId.Vnode,
1718 pCurrentObject->FileId.Unique);
1721 // Pass back the directory entries
1724 *OutParentDirectoryCB = pParentDirEntry;
1726 pParentDirEntry = NULL;
1728 *OutDirectoryCB = NULL;
1730 *OutVolumeCB = pCurrentVolume;
1732 *OutVolumeReferenceReason = VolumeReferenceReason;
1734 bReleaseCurrentVolume = FALSE;
1736 if( ComponentName != NULL)
1739 *ComponentName = uniComponentName;
1742 *RootPathName = uniFullPathName;
1745 try_return( ntStatus);
1752 // Here we have a match on the case insensitive lookup for the name. If there
1753 // Is more than one link entry for this node then fail the lookup request
1756 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1757 pDirEntry->CaseInsensitiveList.fLink != NULL)
1761 // Increment our dir entry ref count since we will decrement it on exit
1764 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1766 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1767 AFS_TRACE_LEVEL_VERBOSE,
1768 "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1769 &pDirEntry->NameInformation.FileName,
1774 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1776 try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1781 if( pDirEntry != NULL)
1785 // If the verify flag is set on the parent and the current entry is deleted
1786 // revalidate the parent and search again.
1789 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1790 BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1793 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1795 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1796 AFS_TRACE_LEVEL_VERBOSE,
1797 "AFSLocateNameEntry (FO: %p) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1799 &pParentDirEntry->NameInformation.FileName,
1800 pParentDirEntry->ObjectInformation->FileId.Cell,
1801 pParentDirEntry->ObjectInformation->FileId.Volume,
1802 pParentDirEntry->ObjectInformation->FileId.Vnode,
1803 pParentDirEntry->ObjectInformation->FileId.Unique);
1806 // Directory TreeLock should be exclusively held
1809 AFSAcquireExcl( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1812 ntStatus = AFSVerifyEntry( AuthGroup,
1815 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1817 if( !NT_SUCCESS( ntStatus))
1820 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1821 AFS_TRACE_LEVEL_ERROR,
1822 "AFSLocateNameEntry (FO: %p) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1824 &pParentDirEntry->NameInformation.FileName,
1825 pParentDirEntry->ObjectInformation->FileId.Cell,
1826 pParentDirEntry->ObjectInformation->FileId.Volume,
1827 pParentDirEntry->ObjectInformation->FileId.Vnode,
1828 pParentDirEntry->ObjectInformation->FileId.Unique,
1831 try_return( ntStatus);
1834 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1835 AFS_TRACE_LEVEL_VERBOSE,
1836 "AFSLocateNameEntry (FO: %p) Reprocessing component %wZ in parent %wZ\n",
1839 &pParentDirEntry->NameInformation.FileName);
1848 // Increment our dir entry ref count
1851 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1853 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1854 AFS_TRACE_LEVEL_VERBOSE,
1855 "AFSLocateNameEntry Increment6 count on %wZ DE %p Ccb %p Cnt %d\n",
1856 &pDirEntry->NameInformation.FileName,
1862 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1864 } // End while( pDirEntry == NULL)
1867 // If we have a dirEntry for this component, perform some basic validation on it
1870 if( pDirEntry != NULL &&
1871 BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1874 pCurrentObject = pDirEntry->ObjectInformation;
1876 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1877 AFS_TRACE_LEVEL_ERROR,
1878 "AFSLocateNameEntry (FO: %p) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1880 &pDirEntry->NameInformation.FileName,
1881 pCurrentObject->FileId.Cell,
1882 pCurrentObject->FileId.Volume,
1883 pCurrentObject->FileId.Vnode,
1884 pCurrentObject->FileId.Unique);
1887 // This entry was deleted through the invalidation call back so perform cleanup
1891 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1894 pParentObjectInfo = AFSFindObjectInfo( pCurrentObject->VolumeCB,
1895 &pCurrentObject->ParentFileId);
1898 ASSERT( pParentObjectInfo != NULL);
1900 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1903 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1906 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1908 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1909 AFS_TRACE_LEVEL_VERBOSE,
1910 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1911 &pDirEntry->NameInformation.FileName,
1916 ASSERT( lCount >= 0);
1921 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1922 AFS_TRACE_LEVEL_VERBOSE,
1923 "AFSLocateNameEntry Deleting dir entry %p (%p) for %wZ\n",
1926 &pDirEntry->NameInformation.FileName);
1929 // Remove and delete the directory entry from the parent list
1932 AFSDeleteDirEntry( pParentObjectInfo,
1935 AFSAcquireShared( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1938 if( pCurrentObject->ObjectReferenceCount <= 0)
1941 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
1944 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1945 AFS_TRACE_LEVEL_VERBOSE,
1946 "AFSLocateNameEntry Removing object %p from volume tree\n",
1949 AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
1950 &pCurrentObject->TreeEntry);
1952 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
1956 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1961 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1962 AFS_TRACE_LEVEL_VERBOSE,
1963 "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
1965 &pDirEntry->NameInformation.FileName);
1967 SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
1969 AFSRemoveNameEntry( pParentObjectInfo,
1973 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1975 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
1977 AFSReleaseObjectInfo( &pParentObjectInfo);
1980 // We deleted the dir entry so check if there is any remaining portion
1981 // of the name to process.
1984 if( uniRemainingPath.Length > 0)
1987 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1989 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1990 AFS_TRACE_LEVEL_VERBOSE,
1991 "AFSLocateNameEntry (FO: %p) Returning path not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1994 pCurrentObject->FileId.Cell,
1995 pCurrentObject->FileId.Volume,
1996 pCurrentObject->FileId.Vnode,
1997 pCurrentObject->FileId.Unique);
2002 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
2004 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2005 AFS_TRACE_LEVEL_VERBOSE,
2006 "AFSLocateNameEntry (FO: %p) Returning name not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2009 pCurrentObject->FileId.Cell,
2010 pCurrentObject->FileId.Volume,
2011 pCurrentObject->FileId.Vnode,
2012 pCurrentObject->FileId.Unique);
2015 // Pass back the directory entries
2018 *OutParentDirectoryCB = pParentDirEntry;
2020 pParentDirEntry = NULL;
2022 *OutDirectoryCB = NULL;
2024 *OutVolumeCB = pCurrentVolume;
2026 *OutVolumeReferenceReason = VolumeReferenceReason;
2028 bReleaseCurrentVolume = FALSE;
2030 if( ComponentName != NULL)
2033 *ComponentName = uniComponentName;
2036 *RootPathName = uniFullPathName;
2040 if( ntStatus != STATUS_SUCCESS)
2043 try_return( ntStatus);
2047 // If we ended up substituting a name in the component then update
2048 // the full path and update the pointers
2051 if( bSubstituteName)
2054 BOOLEAN bRelativeOpen = FALSE;
2056 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2057 AFS_TRACE_LEVEL_VERBOSE_2,
2058 "AFSLocateNameEntry (FO: %p) Substituting %wZ into %wZ Index %08lX\n",
2064 if( FileObject != NULL &&
2065 FileObject->RelatedFileObject != NULL)
2068 bRelativeOpen = TRUE;
2072 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
2073 // and free the prior Buffer contents but only if the fourth
2074 // parameter is TRUE.
2077 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
2082 bAllocatedSymLinkBuffer ||
2085 if( !NT_SUCCESS( ntStatus))
2088 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2089 AFS_TRACE_LEVEL_ERROR,
2090 "AFSLocateNameEntry (FO: %p) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
2097 try_return( ntStatus);
2101 // We have substituted a name into the buffer so if we do this again for this
2102 // path, we need to free up the buffer we allocated.
2105 bSubstitutedName = TRUE;
2109 // Update the search parameters
2112 uniPathName = uniRemainingPath;
2115 // Check if the is a SymLink entry but has no Target FileID or Name. In this
2116 // case it might be a DFS Link so let's go and evaluate it to be sure
2119 if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
2120 ( pCurrentObject->TargetFileId.Vnode == 0 ||
2121 pDirEntry->NameInformation.TargetName.Length == 0))
2124 ntStatus = AFSValidateSymLink( AuthGroup,
2127 if( !NT_SUCCESS( ntStatus))
2130 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2131 AFS_TRACE_LEVEL_ERROR,
2132 "AFSLocateNameEntry (FO: %p) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2134 &pDirEntry->NameInformation.FileName,
2135 pCurrentObject->FileId.Cell,
2136 pCurrentObject->FileId.Volume,
2137 pCurrentObject->FileId.Vnode,
2138 pCurrentObject->FileId.Unique,
2141 try_return( ntStatus);
2146 // Update the name array
2149 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2150 AFS_TRACE_LEVEL_VERBOSE,
2151 "AFSLocateNameEntry (FO: %p) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2153 &pDirEntry->NameInformation.FileName,
2154 pCurrentObject->FileId.Cell,
2155 pCurrentObject->FileId.Volume,
2156 pCurrentObject->FileId.Vnode,
2157 pCurrentObject->FileId.Unique);
2159 ntStatus = AFSInsertNextElement( pNameArray,
2162 if( !NT_SUCCESS( ntStatus))
2165 try_return( ntStatus);
2171 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2172 AFS_TRACE_LEVEL_VERBOSE,
2173 "AFSLocateNameEntry (FO: %p) Completed processing %wZ Status %08lX\n",
2178 if( ( !NT_SUCCESS( ntStatus) &&
2179 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
2180 ntStatus == STATUS_REPARSE)
2182 if( RootPathName->Buffer != uniFullPathName.Buffer)
2185 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
2191 if( *OutParentDirectoryCB != NULL)
2194 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2195 AFS_TRACE_LEVEL_VERBOSE,
2196 "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
2197 &(*OutParentDirectoryCB)->NameInformation.FileName,
2198 *OutParentDirectoryCB,
2200 (*OutParentDirectoryCB)->DirOpenReferenceCount);
2203 if( *OutDirectoryCB != NULL)
2206 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2207 AFS_TRACE_LEVEL_VERBOSE,
2208 "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
2209 &(*OutDirectoryCB)->NameInformation.FileName,
2212 (*OutDirectoryCB)->DirOpenReferenceCount);
2216 if( pDirEntry != NULL)
2219 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
2221 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2222 AFS_TRACE_LEVEL_VERBOSE,
2223 "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
2224 &pDirEntry->NameInformation.FileName,
2229 ASSERT( lCount >= 0);
2232 if( pParentDirEntry != NULL)
2235 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
2237 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2238 AFS_TRACE_LEVEL_VERBOSE,
2239 "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
2240 &pParentDirEntry->NameInformation.FileName,
2245 ASSERT( lCount >= 0);
2248 if( bReleaseCurrentVolume)
2251 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
2253 lCount = AFSVolumeDecrement( pCurrentVolume,
2254 VolumeReferenceReason);
2256 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2257 AFS_TRACE_LEVEL_VERBOSE,
2258 "AFSLocateNameEntry Decrement7 count on volume %p Reason %u Cnt %d\n",
2260 VolumeReferenceReason,
2263 bReleaseCurrentVolume = FALSE;
2266 if( bSubstituteName &&
2267 uniSearchName.Buffer != NULL)
2270 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
2278 AFSCreateDirEntry( IN GUID *AuthGroup,
2279 IN AFSObjectInfoCB *ParentObjectInfo,
2280 IN AFSDirectoryCB *ParentDirCB,
2281 IN PUNICODE_STRING FileName,
2282 IN PUNICODE_STRING ComponentName,
2283 IN ULONG Attributes,
2284 IN OUT AFSDirectoryCB **DirEntry)
2287 UNREFERENCED_PARAMETER(FileName);
2288 NTSTATUS ntStatus = STATUS_SUCCESS;
2289 AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
2290 LARGE_INTEGER liFileSize = {0,0};
2296 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2297 AFS_TRACE_LEVEL_VERBOSE_2,
2298 "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
2299 &ParentDirCB->NameInformation.FileName,
2300 ParentObjectInfo->FileId.Cell,
2301 ParentObjectInfo->FileId.Volume,
2302 ParentObjectInfo->FileId.Vnode,
2303 ParentObjectInfo->FileId.Unique,
2308 // OK, before inserting the node into the parent tree, issue
2309 // the request to the service for node creation
2310 // We will need to drop the lock on the parent node since the create
2311 // could cause a callback into the file system to invalidate it's cache
2314 ntStatus = AFSNotifyFileCreate( AuthGroup,
2322 // If the returned status is STATUS_REPARSE then the entry exists
2323 // and we raced, get out.
2325 if( ntStatus == STATUS_REPARSE)
2328 *DirEntry = pDirNode;
2330 try_return( ntStatus = STATUS_SUCCESS);
2333 if( !NT_SUCCESS( ntStatus))
2336 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2337 AFS_TRACE_LEVEL_ERROR,
2338 "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
2339 &ParentDirCB->NameInformation.FileName,
2340 ParentObjectInfo->FileId.Cell,
2341 ParentObjectInfo->FileId.Volume,
2342 ParentObjectInfo->FileId.Vnode,
2343 ParentObjectInfo->FileId.Unique,
2348 try_return( ntStatus);
2352 // If AFSNotifyFileCreate returns pDirNode != NULL, then its
2353 // DirOpenReferenceCount is held.
2356 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2360 // Before attempting to insert the new entry, check if we need to validate the parent
2363 if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2366 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2367 AFS_TRACE_LEVEL_VERBOSE,
2368 "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2369 &ParentDirCB->NameInformation.FileName,
2370 ParentObjectInfo->FileId.Cell,
2371 ParentObjectInfo->FileId.Volume,
2372 ParentObjectInfo->FileId.Vnode,
2373 ParentObjectInfo->FileId.Unique);
2375 ntStatus = AFSVerifyEntry( AuthGroup,
2378 if( !NT_SUCCESS( ntStatus))
2381 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2382 AFS_TRACE_LEVEL_ERROR,
2383 "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2384 &ParentDirCB->NameInformation.FileName,
2385 ParentObjectInfo->FileId.Cell,
2386 ParentObjectInfo->FileId.Volume,
2387 ParentObjectInfo->FileId.Vnode,
2388 ParentObjectInfo->FileId.Unique,
2391 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2393 try_return( ntStatus);
2398 // Check for the entry in the event we raced with some other thread
2401 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2402 (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2405 if( pExistingDirNode != NULL)
2407 if (AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2408 &pExistingDirNode->ObjectInformation->FileId))
2411 if ( pExistingDirNode != pDirNode)
2414 lCount = InterlockedDecrement( &pDirNode->DirOpenReferenceCount);
2416 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2417 AFS_TRACE_LEVEL_VERBOSE,
2418 "AFSCreateDirEntry Decrement count on %wZ DE %p Cnt %d\n",
2419 &pDirNode->NameInformation.FileName,
2423 AFSDeleteDirEntry( ParentObjectInfo,
2426 lCount = InterlockedIncrement( &pExistingDirNode->DirOpenReferenceCount);
2428 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2429 AFS_TRACE_LEVEL_VERBOSE,
2430 "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2431 &pExistingDirNode->NameInformation.FileName,
2435 *DirEntry = pExistingDirNode;
2438 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2440 try_return( ntStatus = STATUS_SUCCESS);
2446 // Need to tear down this entry and rebuild it below
2449 if( pExistingDirNode->DirOpenReferenceCount <= 0)
2452 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2453 AFS_TRACE_LEVEL_VERBOSE,
2454 "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2456 &pExistingDirNode->NameInformation.FileName,
2457 pExistingDirNode->ObjectInformation->FileId.Cell,
2458 pExistingDirNode->ObjectInformation->FileId.Volume,
2459 pExistingDirNode->ObjectInformation->FileId.Vnode,
2460 pExistingDirNode->ObjectInformation->FileId.Unique,
2461 pDirNode->ObjectInformation->FileId.Cell,
2462 pDirNode->ObjectInformation->FileId.Volume,
2463 pDirNode->ObjectInformation->FileId.Vnode,
2464 pDirNode->ObjectInformation->FileId.Unique);
2466 AFSDeleteDirEntry( ParentObjectInfo,
2472 SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2474 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2475 AFS_TRACE_LEVEL_VERBOSE,
2476 "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2478 &pExistingDirNode->NameInformation.FileName,
2479 pExistingDirNode->ObjectInformation->FileId.Cell,
2480 pExistingDirNode->ObjectInformation->FileId.Volume,
2481 pExistingDirNode->ObjectInformation->FileId.Vnode,
2482 pExistingDirNode->ObjectInformation->FileId.Unique,
2483 pDirNode->ObjectInformation->FileId.Cell,
2484 pDirNode->ObjectInformation->FileId.Volume,
2485 pDirNode->ObjectInformation->FileId.Vnode,
2486 pDirNode->ObjectInformation->FileId.Unique);
2488 AFSRemoveNameEntry( ParentObjectInfo,
2494 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2495 AFS_TRACE_LEVEL_VERBOSE_2,
2496 "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2497 &ParentDirCB->NameInformation.FileName,
2498 ParentObjectInfo->FileId.Cell,
2499 ParentObjectInfo->FileId.Volume,
2500 ParentObjectInfo->FileId.Vnode,
2501 ParentObjectInfo->FileId.Unique,
2505 // Insert the directory node
2508 AFSInsertDirectoryNode( ParentObjectInfo,
2513 // Pass back the dir entry
2516 *DirEntry = pDirNode;
2518 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2529 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2530 IN AFSDirectoryCB *DirEntry,
2531 IN BOOLEAN InsertInEnumList)
2539 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2542 // Insert the node into the directory node tree
2545 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2546 AFS_TRACE_LEVEL_VERBOSE,
2547 "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2549 &DirEntry->NameInformation.FileName);
2551 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2553 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2556 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2558 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2559 AFS_TRACE_LEVEL_VERBOSE,
2560 "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2562 &DirEntry->NameInformation.FileName);
2567 AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2570 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2571 AFS_TRACE_LEVEL_VERBOSE,
2572 "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2574 &DirEntry->NameInformation.FileName);
2577 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2580 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2582 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2584 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2585 AFS_TRACE_LEVEL_VERBOSE,
2586 "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2588 &DirEntry->NameInformation.FileName);
2593 AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2596 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2597 AFS_TRACE_LEVEL_VERBOSE,
2598 "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2600 &DirEntry->NameInformation.FileName);
2604 // Into the shortname tree
2607 if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2610 if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2613 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2615 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2616 AFS_TRACE_LEVEL_VERBOSE,
2617 "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2619 &DirEntry->NameInformation.FileName);
2621 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2626 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2629 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2630 AFS_TRACE_LEVEL_VERBOSE,
2631 "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2633 &DirEntry->NameInformation.FileName);
2637 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2639 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2640 AFS_TRACE_LEVEL_VERBOSE,
2641 "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2643 &DirEntry->NameInformation.FileName);
2648 if( InsertInEnumList)
2652 // And insert the node into the directory list
2655 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2656 AFS_TRACE_LEVEL_VERBOSE,
2657 "AFSInsertDirectoryNode Inserting entry %p %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2659 &DirEntry->NameInformation.FileName,
2660 DirEntry->ObjectInformation->FileId.Cell,
2661 DirEntry->ObjectInformation->FileId.Volume,
2662 DirEntry->ObjectInformation->FileId.Vnode,
2663 DirEntry->ObjectInformation->FileId.Unique);
2665 if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2668 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2673 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2675 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2678 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2680 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2682 lCount = InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2684 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2685 AFS_TRACE_LEVEL_VERBOSE,
2686 "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2687 &DirEntry->NameInformation.FileName,
2689 ParentObjectInfo->FileId.Cell,
2690 ParentObjectInfo->FileId.Volume,
2691 ParentObjectInfo->FileId.Vnode,
2692 ParentObjectInfo->FileId.Unique);
2700 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2701 IN AFSDirectoryCB *DirEntry)
2709 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2710 AFS_TRACE_LEVEL_VERBOSE,
2711 "AFSDeleteDirEntry Deleting dir entry in parent %p Entry %p %wZ FID %08lX-%08lX-%08lX-%08lX RefCount %d\n",
2714 &DirEntry->NameInformation.FileName,
2715 DirEntry->ObjectInformation->FileId.Cell,
2716 DirEntry->ObjectInformation->FileId.Volume,
2717 DirEntry->ObjectInformation->FileId.Vnode,
2718 DirEntry->ObjectInformation->FileId.Unique,
2719 DirEntry->DirOpenReferenceCount);
2721 ASSERT( DirEntry->DirOpenReferenceCount == 0);
2723 AFSRemoveDirNodeFromParent( ParentObjectInfo,
2728 // Free up the name buffer if it was reallocated
2731 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2734 AFSExFreePoolWithTag( DirEntry->NameInformation.FileName.Buffer, 0);
2737 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2740 AFSExFreePoolWithTag( DirEntry->NameInformation.TargetName.Buffer, 0);
2744 // Dereference the object for this dir entry
2747 lCount = AFSObjectInfoDecrement( DirEntry->ObjectInformation,
2748 AFS_OBJECT_REFERENCE_DIRENTRY);
2750 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2751 AFS_TRACE_LEVEL_VERBOSE,
2752 "AFSDeleteDirEntry Decrement count on object %p Cnt %d\n",
2753 DirEntry->ObjectInformation,
2756 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
2757 DirEntry->ObjectInformation->Links == 0)
2760 SetFlag( DirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2763 ExDeleteResourceLite( &DirEntry->NonPaged->Lock);
2765 AFSExFreePoolWithTag( DirEntry->NonPaged, AFS_DIR_ENTRY_NP_TAG);
2768 // Free up the dir entry
2771 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
2772 AFS_TRACE_LEVEL_VERBOSE,
2773 "AFSDeleteDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
2776 AFSExFreePoolWithTag( DirEntry, AFS_DIR_ENTRY_TAG);
2781 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2782 IN AFSDirectoryCB *DirEntry,
2783 IN BOOLEAN RemoveFromEnumList)
2786 NTSTATUS ntStatus = STATUS_SUCCESS;
2793 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2795 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2796 AFS_TRACE_LEVEL_VERBOSE,
2797 "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %p\n",
2799 &DirEntry->NameInformation.FileName,
2800 DirEntry->ObjectInformation->FileId.Cell,
2801 DirEntry->ObjectInformation->FileId.Volume,
2802 DirEntry->ObjectInformation->FileId.Vnode,
2803 DirEntry->ObjectInformation->FileId.Unique,
2806 if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))