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.
53 AFSLocateNameEntry( IN GUID *AuthGroup,
54 IN PFILE_OBJECT FileObject,
55 IN OUT UNICODE_STRING *RootPathName,
56 IN UNICODE_STRING *ParsedPathName,
57 IN AFSNameArrayHdr *NameArray,
59 IN AFSVolumeCB *VolumeCB,
60 IN AFSDirectoryCB *ParentDirectoryCB,
61 OUT AFSVolumeCB **OutVolumeCB,
62 OUT LONG *OutVolumeReferenceReason,
63 OUT AFSDirectoryCB **OutParentDirectoryCB,
64 OUT AFSDirectoryCB **OutDirectoryCB,
65 OUT PUNICODE_STRING ComponentName)
68 NTSTATUS ntStatus = STATUS_SUCCESS;
69 UNICODE_STRING uniPathName, uniComponentName, uniRemainingPath, uniSearchName, uniFullPathName;
71 AFSDirectoryCB *pDirEntry = NULL, *pParentDirEntry = NULL;
72 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
73 UNICODE_STRING uniSysName;
74 ULONG ulSubstituteIndex = 0;
75 BOOLEAN bSubstituteName = FALSE;
76 AFSNameArrayHdr *pNameArray = NameArray;
77 BOOLEAN bAllocatedSymLinkBuffer = FALSE;
78 UNICODE_STRING uniRelativeName, uniNoOpName;
79 AFSObjectInfoCB *pCurrentObject = NULL;
80 AFSObjectInfoCB *pParentObjectInfo = NULL;
81 AFSVolumeCB *pCurrentVolume = NULL;
82 AFSVolumeCB *pTargetVolume = NULL;
83 BOOLEAN bReleaseCurrentVolume = FALSE;
84 LONG VolumeReferenceReason;
85 BOOLEAN bSubstitutedName = FALSE;
91 ASSERT( *OutVolumeCB != VolumeCB);
93 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
94 AFS_TRACE_LEVEL_VERBOSE_2,
95 "AFSLocateNameEntry (FO: %p) Processing full name %wZ\n",
99 RtlInitUnicodeString( &uniSysName,
102 RtlInitUnicodeString( &uniRelativeName,
105 RtlInitUnicodeString( &uniNoOpName,
109 // Cleanup some parameters
112 if( ComponentName != NULL)
115 ComponentName->Length = 0;
116 ComponentName->MaximumLength = 0;
117 ComponentName->Buffer = NULL;
121 // We will parse through the filename, locating the directory nodes until we encounter a cache miss
122 // Starting at the root node
125 pParentDirEntry = NULL;
127 pDirEntry = ParentDirectoryCB;
129 pCurrentVolume = VolumeCB;
131 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
133 lCount = AFSVolumeIncrement( pCurrentVolume,
134 VolumeReferenceReason);
136 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
137 AFS_TRACE_LEVEL_VERBOSE,
138 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
140 VolumeReferenceReason,
143 bReleaseCurrentVolume = TRUE;
145 uniPathName = *ParsedPathName;
147 uniFullPathName = *RootPathName;
149 uniComponentName.Length = uniComponentName.MaximumLength = 0;
150 uniComponentName.Buffer = NULL;
152 uniRemainingPath.Length = uniRemainingPath.MaximumLength = 0;
153 uniRemainingPath.Buffer = NULL;
155 uniSearchName.Length = uniSearchName.MaximumLength = 0;
156 uniSearchName.Buffer = NULL;
161 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
163 ASSERT( pDirEntry->DirOpenReferenceCount > 0);
166 // Check our total link count for this name array
169 if( pNameArray->LinkCount >= (LONG)pDevExt->Specific.RDR.MaxLinkCount)
172 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
175 pCurrentObject = pDirEntry->ObjectInformation;
177 KeQueryTickCount( &pCurrentObject->LastAccessCount);
180 // Check that the directory entry is not deleted or pending delete
183 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
186 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
187 AFS_TRACE_LEVEL_ERROR,
188 "AFSLocateNameEntry (FO: %p) Deleted parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
190 &pDirEntry->NameInformation.FileName,
191 pCurrentObject->FileId.Cell,
192 pCurrentObject->FileId.Volume,
193 pCurrentObject->FileId.Vnode,
194 pCurrentObject->FileId.Unique,
195 STATUS_FILE_DELETED);
197 try_return( ntStatus = STATUS_FILE_DELETED);
200 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
203 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
204 AFS_TRACE_LEVEL_ERROR,
205 "AFSLocateNameEntry (FO: %p) Delete pending on %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_DELETE_PENDING);
214 try_return( ntStatus = STATUS_DELETE_PENDING);
218 // Check if the directory requires verification
221 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
222 ( pCurrentObject->FileType != AFS_FILE_TYPE_DIRECTORY ||
223 !AFSIsEnumerationInProcess( pCurrentObject)))
226 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
227 AFS_TRACE_LEVEL_VERBOSE,
228 "AFSLocateNameEntry (FO: %p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
230 &pDirEntry->NameInformation.FileName,
231 pCurrentObject->FileId.Cell,
232 pCurrentObject->FileId.Volume,
233 pCurrentObject->FileId.Vnode,
234 pCurrentObject->FileId.Unique);
237 // Directory TreeLock should be exclusively held
240 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
243 ntStatus = AFSVerifyEntry( AuthGroup,
246 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
248 if( !NT_SUCCESS( ntStatus))
251 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
252 AFS_TRACE_LEVEL_ERROR,
253 "AFSLocateNameEntry (FO: %p) Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
255 &pDirEntry->NameInformation.FileName,
256 pCurrentObject->FileId.Cell,
257 pCurrentObject->FileId.Volume,
258 pCurrentObject->FileId.Vnode,
259 pCurrentObject->FileId.Unique,
262 try_return( ntStatus);
267 // Ensure the parent node has been evaluated, if not then go do it now
270 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) ||
271 pCurrentObject->FileType == AFS_FILE_TYPE_UNKNOWN)
274 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
275 AFS_TRACE_LEVEL_VERBOSE,
276 "AFSLocateNameEntry (FO: %p) Evaluating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
278 &pDirEntry->NameInformation.FileName,
279 pCurrentObject->FileId.Cell,
280 pCurrentObject->FileId.Volume,
281 pCurrentObject->FileId.Vnode,
282 pCurrentObject->FileId.Unique);
284 ntStatus = AFSEvaluateNode( AuthGroup,
287 if( !NT_SUCCESS( ntStatus))
290 if ( ntStatus == STATUS_NOT_A_DIRECTORY)
293 if ( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
296 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
297 AFS_TRACE_LEVEL_ERROR,
298 "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT NULL Status %08lX\n",
300 &pDirEntry->NameInformation.FileName,
301 pCurrentObject->FileId.Cell,
302 pCurrentObject->FileId.Volume,
303 pCurrentObject->FileId.Vnode,
304 pCurrentObject->FileId.Unique,
310 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
311 AFS_TRACE_LEVEL_ERROR,
312 "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT %08lX-%08lX-%08lX-%08lX Status %08lX\n",
314 &pDirEntry->NameInformation.FileName,
315 pCurrentObject->FileId.Cell,
316 pCurrentObject->FileId.Volume,
317 pCurrentObject->FileId.Vnode,
318 pCurrentObject->FileId.Unique,
319 pCurrentObject->ParentFileId.Cell,
320 pCurrentObject->ParentFileId.Volume,
321 pCurrentObject->ParentFileId.Vnode,
322 pCurrentObject->ParentFileId.Unique,
328 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
329 AFS_TRACE_LEVEL_ERROR,
330 "AFSLocateNameEntry (FO: %p) Failed to evaluate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
332 &pDirEntry->NameInformation.FileName,
333 pCurrentObject->FileId.Cell,
334 pCurrentObject->FileId.Volume,
335 pCurrentObject->FileId.Vnode,
336 pCurrentObject->FileId.Unique,
340 try_return( ntStatus);
343 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
347 // If this is a mount point or symlink then go get the real directory node
350 switch( pCurrentObject->FileType)
353 case AFS_FILE_TYPE_SYMLINK:
356 UNICODE_STRING uniTempName;
357 WCHAR *pTmpBuffer = NULL;
361 // Check if the flag is set to NOT evaluate a symlink
362 // and we are done with the parsing
365 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL) &&
366 uniRemainingPath.Length == 0)
370 // Pass back the directory entries
373 *OutParentDirectoryCB = pParentDirEntry;
375 *OutDirectoryCB = pDirEntry;
377 *OutVolumeCB = pCurrentVolume;
379 *OutVolumeReferenceReason = VolumeReferenceReason;
381 bReleaseCurrentVolume = FALSE;
383 *RootPathName = uniFullPathName;
385 try_return( ntStatus);
388 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
391 AFSAcquireExcl( &pDirEntry->NonPaged->Lock,
394 if( pDirEntry->NameInformation.TargetName.Length == 0)
398 // We'll reset the DV to ensure we validate the metadata content
401 pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
403 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
405 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
406 AFS_TRACE_LEVEL_VERBOSE,
407 "AFSLocateNameEntry (FO: %p) Verifying symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
409 &pDirEntry->NameInformation.FileName,
410 pCurrentObject->FileId.Cell,
411 pCurrentObject->FileId.Volume,
412 pCurrentObject->FileId.Vnode,
413 pCurrentObject->FileId.Unique);
416 // Directory TreeLock should be exclusively held
419 ntStatus = AFSVerifyEntry( AuthGroup,
422 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
424 if( !NT_SUCCESS( ntStatus))
427 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
428 AFS_TRACE_LEVEL_ERROR,
429 "AFSLocateNameEntry (FO: %p) Failed to verify symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
431 &pDirEntry->NameInformation.FileName,
432 pCurrentObject->FileId.Cell,
433 pCurrentObject->FileId.Volume,
434 pCurrentObject->FileId.Vnode,
435 pCurrentObject->FileId.Unique,
438 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
440 try_return( ntStatus);
444 // If the type changed then reprocess this entry
447 if( pCurrentObject->FileType != AFS_FILE_TYPE_SYMLINK)
450 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
458 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
462 // If we were given a zero length target name then deny access to the entry
465 if( pDirEntry->NameInformation.TargetName.Length == 0)
468 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
470 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
471 AFS_TRACE_LEVEL_ERROR,
472 "AFSLocateNameEntry (FO: %p) Failed to retrieve target name for symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
474 &pDirEntry->NameInformation.FileName,
475 pCurrentObject->FileId.Cell,
476 pCurrentObject->FileId.Volume,
477 pCurrentObject->FileId.Vnode,
478 pCurrentObject->FileId.Unique,
481 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
483 try_return( ntStatus);
486 if( AFSIsRelativeName( &pDirEntry->NameInformation.TargetName))
489 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
490 AFS_TRACE_LEVEL_VERBOSE,
491 "AFSLocateNameEntry (FO: %p) Processing relative symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
493 &pDirEntry->NameInformation.TargetName,
494 &pDirEntry->NameInformation.FileName,
495 pCurrentObject->FileId.Cell,
496 pCurrentObject->FileId.Volume,
497 pCurrentObject->FileId.Vnode,
498 pCurrentObject->FileId.Unique);
501 // We'll substitute this name into the current process name
502 // starting at where we sit in the path
505 uniTempName.Length = 0;
506 uniTempName.MaximumLength = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer) +
507 pDirEntry->NameInformation.TargetName.Length +
509 uniRemainingPath.Length;
511 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
512 uniTempName.MaximumLength,
513 AFS_NAME_BUFFER_ONE_TAG);
515 if( uniTempName.Buffer == NULL)
518 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
520 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
524 // We have so first copy in the portion up to the component
528 RtlCopyMemory( uniTempName.Buffer,
529 uniFullPathName.Buffer,
530 (ULONG)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer));
532 uniTempName.Length = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer);
534 if( bAllocatedSymLinkBuffer ||
538 pTmpBuffer = uniFullPathName.Buffer;
541 bAllocatedSymLinkBuffer = TRUE;
544 // Have we parsed this name yet? Better have at least once ...
547 if( uniComponentName.Length == 0)
553 // Copy in the target name ...
556 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
557 pDirEntry->NameInformation.TargetName.Buffer,
558 pDirEntry->NameInformation.TargetName.Length);
560 uniPathName.Buffer = &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)];
562 uniPathName.Length += pDirEntry->NameInformation.TargetName.Length;
563 uniPathName.MaximumLength = uniTempName.MaximumLength;
565 uniTempName.Length += pDirEntry->NameInformation.TargetName.Length;
568 // And now any remaining portion of the name
571 if( uniRemainingPath.Length > 0)
574 if( uniRemainingPath.Buffer[ 0] != L'\\')
577 uniRemainingPath.Buffer--;
578 uniRemainingPath.Length += sizeof( WCHAR);
580 uniPathName.Length += sizeof( WCHAR);
583 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
584 uniRemainingPath.Buffer,
585 uniRemainingPath.Length);
587 uniTempName.Length += uniRemainingPath.Length;
590 uniFullPathName = uniTempName;
592 if( pTmpBuffer != NULL)
595 AFSExFreePoolWithTag( pTmpBuffer, 0);
598 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
601 // Dereference the current entry ..
604 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
606 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
607 AFS_TRACE_LEVEL_VERBOSE,
608 "AFSLocateNameEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
609 &pDirEntry->NameInformation.FileName,
614 ASSERT( lCount >= 0);
617 // OK, need to back up one entry for the correct parent since the current
618 // entry we are on is the symlink itself
621 pDirEntry = AFSBackupEntry( pNameArray);
624 // Increment our reference on this dir entry
627 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
629 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
630 AFS_TRACE_LEVEL_VERBOSE,
631 "AFSLocateNameEntry Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
632 &pDirEntry->NameInformation.FileName,
637 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
640 pParentDirEntry = NULL;
645 pParentDirEntry = AFSGetParentEntry( pNameArray);
647 ASSERT( pParentDirEntry != pDirEntry);
653 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
654 AFS_TRACE_LEVEL_VERBOSE,
655 "AFSLocateNameEntry (FO: %p) Processing absolute symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
657 &pDirEntry->NameInformation.TargetName,
658 &pDirEntry->NameInformation.FileName,
659 pCurrentObject->FileId.Cell,
660 pCurrentObject->FileId.Volume,
661 pCurrentObject->FileId.Vnode,
662 pCurrentObject->FileId.Unique);
664 if ( !AFSIsAbsoluteAFSName( &pDirEntry->NameInformation.TargetName))
667 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
668 AFS_TRACE_LEVEL_ERROR,
669 "AFSLocateNameEntry Name %wZ contains invalid server name\n",
670 &pDirEntry->NameInformation.TargetName);
673 // The correct response would be STATUS_OBJECT_PATH_INVALID
674 // but that prevents cmd.exe from performing a recursive
675 // directory enumeration when opening a directory entry
676 // that represents a symlink to an invalid path is discovered.
679 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
681 try_return( ntStatus = STATUS_OBJECT_PATH_NOT_FOUND);
685 // We'll substitute this name into the current process name
686 // starting at where we sit in the path
689 uniTempName.Length = 0;
690 uniTempName.MaximumLength = pDirEntry->NameInformation.TargetName.Length +
692 uniRemainingPath.Length;
694 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
695 uniTempName.MaximumLength,
696 AFS_NAME_BUFFER_TWO_TAG);
698 if( uniTempName.Buffer == NULL)
701 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
703 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
706 if( bAllocatedSymLinkBuffer ||
710 pTmpBuffer = uniFullPathName.Buffer;
713 bAllocatedSymLinkBuffer = TRUE;
716 // Have we parsed this name yet? Better have at least once ...
719 if( uniComponentName.Length == 0)
725 // Copy in the target name ...
728 RtlCopyMemory( uniTempName.Buffer,
729 &pDirEntry->NameInformation.TargetName.Buffer[ AFSMountRootName.Length/sizeof( WCHAR)],
730 pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length);
732 uniTempName.Length = pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length;
735 // And now any remaining portion of the name
738 if( uniRemainingPath.Length > 0)
741 if( uniRemainingPath.Buffer[ 0] != L'\\')
744 uniRemainingPath.Buffer--;
745 uniRemainingPath.Length += sizeof( WCHAR);
748 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
749 uniRemainingPath.Buffer,
750 uniRemainingPath.Length);
752 uniTempName.Length += uniRemainingPath.Length;
755 uniFullPathName = uniTempName;
757 uniPathName = uniTempName;
759 if( pTmpBuffer != NULL)
762 AFSExFreePoolWithTag( pTmpBuffer, 0);
765 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
768 // If our current volume is not the global root then make it so ...
771 if( pCurrentVolume != AFSGlobalRoot)
774 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
775 AFS_TRACE_LEVEL_VERBOSE,
776 "AFSLocateNameEntry (FO: %p) Current volume not global, resetting for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
778 &pDirEntry->NameInformation.FileName,
779 pCurrentObject->FileId.Cell,
780 pCurrentObject->FileId.Volume,
781 pCurrentObject->FileId.Vnode,
782 pCurrentObject->FileId.Unique);
784 lCount = AFSVolumeDecrement( pCurrentVolume,
785 VolumeReferenceReason);
787 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
788 AFS_TRACE_LEVEL_VERBOSE,
789 "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
791 VolumeReferenceReason,
794 pCurrentVolume = AFSGlobalRoot;
796 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
798 lCount = AFSVolumeIncrement( pCurrentVolume,
799 VolumeReferenceReason);
801 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
802 AFS_TRACE_LEVEL_VERBOSE,
803 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
805 VolumeReferenceReason,
810 // Dereference our current dir entry
813 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
815 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
816 AFS_TRACE_LEVEL_VERBOSE,
817 "AFSLocateNameEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
818 &pDirEntry->NameInformation.FileName,
823 ASSERT( lCount >= 0);
825 pDirEntry = pCurrentVolume->DirectoryCB;
828 // Reference the new dir entry
831 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
833 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
834 AFS_TRACE_LEVEL_VERBOSE,
835 "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
836 &pDirEntry->NameInformation.FileName,
842 // Reset the name array
843 // Persist the link count in the name array
846 lLinkCount = pNameArray->LinkCount;
848 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
849 AFS_TRACE_LEVEL_VERBOSE,
850 "AFSLocateNameEntry (FO: %p) Resetting name array for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
852 &pDirEntry->NameInformation.FileName,
853 pCurrentObject->FileId.Cell,
854 pCurrentObject->FileId.Volume,
855 pCurrentObject->FileId.Vnode,
856 pCurrentObject->FileId.Unique);
858 AFSResetNameArray( pNameArray,
861 pNameArray->LinkCount = lLinkCount;
863 pParentDirEntry = NULL;
867 // Increment our link count
870 lCount = InterlockedIncrement( &pNameArray->LinkCount);
875 case AFS_FILE_TYPE_MOUNTPOINT:
879 // Check if the flag is set to NOT evaluate a mount point
880 // and we are done with the parsing
883 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL) &&
884 uniRemainingPath.Length == 0)
888 // Pass back the directory entries
891 *OutParentDirectoryCB = pParentDirEntry;
893 *OutDirectoryCB = pDirEntry;
895 *OutVolumeCB = pCurrentVolume;
897 *OutVolumeReferenceReason = VolumeReferenceReason;
899 bReleaseCurrentVolume = FALSE;
901 *RootPathName = uniFullPathName;
903 try_return( ntStatus);
906 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
907 AFS_TRACE_LEVEL_VERBOSE,
908 "AFSLocateNameEntry (FO: %p) Building MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
910 &pDirEntry->NameInformation.FileName,
911 pCurrentObject->FileId.Cell,
912 pCurrentObject->FileId.Volume,
913 pCurrentObject->FileId.Vnode,
914 pCurrentObject->FileId.Unique);
917 // Go retrieve the target entry for this node
918 // Release the current volume cb entry since we would
919 // have lock inversion in the following call
920 // Also decrement the ref count on the volume
923 ntStatus = AFSBuildMountPointTarget( AuthGroup,
927 if( !NT_SUCCESS( ntStatus))
930 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
931 AFS_TRACE_LEVEL_ERROR,
932 "AFSLocateNameEntry (FO: %p) Failed to build MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
934 &pDirEntry->NameInformation.FileName,
935 pCurrentObject->FileId.Cell,
936 pCurrentObject->FileId.Volume,
937 pCurrentObject->FileId.Vnode,
938 pCurrentObject->FileId.Unique,
941 try_return( ntStatus);
944 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
946 lCount = AFSVolumeDecrement( pCurrentVolume,
947 VolumeReferenceReason);
949 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
950 AFS_TRACE_LEVEL_VERBOSE,
951 "AFSLocateNameEntry Decrement2 count on volume %p Reason %u Cnt %d\n",
953 VolumeReferenceReason,
956 pCurrentVolume = pTargetVolume;
958 pTargetVolume = NULL;
960 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
962 VolumeReferenceReason = AFS_VOLUME_REFERENCE_MOUNTPT;
965 // We want to restart processing here on the new parent ...
966 // Deref and ref count the entries
969 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
971 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
972 AFS_TRACE_LEVEL_VERBOSE,
973 "AFSLocateNameEntry Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
974 &pDirEntry->NameInformation.FileName,
979 ASSERT( lCount >= 0);
981 pDirEntry = pCurrentVolume->DirectoryCB;
983 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
985 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
986 AFS_TRACE_LEVEL_VERBOSE,
987 "AFSLocateNameEntry Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
988 &pDirEntry->NameInformation.FileName,
994 // The name array stores both the mount point and the target.
995 // Insert the target.
998 AFSInsertNextElement( pNameArray,
1001 pParentDirEntry = NULL;
1004 // Increment our link count
1007 lCount = InterlockedIncrement( &pNameArray->LinkCount);
1012 case AFS_FILE_TYPE_DFSLINK:
1015 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL))
1019 // Pass back the directory entries
1022 *OutParentDirectoryCB = pParentDirEntry;
1024 *OutDirectoryCB = pDirEntry;
1026 *OutVolumeCB = pCurrentVolume;
1028 *OutVolumeReferenceReason = VolumeReferenceReason;
1030 bReleaseCurrentVolume = FALSE;
1032 *RootPathName = uniFullPathName;
1034 try_return( ntStatus);
1038 // This is a DFS link so we need to update the file name and return STATUS_REPARSE to the
1039 // system for it to reevaluate it
1042 if( FileObject != NULL)
1045 ntStatus = AFSProcessDFSLink( pDirEntry,
1054 // This is where we have been re-entered from an NP evaluation call via the BuildBranch()
1058 ntStatus = STATUS_INVALID_PARAMETER;
1061 if( ntStatus != STATUS_SUCCESS &&
1062 ntStatus != STATUS_REPARSE)
1065 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1066 AFS_TRACE_LEVEL_ERROR,
1067 "AFSLocateNameEntry (FO: %p) Failed to process DFSLink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1069 &pDirEntry->NameInformation.FileName,
1070 pCurrentObject->FileId.Cell,
1071 pCurrentObject->FileId.Volume,
1072 pCurrentObject->FileId.Vnode,
1073 pCurrentObject->FileId.Unique,
1077 try_return( ntStatus);
1080 case AFS_FILE_TYPE_UNKNOWN:
1081 case AFS_FILE_TYPE_INVALID:
1085 // Something was not processed ...
1088 try_return( ntStatus = STATUS_ACCESS_DENIED);
1091 } /* end of switch */
1094 // If the parent is not initialized then do it now
1097 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1098 !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1101 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1102 AFS_TRACE_LEVEL_VERBOSE,
1103 "AFSLocateNameEntry (FO: %p) Enumerating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1105 &pDirEntry->NameInformation.FileName,
1106 pCurrentObject->FileId.Cell,
1107 pCurrentObject->FileId.Volume,
1108 pCurrentObject->FileId.Vnode,
1109 pCurrentObject->FileId.Unique);
1111 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1114 if( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1117 ntStatus = AFSEnumerateDirectory( AuthGroup,
1121 if( !NT_SUCCESS( ntStatus))
1124 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1126 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1127 AFS_TRACE_LEVEL_ERROR,
1128 "AFSLocateNameEntry (FO: %p) Failed to enumerate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1130 &pDirEntry->NameInformation.FileName,
1131 pCurrentObject->FileId.Cell,
1132 pCurrentObject->FileId.Volume,
1133 pCurrentObject->FileId.Vnode,
1134 pCurrentObject->FileId.Unique,
1137 try_return( ntStatus);
1140 SetFlag( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1143 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1145 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1148 if( uniPathName.Length > 0)
1151 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1152 AFS_TRACE_LEVEL_ERROR,
1153 "AFSLocateNameEntry (FO: %p) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1155 &pDirEntry->NameInformation.FileName,
1156 pCurrentObject->FileId.Cell,
1157 pCurrentObject->FileId.Volume,
1158 pCurrentObject->FileId.Vnode,
1159 pCurrentObject->FileId.Unique);
1161 // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1162 // one of the components of the path is not a directory. However, returning
1163 // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1164 // Instead IIS insists on treating the target file as if it is a directory containing
1165 // a potential web.config file. NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1166 // AFS will follow suit.
1168 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1173 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1174 AFS_TRACE_LEVEL_VERBOSE,
1175 "AFSLocateNameEntry (FO: %p) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1177 &pDirEntry->NameInformation.FileName,
1178 pCurrentObject->FileId.Cell,
1179 pCurrentObject->FileId.Volume,
1180 pCurrentObject->FileId.Vnode,
1181 pCurrentObject->FileId.Unique);
1184 // Pass back the directory entries
1187 *OutParentDirectoryCB = pParentDirEntry;
1189 *OutDirectoryCB = pDirEntry;
1191 *OutVolumeCB = pCurrentVolume;
1193 *OutVolumeReferenceReason = VolumeReferenceReason;
1195 bReleaseCurrentVolume = FALSE;
1197 *RootPathName = uniFullPathName;
1200 try_return( ntStatus);
1204 // If we are at the end of the processing, set our returned information and get out
1207 if( uniPathName.Length == 0)
1210 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1211 AFS_TRACE_LEVEL_VERBOSE,
1212 "AFSLocateNameEntry (FO: %p) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1214 &pDirEntry->NameInformation.FileName,
1215 pCurrentObject->FileId.Cell,
1216 pCurrentObject->FileId.Volume,
1217 pCurrentObject->FileId.Vnode,
1218 pCurrentObject->FileId.Unique);
1221 // Pass back the directory entries
1224 *OutParentDirectoryCB = pParentDirEntry;
1226 *OutDirectoryCB = pDirEntry;
1228 *OutVolumeCB = pCurrentVolume;
1230 *OutVolumeReferenceReason = VolumeReferenceReason;
1232 bReleaseCurrentVolume = FALSE;
1234 *RootPathName = uniFullPathName;
1236 try_return( ntStatus);
1240 // We may have returned to the top of the while( TRUE)
1242 if( bSubstituteName &&
1243 uniSearchName.Buffer != NULL)
1246 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1248 bSubstituteName = FALSE;
1250 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1251 uniSearchName.Buffer = NULL;
1254 ulSubstituteIndex = 1;
1256 ntStatus = STATUS_SUCCESS;
1259 // Get the next component name
1262 FsRtlDissectName( uniPathName,
1267 // Check for the . and .. in the path
1270 if( RtlCompareUnicodeString( &uniComponentName,
1275 uniPathName = uniRemainingPath;
1280 if( RtlCompareUnicodeString( &uniComponentName,
1285 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1286 AFS_TRACE_LEVEL_VERBOSE,
1287 "AFSLocateNameEntry (FO: %p) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1289 &pDirEntry->NameInformation.FileName,
1290 pCurrentObject->FileId.Cell,
1291 pCurrentObject->FileId.Volume,
1292 pCurrentObject->FileId.Vnode,
1293 pCurrentObject->FileId.Unique);
1296 // Need to back up one entry in the name array
1298 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1300 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1301 AFS_TRACE_LEVEL_VERBOSE,
1302 "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1303 &pDirEntry->NameInformation.FileName,
1308 ASSERT( lCount >= 0);
1310 pDirEntry = AFSBackupEntry( NameArray);
1312 if( pDirEntry == NULL)
1315 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1316 AFS_TRACE_LEVEL_ERROR,
1317 "AFSLocateNameEntry AFSBackupEntry failed\n");
1319 try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1322 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1324 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1325 AFS_TRACE_LEVEL_VERBOSE,
1326 "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1327 &pDirEntry->NameInformation.FileName,
1332 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1335 pParentDirEntry = NULL;
1340 pParentDirEntry = AFSGetParentEntry( pNameArray);
1342 ASSERT( pParentDirEntry != pDirEntry);
1345 uniPathName = uniRemainingPath;
1351 // Update our pointers
1354 pParentDirEntry = pDirEntry;
1358 uniSearchName = uniComponentName;
1360 while( pDirEntry == NULL)
1364 // If the SearchName contains @SYS then we perform the substitution.
1365 // If there is no substitution we give up.
1368 if( !bSubstituteName &&
1369 FsRtlIsNameInExpression( &uniSysName,
1375 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1376 AFS_TRACE_LEVEL_VERBOSE_2,
1377 "AFSLocateNameEntry (FO: %p) Processing @SYS substitution for %wZ Index %08lX\n",
1382 ntStatus = AFSSubstituteSysName( &uniComponentName,
1386 if ( NT_SUCCESS( ntStatus))
1389 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1390 AFS_TRACE_LEVEL_VERBOSE_2,
1391 "AFSLocateNameEntry (FO: %p) Located substitution %wZ for %wZ Index %08lX\n",
1398 // Go reparse the name again
1401 bSubstituteName = TRUE;
1403 ulSubstituteIndex++; // For the next entry, if needed
1405 continue; // while( pDirEntry == NULL)
1410 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1411 AFS_TRACE_LEVEL_ERROR,
1412 "AFSLocateNameEntry (FO: %p) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1418 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1422 // Pass back the directory entries
1425 *OutParentDirectoryCB = pParentDirEntry;
1427 *OutDirectoryCB = NULL;
1429 *OutVolumeCB = pCurrentVolume;
1431 *OutVolumeReferenceReason = VolumeReferenceReason;
1433 bReleaseCurrentVolume = FALSE;
1435 if( ComponentName != NULL)
1438 *ComponentName = uniComponentName;
1441 *RootPathName = uniFullPathName;
1445 // We can't possibly have a pDirEntry since the lookup failed
1447 try_return( ntStatus);
1452 // Generate the CRC on the node and perform a case sensitive lookup
1455 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1456 AFS_TRACE_LEVEL_VERBOSE_2,
1457 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case sensitive\n",
1461 ulCRC = AFSGenerateCRC( &uniSearchName,
1464 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1467 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1471 if( pDirEntry == NULL)
1475 // Missed so perform a case insensitive lookup
1478 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1479 AFS_TRACE_LEVEL_VERBOSE_2,
1480 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case insensitive\n",
1484 ulCRC = AFSGenerateCRC( &uniSearchName,
1487 AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1491 if( pDirEntry == NULL)
1495 // OK, if this component is a valid short name then try
1496 // a lookup in the short name tree
1499 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1500 RtlIsNameLegalDOS8Dot3( &uniSearchName,
1505 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1506 AFS_TRACE_LEVEL_VERBOSE_2,
1507 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ short name\n",
1511 AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1516 if ( pDirEntry == NULL &&
1517 pParentDirEntry->ObjectInformation->VolumeCB == AFSGlobalRoot)
1521 // Check with the service to see if this is a valid cell name
1522 // that can be automatically resolved. Drop the shared TreeLock
1523 // since AFSCheckCellName must acquire it exclusively.
1526 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1528 ntStatus = AFSCheckCellName( AuthGroup,
1532 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1536 if( pDirEntry == NULL)
1540 // If we substituted a name then reset our search name and try again
1543 if( bSubstituteName)
1546 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1548 uniSearchName = uniComponentName;
1550 bSubstituteName = FALSE;
1552 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1554 continue; // while( pDirEntry == NULL)
1557 if( uniRemainingPath.Length > 0)
1560 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1562 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1563 AFS_TRACE_LEVEL_VERBOSE,
1564 "AFSLocateNameEntry (FO: %p) Returning path not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1567 pCurrentObject->FileId.Cell,
1568 pCurrentObject->FileId.Volume,
1569 pCurrentObject->FileId.Vnode,
1570 pCurrentObject->FileId.Unique);
1575 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1577 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1578 AFS_TRACE_LEVEL_VERBOSE,
1579 "AFSLocateNameEntry (FO: %p) Returning name not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1582 pCurrentObject->FileId.Cell,
1583 pCurrentObject->FileId.Volume,
1584 pCurrentObject->FileId.Vnode,
1585 pCurrentObject->FileId.Unique);
1588 // Pass back the directory entries
1591 *OutParentDirectoryCB = pParentDirEntry;
1593 *OutDirectoryCB = NULL;
1595 *OutVolumeCB = pCurrentVolume;
1597 *OutVolumeReferenceReason = VolumeReferenceReason;
1599 bReleaseCurrentVolume = FALSE;
1601 if( ComponentName != NULL)
1604 *ComponentName = uniComponentName;
1607 *RootPathName = uniFullPathName;
1610 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1613 // Node name not found so get out
1616 try_return( ntStatus); // while( pDirEntry == NULL)
1623 // Here we have a match on the case insensitive lookup for the name. If there
1624 // Is more than one link entry for this node then fail the lookup request
1627 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1628 pDirEntry->CaseInsensitiveList.fLink != NULL)
1632 // Increment our dir entry ref count since we will decrement it on exit
1635 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1637 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1638 AFS_TRACE_LEVEL_VERBOSE,
1639 "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1640 &pDirEntry->NameInformation.FileName,
1645 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1647 try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1652 if( pDirEntry != NULL)
1656 // If the verify flag is set on the parent and the current entry is deleted
1657 // revalidate the parent and search again.
1660 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1661 BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1664 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1666 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1667 AFS_TRACE_LEVEL_VERBOSE,
1668 "AFSLocateNameEntry (FO: %p) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1670 &pParentDirEntry->NameInformation.FileName,
1671 pParentDirEntry->ObjectInformation->FileId.Cell,
1672 pParentDirEntry->ObjectInformation->FileId.Volume,
1673 pParentDirEntry->ObjectInformation->FileId.Vnode,
1674 pParentDirEntry->ObjectInformation->FileId.Unique);
1677 // Directory TreeLock should be exclusively held
1680 AFSAcquireExcl( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1683 ntStatus = AFSVerifyEntry( AuthGroup,
1686 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1688 if( !NT_SUCCESS( ntStatus))
1691 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1692 AFS_TRACE_LEVEL_ERROR,
1693 "AFSLocateNameEntry (FO: %p) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1695 &pParentDirEntry->NameInformation.FileName,
1696 pParentDirEntry->ObjectInformation->FileId.Cell,
1697 pParentDirEntry->ObjectInformation->FileId.Volume,
1698 pParentDirEntry->ObjectInformation->FileId.Vnode,
1699 pParentDirEntry->ObjectInformation->FileId.Unique,
1702 try_return( ntStatus);
1705 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1706 AFS_TRACE_LEVEL_VERBOSE,
1707 "AFSLocateNameEntry (FO: %p) Reprocessing component %wZ in parent %wZ\n",
1710 &pParentDirEntry->NameInformation.FileName);
1719 // Increment our dir entry ref count
1722 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1724 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1725 AFS_TRACE_LEVEL_VERBOSE,
1726 "AFSLocateNameEntry Increment6 count on %wZ DE %p Ccb %p Cnt %d\n",
1727 &pDirEntry->NameInformation.FileName,
1733 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1735 } // End while( pDirEntry == NULL)
1738 // If we have a dirEntry for this component, perform some basic validation on it
1741 if( pDirEntry != NULL &&
1742 BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1745 pCurrentObject = pDirEntry->ObjectInformation;
1747 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1748 AFS_TRACE_LEVEL_ERROR,
1749 "AFSLocateNameEntry (FO: %p) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1751 &pDirEntry->NameInformation.FileName,
1752 pCurrentObject->FileId.Cell,
1753 pCurrentObject->FileId.Volume,
1754 pCurrentObject->FileId.Vnode,
1755 pCurrentObject->FileId.Unique);
1758 // This entry was deleted through the invalidation call back so perform cleanup
1762 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1765 pParentObjectInfo = AFSFindObjectInfo( pCurrentObject->VolumeCB,
1766 &pCurrentObject->ParentFileId);
1769 ASSERT( pParentObjectInfo != NULL);
1771 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1774 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1777 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1779 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1780 AFS_TRACE_LEVEL_VERBOSE,
1781 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1782 &pDirEntry->NameInformation.FileName,
1787 ASSERT( lCount >= 0);
1792 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1793 AFS_TRACE_LEVEL_VERBOSE,
1794 "AFSLocateNameEntry Deleting dir entry %p (%p) for %wZ\n",
1797 &pDirEntry->NameInformation.FileName);
1800 // Remove and delete the directory entry from the parent list
1803 AFSDeleteDirEntry( pParentObjectInfo,
1806 AFSAcquireShared( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1809 if( pCurrentObject->ObjectReferenceCount <= 0)
1812 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
1815 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1816 AFS_TRACE_LEVEL_VERBOSE,
1817 "AFSLocateNameEntry Removing object %p from volume tree\n",
1820 AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
1821 &pCurrentObject->TreeEntry);
1823 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
1827 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1832 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1833 AFS_TRACE_LEVEL_VERBOSE,
1834 "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
1836 &pDirEntry->NameInformation.FileName);
1838 SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
1840 AFSRemoveNameEntry( pParentObjectInfo,
1844 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1846 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
1848 AFSReleaseObjectInfo( &pParentObjectInfo);
1851 // We deleted the dir entry so check if there is any remaining portion
1852 // of the name to process.
1855 if( uniRemainingPath.Length > 0)
1858 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1860 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1861 AFS_TRACE_LEVEL_VERBOSE,
1862 "AFSLocateNameEntry (FO: %p) Returning path not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1865 pCurrentObject->FileId.Cell,
1866 pCurrentObject->FileId.Volume,
1867 pCurrentObject->FileId.Vnode,
1868 pCurrentObject->FileId.Unique);
1873 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1875 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1876 AFS_TRACE_LEVEL_VERBOSE,
1877 "AFSLocateNameEntry (FO: %p) Returning name not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1880 pCurrentObject->FileId.Cell,
1881 pCurrentObject->FileId.Volume,
1882 pCurrentObject->FileId.Vnode,
1883 pCurrentObject->FileId.Unique);
1886 // Pass back the directory entries
1889 *OutParentDirectoryCB = pParentDirEntry;
1891 *OutDirectoryCB = NULL;
1893 *OutVolumeCB = pCurrentVolume;
1895 *OutVolumeReferenceReason = VolumeReferenceReason;
1897 bReleaseCurrentVolume = FALSE;
1899 if( ComponentName != NULL)
1902 *ComponentName = uniComponentName;
1905 *RootPathName = uniFullPathName;
1909 if( ntStatus != STATUS_SUCCESS)
1912 try_return( ntStatus);
1916 // Decrement the previous parent
1919 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1921 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1922 AFS_TRACE_LEVEL_VERBOSE,
1923 "AFSLocateNameEntry Decrement5 count on Parent %wZ DE %p Ccb %p Cnt %d\n",
1924 &pParentDirEntry->NameInformation.FileName,
1929 ASSERT( lCount >= 0);
1932 // If we ended up substituting a name in the component then update
1933 // the full path and update the pointers
1936 if( bSubstituteName)
1939 BOOLEAN bRelativeOpen = FALSE;
1941 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1942 AFS_TRACE_LEVEL_VERBOSE_2,
1943 "AFSLocateNameEntry (FO: %p) Substituting %wZ into %wZ Index %08lX\n",
1949 if( FileObject != NULL &&
1950 FileObject->RelatedFileObject != NULL)
1953 bRelativeOpen = TRUE;
1957 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
1958 // and free the prior Buffer contents but only if the fourth
1959 // parameter is TRUE.
1962 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
1967 bAllocatedSymLinkBuffer ||
1970 if( !NT_SUCCESS( ntStatus))
1973 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1974 AFS_TRACE_LEVEL_ERROR,
1975 "AFSLocateNameEntry (FO: %p) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
1982 try_return( ntStatus);
1986 // We have substituted a name into the buffer so if we do this again for this
1987 // path, we need to free up the buffer we allocated.
1990 bSubstitutedName = TRUE;
1994 // Update the search parameters
1997 uniPathName = uniRemainingPath;
2000 // Check if the is a SymLink entry but has no Target FileID or Name. In this
2001 // case it might be a DFS Link so let's go and evaluate it to be sure
2004 if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
2005 ( pCurrentObject->TargetFileId.Vnode == 0 ||
2006 pDirEntry->NameInformation.TargetName.Length == 0))
2009 ntStatus = AFSValidateSymLink( AuthGroup,
2012 if( !NT_SUCCESS( ntStatus))
2015 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2016 AFS_TRACE_LEVEL_ERROR,
2017 "AFSLocateNameEntry (FO: %p) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2019 &pDirEntry->NameInformation.FileName,
2020 pCurrentObject->FileId.Cell,
2021 pCurrentObject->FileId.Volume,
2022 pCurrentObject->FileId.Vnode,
2023 pCurrentObject->FileId.Unique,
2026 try_return( ntStatus);
2031 // Update the name array
2034 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2035 AFS_TRACE_LEVEL_VERBOSE,
2036 "AFSLocateNameEntry (FO: %p) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2038 &pDirEntry->NameInformation.FileName,
2039 pCurrentObject->FileId.Cell,
2040 pCurrentObject->FileId.Volume,
2041 pCurrentObject->FileId.Vnode,
2042 pCurrentObject->FileId.Unique);
2044 ntStatus = AFSInsertNextElement( pNameArray,
2047 if( !NT_SUCCESS( ntStatus))
2050 try_return( ntStatus);
2056 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2057 AFS_TRACE_LEVEL_VERBOSE,
2058 "AFSLocateNameEntry (FO: %p) Completed processing %wZ Status %08lX\n",
2063 if( ( !NT_SUCCESS( ntStatus) &&
2064 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
2065 ntStatus == STATUS_REPARSE)
2068 if( pDirEntry != NULL)
2071 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
2073 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2074 AFS_TRACE_LEVEL_VERBOSE,
2075 "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
2076 &pDirEntry->NameInformation.FileName,
2081 ASSERT( lCount >= 0);
2083 else if( pParentDirEntry != NULL)
2086 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
2088 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2089 AFS_TRACE_LEVEL_VERBOSE,
2090 "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
2091 &pParentDirEntry->NameInformation.FileName,
2096 ASSERT( lCount >= 0);
2099 if( RootPathName->Buffer != uniFullPathName.Buffer)
2102 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
2108 if( *OutParentDirectoryCB != NULL)
2111 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2112 AFS_TRACE_LEVEL_VERBOSE,
2113 "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
2114 &(*OutParentDirectoryCB)->NameInformation.FileName,
2115 *OutParentDirectoryCB,
2117 (*OutParentDirectoryCB)->DirOpenReferenceCount);
2120 if( *OutDirectoryCB != NULL)
2123 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2124 AFS_TRACE_LEVEL_VERBOSE,
2125 "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
2126 &(*OutDirectoryCB)->NameInformation.FileName,
2129 (*OutDirectoryCB)->DirOpenReferenceCount);
2133 if( bReleaseCurrentVolume)
2136 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
2138 lCount = AFSVolumeDecrement( pCurrentVolume,
2139 VolumeReferenceReason);
2141 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2142 AFS_TRACE_LEVEL_VERBOSE,
2143 "AFSLocateNameEntry Decrement7 count on volume %p Reason %u Cnt %d\n",
2145 VolumeReferenceReason,
2148 bReleaseCurrentVolume = FALSE;
2151 if( bSubstituteName &&
2152 uniSearchName.Buffer != NULL)
2155 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
2163 AFSCreateDirEntry( IN GUID *AuthGroup,
2164 IN AFSObjectInfoCB *ParentObjectInfo,
2165 IN AFSDirectoryCB *ParentDirCB,
2166 IN PUNICODE_STRING FileName,
2167 IN PUNICODE_STRING ComponentName,
2168 IN ULONG Attributes,
2169 IN OUT AFSDirectoryCB **DirEntry)
2172 UNREFERENCED_PARAMETER(FileName);
2173 NTSTATUS ntStatus = STATUS_SUCCESS;
2174 AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
2175 LARGE_INTEGER liFileSize = {0,0};
2181 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2182 AFS_TRACE_LEVEL_VERBOSE_2,
2183 "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
2184 &ParentDirCB->NameInformation.FileName,
2185 ParentObjectInfo->FileId.Cell,
2186 ParentObjectInfo->FileId.Volume,
2187 ParentObjectInfo->FileId.Vnode,
2188 ParentObjectInfo->FileId.Unique,
2193 // OK, before inserting the node into the parent tree, issue
2194 // the request to the service for node creation
2195 // We will need to drop the lock on the parent node since the create
2196 // could cause a callback into the file system to invalidate it's cache
2199 ntStatus = AFSNotifyFileCreate( AuthGroup,
2207 // If the returned status is STATUS_REPARSE then the entry exists
2208 // and we raced, get out.
2210 if( ntStatus == STATUS_REPARSE)
2213 *DirEntry = pDirNode;
2215 try_return( ntStatus = STATUS_SUCCESS);
2218 if( !NT_SUCCESS( ntStatus))
2221 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2222 AFS_TRACE_LEVEL_ERROR,
2223 "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
2224 &ParentDirCB->NameInformation.FileName,
2225 ParentObjectInfo->FileId.Cell,
2226 ParentObjectInfo->FileId.Volume,
2227 ParentObjectInfo->FileId.Vnode,
2228 ParentObjectInfo->FileId.Unique,
2233 try_return( ntStatus);
2237 // If AFSNotifyFileCreate returns pDirNode != NULL, then its
2238 // DirOpenReferenceCount is held.
2241 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2245 // Before attempting to insert the new entry, check if we need to validate the parent
2248 if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2251 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2252 AFS_TRACE_LEVEL_VERBOSE,
2253 "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2254 &ParentDirCB->NameInformation.FileName,
2255 ParentObjectInfo->FileId.Cell,
2256 ParentObjectInfo->FileId.Volume,
2257 ParentObjectInfo->FileId.Vnode,
2258 ParentObjectInfo->FileId.Unique);
2260 ntStatus = AFSVerifyEntry( AuthGroup,
2263 if( !NT_SUCCESS( ntStatus))
2266 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2267 AFS_TRACE_LEVEL_ERROR,
2268 "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2269 &ParentDirCB->NameInformation.FileName,
2270 ParentObjectInfo->FileId.Cell,
2271 ParentObjectInfo->FileId.Volume,
2272 ParentObjectInfo->FileId.Vnode,
2273 ParentObjectInfo->FileId.Unique,
2276 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2278 try_return( ntStatus);
2283 // Check for the entry in the event we raced with some other thread
2286 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2287 (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2290 if( pExistingDirNode != NULL)
2292 if (AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2293 &pExistingDirNode->ObjectInformation->FileId))
2296 if ( pExistingDirNode != pDirNode)
2299 lCount = InterlockedDecrement( &pDirNode->DirOpenReferenceCount);
2301 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2302 AFS_TRACE_LEVEL_VERBOSE,
2303 "AFSCreateDirEntry Decrement count on %wZ DE %p Cnt %d\n",
2304 &pDirNode->NameInformation.FileName,
2308 AFSDeleteDirEntry( ParentObjectInfo,
2311 lCount = InterlockedIncrement( &pExistingDirNode->DirOpenReferenceCount);
2313 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2314 AFS_TRACE_LEVEL_VERBOSE,
2315 "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2316 &pExistingDirNode->NameInformation.FileName,
2320 *DirEntry = pExistingDirNode;
2323 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2325 try_return( ntStatus = STATUS_SUCCESS);
2331 // Need to tear down this entry and rebuild it below
2334 if( pExistingDirNode->DirOpenReferenceCount <= 0)
2337 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2338 AFS_TRACE_LEVEL_VERBOSE,
2339 "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2341 &pExistingDirNode->NameInformation.FileName,
2342 pExistingDirNode->ObjectInformation->FileId.Cell,
2343 pExistingDirNode->ObjectInformation->FileId.Volume,
2344 pExistingDirNode->ObjectInformation->FileId.Vnode,
2345 pExistingDirNode->ObjectInformation->FileId.Unique,
2346 pDirNode->ObjectInformation->FileId.Cell,
2347 pDirNode->ObjectInformation->FileId.Volume,
2348 pDirNode->ObjectInformation->FileId.Vnode,
2349 pDirNode->ObjectInformation->FileId.Unique);
2351 AFSDeleteDirEntry( ParentObjectInfo,
2357 SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2359 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2360 AFS_TRACE_LEVEL_VERBOSE,
2361 "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2363 &pExistingDirNode->NameInformation.FileName,
2364 pExistingDirNode->ObjectInformation->FileId.Cell,
2365 pExistingDirNode->ObjectInformation->FileId.Volume,
2366 pExistingDirNode->ObjectInformation->FileId.Vnode,
2367 pExistingDirNode->ObjectInformation->FileId.Unique,
2368 pDirNode->ObjectInformation->FileId.Cell,
2369 pDirNode->ObjectInformation->FileId.Volume,
2370 pDirNode->ObjectInformation->FileId.Vnode,
2371 pDirNode->ObjectInformation->FileId.Unique);
2373 AFSRemoveNameEntry( ParentObjectInfo,
2379 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2380 AFS_TRACE_LEVEL_VERBOSE_2,
2381 "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2382 &ParentDirCB->NameInformation.FileName,
2383 ParentObjectInfo->FileId.Cell,
2384 ParentObjectInfo->FileId.Volume,
2385 ParentObjectInfo->FileId.Vnode,
2386 ParentObjectInfo->FileId.Unique,
2390 // Insert the directory node
2393 AFSInsertDirectoryNode( ParentObjectInfo,
2398 // Pass back the dir entry
2401 *DirEntry = pDirNode;
2403 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2414 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2415 IN AFSDirectoryCB *DirEntry,
2416 IN BOOLEAN InsertInEnumList)
2424 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2427 // Insert the node into the directory node tree
2430 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2431 AFS_TRACE_LEVEL_VERBOSE,
2432 "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2434 &DirEntry->NameInformation.FileName);
2436 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2438 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2441 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2443 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2444 AFS_TRACE_LEVEL_VERBOSE,
2445 "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2447 &DirEntry->NameInformation.FileName);
2452 AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2455 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2456 AFS_TRACE_LEVEL_VERBOSE,
2457 "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2459 &DirEntry->NameInformation.FileName);
2462 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2465 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2467 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2469 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2470 AFS_TRACE_LEVEL_VERBOSE,
2471 "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2473 &DirEntry->NameInformation.FileName);
2478 AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2481 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2482 AFS_TRACE_LEVEL_VERBOSE,
2483 "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2485 &DirEntry->NameInformation.FileName);
2489 // Into the shortname tree
2492 if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2495 if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2498 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2500 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2501 AFS_TRACE_LEVEL_VERBOSE,
2502 "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2504 &DirEntry->NameInformation.FileName);
2506 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2511 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2514 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2515 AFS_TRACE_LEVEL_VERBOSE,
2516 "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2518 &DirEntry->NameInformation.FileName);
2522 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2524 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2525 AFS_TRACE_LEVEL_VERBOSE,
2526 "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2528 &DirEntry->NameInformation.FileName);
2533 if( InsertInEnumList)
2537 // And insert the node into the directory list
2540 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2541 AFS_TRACE_LEVEL_VERBOSE,
2542 "AFSInsertDirectoryNode Inserting entry %p %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2544 &DirEntry->NameInformation.FileName,
2545 DirEntry->ObjectInformation->FileId.Cell,
2546 DirEntry->ObjectInformation->FileId.Volume,
2547 DirEntry->ObjectInformation->FileId.Vnode,
2548 DirEntry->ObjectInformation->FileId.Unique);
2550 if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2553 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2558 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2560 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2563 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2565 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2567 lCount = InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2569 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2570 AFS_TRACE_LEVEL_VERBOSE,
2571 "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2572 &DirEntry->NameInformation.FileName,
2574 ParentObjectInfo->FileId.Cell,
2575 ParentObjectInfo->FileId.Volume,
2576 ParentObjectInfo->FileId.Vnode,
2577 ParentObjectInfo->FileId.Unique);
2585 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2586 IN AFSDirectoryCB *DirEntry)
2594 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2595 AFS_TRACE_LEVEL_VERBOSE,
2596 "AFSDeleteDirEntry Deleting dir entry in parent %p Entry %p %wZ FID %08lX-%08lX-%08lX-%08lX RefCount %d\n",
2599 &DirEntry->NameInformation.FileName,
2600 DirEntry->ObjectInformation->FileId.Cell,
2601 DirEntry->ObjectInformation->FileId.Volume,
2602 DirEntry->ObjectInformation->FileId.Vnode,
2603 DirEntry->ObjectInformation->FileId.Unique,
2604 DirEntry->DirOpenReferenceCount);
2606 ASSERT( DirEntry->DirOpenReferenceCount == 0);
2608 AFSRemoveDirNodeFromParent( ParentObjectInfo,
2613 // Free up the name buffer if it was reallocated
2616 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2619 AFSExFreePoolWithTag( DirEntry->NameInformation.FileName.Buffer, 0);
2622 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2625 AFSExFreePoolWithTag( DirEntry->NameInformation.TargetName.Buffer, 0);
2629 // Dereference the object for this dir entry
2632 lCount = AFSObjectInfoDecrement( DirEntry->ObjectInformation,
2633 AFS_OBJECT_REFERENCE_DIRENTRY);
2635 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2636 AFS_TRACE_LEVEL_VERBOSE,
2637 "AFSDeleteDirEntry Decrement count on object %p Cnt %d\n",
2638 DirEntry->ObjectInformation,
2641 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
2642 DirEntry->ObjectInformation->Links == 0)
2645 SetFlag( DirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2648 ExDeleteResourceLite( &DirEntry->NonPaged->Lock);
2650 AFSExFreePoolWithTag( DirEntry->NonPaged, AFS_DIR_ENTRY_NP_TAG);
2653 // Free up the dir entry
2656 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
2657 AFS_TRACE_LEVEL_VERBOSE,
2658 "AFSDeleteDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
2661 AFSExFreePoolWithTag( DirEntry, AFS_DIR_ENTRY_TAG);
2666 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2667 IN AFSDirectoryCB *DirEntry,
2668 IN BOOLEAN RemoveFromEnumList)
2671 NTSTATUS ntStatus = STATUS_SUCCESS;
2678 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2680 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2681 AFS_TRACE_LEVEL_VERBOSE,
2682 "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %p\n",
2684 &DirEntry->NameInformation.FileName,
2685 DirEntry->ObjectInformation->FileId.Cell,
2686 DirEntry->ObjectInformation->FileId.Volume,
2687 DirEntry->ObjectInformation->FileId.Vnode,
2688 DirEntry->ObjectInformation->FileId.Unique,
2691 if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2694 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2695 AFS_TRACE_LEVEL_VERBOSE,
2696 "AFSRemoveDirNodeFromParent Removing DirEntry %p name %wZ\n",
2698 &DirEntry->NameInformation.FileName);
2700 AFSRemoveNameEntry( ParentObjectInfo,
2706 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2707 AFS_TRACE_LEVEL_VERBOSE,
2708 "AFSRemoveDirNodeFromParent DE %p for %wZ NOT removing entry due to flag set\n",
2710 &DirEntry->NameInformation.FileName);
2714 if( RemoveFromEnumList &&
2715 BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST))
2719 // And remove the entry from the enumeration list
2722 if( DirEntry->ListEntry.fLink == NULL)
2725 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = (AFSDirectoryCB *)DirEntry->ListEntry.bLink;
2730 ((AFSDirectoryCB *)DirEntry->ListEntry.fLink)->ListEntry.bLink = DirEntry->ListEntry.bLink;
2733 if( DirEntry->ListEntry.bLink == NULL)
2736 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = (AFSDirectoryCB *)DirEntry->ListEntry.fLink;
2741 ((AFSDirectoryCB *)DirEntry->ListEntry.bLink)->ListEntry.fLink = DirEntry->ListEntry.fLink;
2744 ASSERT( ParentObjectInfo->Specific.Directory.DirectoryNodeCount > 0);
2746 lCount = InterlockedDecrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2748 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2750 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2751 AFS_TRACE_LEVEL_VERBOSE,
2752 "AFSRemoveDirNodeFromParent Removing entry %wZ Dec Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2753 &DirEntry->NameInformation.FileName,
2755 ParentObjectInfo->FileId.Cell,
2756 ParentObjectInfo->FileId.Volume,
2757 ParentObjectInfo->FileId.Vnode,
2758 ParentObjectInfo->FileId.Unique);
2760 DirEntry->ListEntry.fLink = NULL;
2761 DirEntry->ListEntry.bLink = NULL;
2769 AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
2770 IN OUT PUNICODE_STRING TargetFileName)
2773 NTSTATUS ntStatus = STATUS_SUCCESS;
2774 UNICODE_STRING uniFileName;
2780 // We will process backwards from the end of the name looking
2781 // for the first \ we encounter
2784 uniFileName.Length = FileName->Length;
2785 uniFileName.MaximumLength = FileName->MaximumLength;
2787 uniFileName.Buffer = FileName->Buffer;
2792 if( uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
2796 // Subtract one more character off of the filename if it is not the root
2799 if( uniFileName.Length > sizeof( WCHAR))
2802 uniFileName.Length -= sizeof( WCHAR);
2806 // Now build up the target name
2809 TargetFileName->Length = FileName->Length - uniFileName.Length;
2812 // If we are not on the root then fixup the name
2815 if( uniFileName.Length > sizeof( WCHAR))
2818 TargetFileName->Length -= sizeof( WCHAR);
2820 TargetFileName->Buffer = &uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) + 1];
2825 TargetFileName->Buffer = &uniFileName.Buffer[ uniFileName.Length/sizeof( WCHAR)];
2829 // Fixup the passed back filename length