2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSNameSupport.cpp
39 #include "AFSCommon.h"
42 AFSLocateNameEntry( IN GUID *AuthGroup,
43 IN PFILE_OBJECT FileObject,
44 IN UNICODE_STRING *RootPathName,
45 IN UNICODE_STRING *ParsedPathName,
46 IN AFSNameArrayHdr *NameArray,
48 OUT AFSVolumeCB **VolumeCB,
49 IN OUT AFSDirectoryCB **ParentDirectoryCB,
50 OUT AFSDirectoryCB **DirectoryCB,
51 OUT PUNICODE_STRING ComponentName)
54 NTSTATUS ntStatus = STATUS_SUCCESS;
55 UNICODE_STRING uniPathName, uniComponentName, uniRemainingPath, uniSearchName, uniFullPathName;
57 AFSDirectoryCB *pDirEntry = NULL, *pParentDirEntry = NULL;
58 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
59 UNICODE_STRING uniSysName;
60 ULONG ulSubstituteIndex = 0;
61 BOOLEAN bSubstituteName = FALSE;
62 AFSNameArrayHdr *pNameArray = NameArray;
63 BOOLEAN bAllocatedSymLinkBuffer = FALSE;
64 UNICODE_STRING uniRelativeName, uniNoOpName;
65 AFSObjectInfoCB *pCurrentObject = NULL;
66 AFSVolumeCB *pCurrentVolume = *VolumeCB;
67 BOOLEAN bReleaseCurrentVolume = TRUE;
68 BOOLEAN bSubstitutedName = FALSE;
73 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
74 AFS_TRACE_LEVEL_VERBOSE_2,
75 "AFSLocateNameEntry (FO: %08lX) Processing full name %wZ\n",
79 RtlInitUnicodeString( &uniSysName,
82 RtlInitUnicodeString( &uniRelativeName,
85 RtlInitUnicodeString( &uniNoOpName,
89 // Cleanup some parameters
92 if( ComponentName != NULL)
95 ComponentName->Length = 0;
96 ComponentName->MaximumLength = 0;
97 ComponentName->Buffer = NULL;
101 // We will parse through the filename, locating the directory nodes until we encounter a cache miss
102 // Starting at the root node
105 pParentDirEntry = NULL;
107 pDirEntry = *ParentDirectoryCB;
109 uniPathName = *ParsedPathName;
111 uniFullPathName = *RootPathName;
113 uniComponentName.Length = uniComponentName.MaximumLength = 0;
114 uniComponentName.Buffer = NULL;
116 uniRemainingPath.Length = uniRemainingPath.MaximumLength = 0;
117 uniRemainingPath.Buffer = NULL;
119 uniSearchName.Length = uniSearchName.MaximumLength = 0;
120 uniSearchName.Buffer = NULL;
122 ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
128 // Check our total link count for this name array
131 if( pNameArray->LinkCount >= (LONG)pDevExt->Specific.RDR.MaxLinkCount)
134 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
137 pCurrentObject = pDirEntry->ObjectInformation;
139 KeQueryTickCount( &pCurrentObject->LastAccessCount);
142 // Check that the directory entry is not deleted or pending delete
145 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
148 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
149 AFS_TRACE_LEVEL_ERROR,
150 "AFSLocateNameEntry (FO: %08lX) Deleted parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
152 &pDirEntry->NameInformation.FileName,
153 pCurrentObject->FileId.Cell,
154 pCurrentObject->FileId.Volume,
155 pCurrentObject->FileId.Vnode,
156 pCurrentObject->FileId.Unique,
159 try_return( ntStatus = STATUS_FILE_DELETED);
162 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
165 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
166 AFS_TRACE_LEVEL_ERROR,
167 "AFSLocateNameEntry (FO: %08lX) Delete pending on %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
169 &pDirEntry->NameInformation.FileName,
170 pCurrentObject->FileId.Cell,
171 pCurrentObject->FileId.Volume,
172 pCurrentObject->FileId.Vnode,
173 pCurrentObject->FileId.Unique,
176 try_return( ntStatus = STATUS_DELETE_PENDING);
180 // Check if the directory requires verification
183 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
184 ( pCurrentObject->FileType != AFS_FILE_TYPE_DIRECTORY ||
185 !AFSIsEnumerationInProcess( pCurrentObject)))
188 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
189 AFS_TRACE_LEVEL_VERBOSE,
190 "AFSLocateNameEntry (FO: %08lX) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
192 &pDirEntry->NameInformation.FileName,
193 pCurrentObject->FileId.Cell,
194 pCurrentObject->FileId.Volume,
195 pCurrentObject->FileId.Vnode,
196 pCurrentObject->FileId.Unique);
198 ntStatus = AFSVerifyEntry( AuthGroup,
201 if( !NT_SUCCESS( ntStatus))
204 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
205 AFS_TRACE_LEVEL_ERROR,
206 "AFSLocateNameEntry (FO: %08lX) Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
208 &pDirEntry->NameInformation.FileName,
209 pCurrentObject->FileId.Cell,
210 pCurrentObject->FileId.Volume,
211 pCurrentObject->FileId.Vnode,
212 pCurrentObject->FileId.Unique,
215 try_return( ntStatus);
220 // Ensure the parent node has been evaluated, if not then go do it now
223 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) ||
224 pCurrentObject->FileType == AFS_FILE_TYPE_UNKNOWN)
227 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
228 AFS_TRACE_LEVEL_VERBOSE,
229 "AFSLocateNameEntry (FO: %08lX) Evaluating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
231 &pDirEntry->NameInformation.FileName,
232 pCurrentObject->FileId.Cell,
233 pCurrentObject->FileId.Volume,
234 pCurrentObject->FileId.Vnode,
235 pCurrentObject->FileId.Unique);
237 ntStatus = AFSEvaluateNode( AuthGroup,
240 if( !NT_SUCCESS( ntStatus))
243 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
244 AFS_TRACE_LEVEL_ERROR,
245 "AFSLocateNameEntry (FO: %08lX) Failed to evaluate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
247 &pDirEntry->NameInformation.FileName,
248 pCurrentObject->FileId.Cell,
249 pCurrentObject->FileId.Volume,
250 pCurrentObject->FileId.Vnode,
251 pCurrentObject->FileId.Unique,
254 try_return( ntStatus);
257 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
261 // If this is a mount point or symlink then go get the real directory node
264 switch( pCurrentObject->FileType)
267 case AFS_FILE_TYPE_SYMLINK:
270 UNICODE_STRING uniTempName;
271 WCHAR *pTmpBuffer = NULL;
275 // Check if the flag is set to NOT evaluate a symlink
276 // and we are done with the parsing
279 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL) &&
280 uniRemainingPath.Length == 0)
284 // Pass back the directory entries
287 *ParentDirectoryCB = pParentDirEntry;
289 *DirectoryCB = pDirEntry;
291 *VolumeCB = pCurrentVolume;
293 *RootPathName = uniFullPathName;
295 try_return( ntStatus);
298 AFSAcquireExcl( &pDirEntry->NonPaged->Lock,
301 if( pDirEntry->NameInformation.TargetName.Length == 0)
305 // We'll reset the DV to ensure we validate the metadata content
308 pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
310 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
312 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
313 AFS_TRACE_LEVEL_VERBOSE,
314 "AFSLocateNameEntry (FO: %08lX) Verifying symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
316 &pDirEntry->NameInformation.FileName,
317 pCurrentObject->FileId.Cell,
318 pCurrentObject->FileId.Volume,
319 pCurrentObject->FileId.Vnode,
320 pCurrentObject->FileId.Unique);
322 ntStatus = AFSVerifyEntry( AuthGroup,
325 if( !NT_SUCCESS( ntStatus))
328 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
329 AFS_TRACE_LEVEL_ERROR,
330 "AFSLocateNameEntry (FO: %08lX) Failed to verify symlink 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,
339 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
341 try_return( ntStatus);
345 // If the type changed then reprocess this entry
348 if( pCurrentObject->FileType != AFS_FILE_TYPE_SYMLINK)
351 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
358 // If we were given a zero length target name then deny access to the entry
361 if( pDirEntry->NameInformation.TargetName.Length == 0)
364 ntStatus = STATUS_ACCESS_DENIED;
366 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
367 AFS_TRACE_LEVEL_ERROR,
368 "AFSLocateNameEntry (FO: %08lX) Failed to retrieve target name for symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
370 &pDirEntry->NameInformation.FileName,
371 pCurrentObject->FileId.Cell,
372 pCurrentObject->FileId.Volume,
373 pCurrentObject->FileId.Vnode,
374 pCurrentObject->FileId.Unique,
377 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
379 try_return( ntStatus);
382 if( AFSIsRelativeName( &pDirEntry->NameInformation.TargetName))
385 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
386 AFS_TRACE_LEVEL_VERBOSE,
387 "AFSLocateNameEntry (FO: %08lX) Processing relative symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
389 &pDirEntry->NameInformation.TargetName,
390 &pDirEntry->NameInformation.FileName,
391 pCurrentObject->FileId.Cell,
392 pCurrentObject->FileId.Volume,
393 pCurrentObject->FileId.Vnode,
394 pCurrentObject->FileId.Unique);
397 // We'll substitute this name into the current process name
398 // starting at where we sit in the path
401 uniTempName.Length = 0;
402 uniTempName.MaximumLength = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer) +
403 pDirEntry->NameInformation.TargetName.Length +
405 uniRemainingPath.Length;
407 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
408 uniTempName.MaximumLength,
409 AFS_NAME_BUFFER_ONE_TAG);
411 if( uniTempName.Buffer == NULL)
414 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
416 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
420 // We have so first copy in the portion up to the component
424 RtlCopyMemory( uniTempName.Buffer,
425 uniFullPathName.Buffer,
426 (ULONG)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer));
428 uniTempName.Length = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer);
430 if( bAllocatedSymLinkBuffer ||
434 pTmpBuffer = uniFullPathName.Buffer;
437 bAllocatedSymLinkBuffer = TRUE;
440 // Have we parsed this name yet? Better have at least once ...
443 if( uniComponentName.Length == 0)
449 // Copy in the target name ...
452 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
453 pDirEntry->NameInformation.TargetName.Buffer,
454 pDirEntry->NameInformation.TargetName.Length);
456 uniPathName.Buffer = &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)];
458 uniPathName.Length += pDirEntry->NameInformation.TargetName.Length;
459 uniPathName.MaximumLength = uniTempName.MaximumLength;
461 uniTempName.Length += pDirEntry->NameInformation.TargetName.Length;
464 // And now any remaining portion of the name
467 if( uniRemainingPath.Length > 0)
470 if( uniRemainingPath.Buffer[ 0] != L'\\')
473 uniRemainingPath.Buffer--;
474 uniRemainingPath.Length += sizeof( WCHAR);
476 uniPathName.Length += sizeof( WCHAR);
479 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
480 uniRemainingPath.Buffer,
481 uniRemainingPath.Length);
483 uniTempName.Length += uniRemainingPath.Length;
486 uniFullPathName = uniTempName;
488 if( pTmpBuffer != NULL)
491 AFSExFreePool( pTmpBuffer);
494 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
497 // Dereference the current entry ..
500 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
502 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
503 AFS_TRACE_LEVEL_VERBOSE,
504 "AFSLocateNameEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
505 &pDirEntry->NameInformation.FileName,
508 pDirEntry->OpenReferenceCount);
511 // OK, need to back up one entry for the correct parent since the current
512 // entry we are on is the symlink itself
515 pDirEntry = AFSBackupEntry( pNameArray);
518 // Increment our reference on this dir entry
521 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
523 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
524 AFS_TRACE_LEVEL_VERBOSE,
525 "AFSLocateNameEntry Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
526 &pDirEntry->NameInformation.FileName,
529 pDirEntry->OpenReferenceCount);
531 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
534 pParentDirEntry = NULL;
539 pParentDirEntry = AFSGetParentEntry( pNameArray);
541 ASSERT( pParentDirEntry != pDirEntry);
547 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
548 AFS_TRACE_LEVEL_VERBOSE,
549 "AFSLocateNameEntry (FO: %08lX) Processing absolute symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
551 &pDirEntry->NameInformation.TargetName,
552 &pDirEntry->NameInformation.FileName,
553 pCurrentObject->FileId.Cell,
554 pCurrentObject->FileId.Volume,
555 pCurrentObject->FileId.Vnode,
556 pCurrentObject->FileId.Unique);
559 // We'll substitute this name into the current process name
560 // starting at where we sit in the path
563 uniTempName.Length = 0;
564 uniTempName.MaximumLength = pDirEntry->NameInformation.TargetName.Length +
566 uniRemainingPath.Length;
568 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
569 uniTempName.MaximumLength,
570 AFS_NAME_BUFFER_TWO_TAG);
572 if( uniTempName.Buffer == NULL)
575 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
577 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
580 if( bAllocatedSymLinkBuffer ||
584 pTmpBuffer = uniFullPathName.Buffer;
587 bAllocatedSymLinkBuffer = TRUE;
590 // Have we parsed this name yet? Better have at least once ...
593 if( uniComponentName.Length == 0)
599 // Copy in the target name ...
602 RtlCopyMemory( uniTempName.Buffer,
603 pDirEntry->NameInformation.TargetName.Buffer,
604 pDirEntry->NameInformation.TargetName.Length);
606 uniTempName.Length = pDirEntry->NameInformation.TargetName.Length;
609 // And now any remaining portion of the name
612 if( uniRemainingPath.Length > 0)
615 if( uniRemainingPath.Buffer[ 0] != L'\\')
618 uniRemainingPath.Buffer--;
619 uniRemainingPath.Length += sizeof( WCHAR);
622 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
623 uniRemainingPath.Buffer,
624 uniRemainingPath.Length);
626 uniTempName.Length += uniRemainingPath.Length;
629 uniFullPathName = uniTempName;
631 uniPathName = uniTempName;
633 if( pTmpBuffer != NULL)
636 AFSExFreePool( pTmpBuffer);
639 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
642 // If our current volume is not the global root then make it so ...
645 if( pCurrentVolume != AFSGlobalRoot)
648 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
649 AFS_TRACE_LEVEL_VERBOSE,
650 "AFSLocateNameEntry (FO: %08lX) Current volume not global, resetting for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
652 &pDirEntry->NameInformation.FileName,
653 pCurrentObject->FileId.Cell,
654 pCurrentObject->FileId.Volume,
655 pCurrentObject->FileId.Vnode,
656 pCurrentObject->FileId.Unique);
658 InterlockedDecrement( &pCurrentVolume->VolumeReferenceCount);
660 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
661 AFS_TRACE_LEVEL_VERBOSE,
662 "AFSLocateNameEntry Decrement count on volume %08lX Cnt %d\n",
664 pCurrentVolume->VolumeReferenceCount);
666 pCurrentVolume = AFSGlobalRoot;
668 InterlockedIncrement( &pCurrentVolume->VolumeReferenceCount);
670 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
671 AFS_TRACE_LEVEL_VERBOSE,
672 "AFSLocateNameEntry Increment count on volume %08lX Cnt %d\n",
674 pCurrentVolume->VolumeReferenceCount);
678 // Dereference our current dir entry
681 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
683 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
684 AFS_TRACE_LEVEL_VERBOSE,
685 "AFSLocateNameEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
686 &pDirEntry->NameInformation.FileName,
689 pDirEntry->OpenReferenceCount);
691 pDirEntry = pCurrentVolume->DirectoryCB;
694 // Reference the new dir entry
697 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
699 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
700 AFS_TRACE_LEVEL_VERBOSE,
701 "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
702 &pDirEntry->NameInformation.FileName,
705 pDirEntry->OpenReferenceCount);
708 // Reset the name array
709 // Persist the link count in the name array
712 lLinkCount = pNameArray->LinkCount;
714 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
715 AFS_TRACE_LEVEL_VERBOSE,
716 "AFSLocateNameEntry (FO: %08lX) Resetting name array for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
718 &pDirEntry->NameInformation.FileName,
719 pCurrentObject->FileId.Cell,
720 pCurrentObject->FileId.Volume,
721 pCurrentObject->FileId.Vnode,
722 pCurrentObject->FileId.Unique);
724 AFSResetNameArray( pNameArray,
727 pNameArray->LinkCount = lLinkCount;
730 // Process over the \\<Global root> portion of the name
733 FsRtlDissectName( uniPathName,
737 if( RtlCompareUnicodeString( &uniComponentName,
742 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
743 AFS_TRACE_LEVEL_ERROR,
744 "AFSLocateNameEntry Name %wZ contains invalid server name\n",
748 // The correct response would be STATUS_OBJECT_PATH_INVALID
749 // but that prevents cmd.exe from performing a recursive
750 // directory enumeration when opening a directory entry
751 // that represents a symlink to an invalid path is discovered.
753 try_return( ntStatus = STATUS_OBJECT_PATH_NOT_FOUND);
756 uniPathName = uniRemainingPath;
758 pParentDirEntry = NULL;
762 // Increment our link count
765 InterlockedIncrement( &pNameArray->LinkCount);
770 case AFS_FILE_TYPE_MOUNTPOINT:
774 // Check if the flag is set to NOT evaluate a mount point
775 // and we are done with the parsing
778 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL) &&
779 uniRemainingPath.Length == 0)
783 // Pass back the directory entries
786 *ParentDirectoryCB = pParentDirEntry;
788 *DirectoryCB = pDirEntry;
790 *VolumeCB = pCurrentVolume;
792 *RootPathName = uniFullPathName;
794 try_return( ntStatus);
797 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
798 AFS_TRACE_LEVEL_VERBOSE,
799 "AFSLocateNameEntry (FO: %08lX) Building MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
801 &pDirEntry->NameInformation.FileName,
802 pCurrentObject->FileId.Cell,
803 pCurrentObject->FileId.Volume,
804 pCurrentObject->FileId.Vnode,
805 pCurrentObject->FileId.Unique);
808 // Go retrieve the target entry for this node
809 // Release the current volume cb entry since we would
810 // have lock inversion in the following call
811 // Also decrement the ref count on the volume
814 ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
816 InterlockedDecrement( &pCurrentVolume->VolumeReferenceCount);
818 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
819 AFS_TRACE_LEVEL_VERBOSE,
820 "AFSLocateNameEntry Decrement2 count on volume %08lX Cnt %d\n",
822 pCurrentVolume->VolumeReferenceCount);
824 ntStatus = AFSBuildMountPointTarget( AuthGroup,
828 if( !NT_SUCCESS( ntStatus))
831 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
832 AFS_TRACE_LEVEL_ERROR,
833 "AFSLocateNameEntry (FO: %08lX) Failed to build MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
835 &pDirEntry->NameInformation.FileName,
836 pCurrentObject->FileId.Cell,
837 pCurrentObject->FileId.Volume,
838 pCurrentObject->FileId.Vnode,
839 pCurrentObject->FileId.Unique,
843 // We already decremented the current volume above
846 bReleaseCurrentVolume = FALSE;
848 try_return( ntStatus = STATUS_ACCESS_DENIED);
851 ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
854 // Replace the current name for the mp with the volume root of the target
857 AFSReplaceCurrentElement( pNameArray,
858 pCurrentVolume->DirectoryCB);
861 // We want to restart processing here on the new parent ...
862 // Deref and ref count the entries
865 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
867 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
868 AFS_TRACE_LEVEL_VERBOSE,
869 "AFSLocateNameEntry Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
870 &pDirEntry->NameInformation.FileName,
873 pDirEntry->OpenReferenceCount);
875 pDirEntry = pCurrentVolume->DirectoryCB;
877 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
879 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
880 AFS_TRACE_LEVEL_VERBOSE,
881 "AFSLocateNameEntry Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
882 &pDirEntry->NameInformation.FileName,
885 pDirEntry->OpenReferenceCount);
887 pParentDirEntry = NULL;
890 // Increment our link count
893 InterlockedIncrement( &pNameArray->LinkCount);
898 case AFS_FILE_TYPE_DFSLINK:
901 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL))
905 // Pass back the directory entries
908 *ParentDirectoryCB = pParentDirEntry;
910 *DirectoryCB = pDirEntry;
912 *VolumeCB = pCurrentVolume;
914 *RootPathName = uniFullPathName;
916 try_return( ntStatus);
920 // This is a DFS link so we need to update the file name and return STATUS_REPARSE to the
921 // system for it to reevaluate it
924 if( FileObject != NULL)
927 ntStatus = AFSProcessDFSLink( pDirEntry,
936 // This is where we have been re-entered from an NP evaluation call via the BuildBranch()
940 ntStatus = STATUS_INVALID_PARAMETER;
943 if( ntStatus != STATUS_SUCCESS &&
944 ntStatus != STATUS_REPARSE)
947 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
948 AFS_TRACE_LEVEL_ERROR,
949 "AFSLocateNameEntry (FO: %08lX) Failed to process DFSLink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
951 &pDirEntry->NameInformation.FileName,
952 pCurrentObject->FileId.Cell,
953 pCurrentObject->FileId.Volume,
954 pCurrentObject->FileId.Vnode,
955 pCurrentObject->FileId.Unique,
959 try_return( ntStatus);
962 case AFS_FILE_TYPE_UNKNOWN:
963 case AFS_FILE_TYPE_INVALID:
967 // Something was not processed ...
970 try_return( ntStatus = STATUS_ACCESS_DENIED);
973 } /* end of switch */
976 // If the parent is not initialized then do it now
979 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
980 !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
983 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
984 AFS_TRACE_LEVEL_VERBOSE,
985 "AFSLocateNameEntry (FO: %08lX) Enumerating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
987 &pDirEntry->NameInformation.FileName,
988 pCurrentObject->FileId.Cell,
989 pCurrentObject->FileId.Volume,
990 pCurrentObject->FileId.Vnode,
991 pCurrentObject->FileId.Unique);
993 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
996 if( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
999 ntStatus = AFSEnumerateDirectory( AuthGroup,
1003 if( !NT_SUCCESS( ntStatus))
1006 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1008 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1009 AFS_TRACE_LEVEL_ERROR,
1010 "AFSLocateNameEntry (FO: %08lX) Failed to enumerate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1012 &pDirEntry->NameInformation.FileName,
1013 pCurrentObject->FileId.Cell,
1014 pCurrentObject->FileId.Volume,
1015 pCurrentObject->FileId.Vnode,
1016 pCurrentObject->FileId.Unique,
1019 try_return( ntStatus);
1022 SetFlag( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1025 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1027 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1030 if( uniPathName.Length > 0)
1033 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1034 AFS_TRACE_LEVEL_ERROR,
1035 "AFSLocateNameEntry (FO: %08lX) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1037 &pDirEntry->NameInformation.FileName,
1038 pCurrentObject->FileId.Cell,
1039 pCurrentObject->FileId.Volume,
1040 pCurrentObject->FileId.Vnode,
1041 pCurrentObject->FileId.Unique);
1043 // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1044 // one of the components of the path is not a directory. However, returning
1045 // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1046 // Instead IIS insists on treating the target file as if it is a directory containing
1047 // a potential web.config file. NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1048 // AFS will follow suit.
1050 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1055 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1056 AFS_TRACE_LEVEL_VERBOSE,
1057 "AFSLocateNameEntry (FO: %08lX) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1059 &pDirEntry->NameInformation.FileName,
1060 pCurrentObject->FileId.Cell,
1061 pCurrentObject->FileId.Volume,
1062 pCurrentObject->FileId.Vnode,
1063 pCurrentObject->FileId.Unique);
1066 // Pass back the directory entries
1069 *ParentDirectoryCB = pParentDirEntry;
1071 *DirectoryCB = pDirEntry;
1073 *VolumeCB = pCurrentVolume;
1075 *RootPathName = uniFullPathName;
1078 try_return( ntStatus);
1082 // If we are at the end of the processing, set our returned information and get out
1085 if( uniPathName.Length == 0)
1088 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1089 AFS_TRACE_LEVEL_VERBOSE,
1090 "AFSLocateNameEntry (FO: %08lX) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1092 &pDirEntry->NameInformation.FileName,
1093 pCurrentObject->FileId.Cell,
1094 pCurrentObject->FileId.Volume,
1095 pCurrentObject->FileId.Vnode,
1096 pCurrentObject->FileId.Unique);
1099 // Pass back the directory entries
1102 *ParentDirectoryCB = pParentDirEntry;
1104 *DirectoryCB = pDirEntry;
1106 *VolumeCB = pCurrentVolume;
1108 *RootPathName = uniFullPathName;
1110 try_return( ntStatus);
1114 // We may have returned to the top of the while( TRUE)
1116 if( bSubstituteName &&
1117 uniSearchName.Buffer != NULL)
1120 AFSExFreePool( uniSearchName.Buffer);
1122 bSubstituteName = FALSE;
1124 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1125 uniSearchName.Buffer = NULL;
1128 ulSubstituteIndex = 1;
1130 ntStatus = STATUS_SUCCESS;
1133 // Get the next component name
1136 FsRtlDissectName( uniPathName,
1141 // Check for the . and .. in the path
1144 if( RtlCompareUnicodeString( &uniComponentName,
1149 uniPathName = uniRemainingPath;
1154 if( RtlCompareUnicodeString( &uniComponentName,
1159 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1160 AFS_TRACE_LEVEL_VERBOSE,
1161 "AFSLocateNameEntry (FO: %08lX) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1163 &pDirEntry->NameInformation.FileName,
1164 pCurrentObject->FileId.Cell,
1165 pCurrentObject->FileId.Volume,
1166 pCurrentObject->FileId.Vnode,
1167 pCurrentObject->FileId.Unique);
1170 // Need to back up one entry in the name array
1173 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
1175 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1176 AFS_TRACE_LEVEL_VERBOSE,
1177 "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1178 &pDirEntry->NameInformation.FileName,
1181 pDirEntry->OpenReferenceCount);
1183 pDirEntry = AFSBackupEntry( NameArray);
1185 if( pDirEntry == NULL)
1188 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1189 AFS_TRACE_LEVEL_ERROR,
1190 "AFSLocateNameEntry AFSBackupEntry failed\n");
1192 try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1195 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1197 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1200 pParentDirEntry = NULL;
1205 pParentDirEntry = AFSGetParentEntry( pNameArray);
1207 ASSERT( pParentDirEntry != pDirEntry);
1210 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1211 AFS_TRACE_LEVEL_VERBOSE,
1212 "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1213 &pDirEntry->NameInformation.FileName,
1216 pDirEntry->OpenReferenceCount);
1218 uniPathName = uniRemainingPath;
1224 // Update our pointers
1227 pParentDirEntry = pDirEntry;
1231 uniSearchName = uniComponentName;
1233 while( pDirEntry == NULL)
1237 // If the SearchName contains @SYS then we perform the substitution.
1238 // If there is no substitution we give up.
1241 if( !bSubstituteName &&
1242 FsRtlIsNameInExpression( &uniSysName,
1248 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1249 AFS_TRACE_LEVEL_VERBOSE_2,
1250 "AFSLocateNameEntry (FO: %08lX) Processing @SYS substitution for %wZ Index %08lX\n",
1255 ntStatus = AFSSubstituteSysName( &uniComponentName,
1259 if ( NT_SUCCESS( ntStatus))
1262 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1263 AFS_TRACE_LEVEL_VERBOSE_2,
1264 "AFSLocateNameEntry (FO: %08lX) Located substitution %wZ for %wZ Index %08lX\n",
1271 // Go reparse the name again
1274 bSubstituteName = TRUE;
1276 ulSubstituteIndex++; // For the next entry, if needed
1278 continue; // while( pDirEntry == NULL)
1283 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1284 AFS_TRACE_LEVEL_ERROR,
1285 "AFSLocateNameEntry (FO: %08lX) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1291 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1295 // Pass back the directory entries
1298 *ParentDirectoryCB = pParentDirEntry;
1300 *DirectoryCB = NULL;
1302 *VolumeCB = pCurrentVolume;
1304 if( ComponentName != NULL)
1307 *ComponentName = uniComponentName;
1310 *RootPathName = uniFullPathName;
1314 // We can't possibly have a pDirEntry since the lookup failed
1316 try_return( ntStatus);
1321 // Generate the CRC on the node and perform a case sensitive lookup
1324 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1325 AFS_TRACE_LEVEL_VERBOSE_2,
1326 "AFSLocateNameEntry (FO: %08lX) Searching for entry %wZ case sensitive\n",
1330 ulCRC = AFSGenerateCRC( &uniSearchName,
1333 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1336 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1340 if( pDirEntry == NULL)
1344 // Missed so perform a case insensitive lookup
1347 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1348 AFS_TRACE_LEVEL_VERBOSE_2,
1349 "AFSLocateNameEntry (FO: %08lX) Searching for entry %wZ case insensitive\n",
1353 ulCRC = AFSGenerateCRC( &uniSearchName,
1356 AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1360 if( pDirEntry == NULL)
1364 // OK, if this component is a valid short name then try
1365 // a lookup in the short name tree
1368 if( RtlIsNameLegalDOS8Dot3( &uniSearchName,
1373 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1374 AFS_TRACE_LEVEL_VERBOSE_2,
1375 "AFSLocateNameEntry (FO: %08lX) Searching for entry %wZ short name\n",
1379 AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1384 if( pDirEntry == NULL)
1388 // If we substituted a name then reset our search name and try again
1391 if( bSubstituteName)
1394 AFSExFreePool( uniSearchName.Buffer);
1396 uniSearchName = uniComponentName;
1398 bSubstituteName = FALSE;
1400 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1402 continue; // while( pDirEntry == NULL)
1405 if( uniRemainingPath.Length > 0)
1408 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1413 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1415 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1416 AFS_TRACE_LEVEL_VERBOSE,
1417 "AFSLocateNameEntry (FO: %08lX) Returning name not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1420 pCurrentObject->FileId.Cell,
1421 pCurrentObject->FileId.Volume,
1422 pCurrentObject->FileId.Vnode,
1423 pCurrentObject->FileId.Unique);
1426 // Pass back the directory entries
1429 *ParentDirectoryCB = pParentDirEntry;
1431 *DirectoryCB = NULL;
1433 *VolumeCB = pCurrentVolume;
1435 if( ComponentName != NULL)
1438 *ComponentName = uniComponentName;
1441 *RootPathName = uniFullPathName;
1444 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1447 // Node name not found so get out
1450 try_return( ntStatus); // while( pDirEntry == NULL)
1457 // Here we have a match on the case insensitive lookup for the name. If there
1458 // Is more than one link entry for this node then fail the lookup request
1461 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1462 pDirEntry->CaseInsensitiveList.fLink != NULL)
1465 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1467 try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1472 if( pDirEntry != NULL)
1476 // If the verify flag is set on the parent and the current entry is deleted
1477 // revalidate the parent and search again.
1480 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1481 BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1484 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1486 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1487 AFS_TRACE_LEVEL_VERBOSE,
1488 "AFSLocateNameEntry (FO: %08lX) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1490 &pParentDirEntry->NameInformation.FileName,
1491 pParentDirEntry->ObjectInformation->FileId.Cell,
1492 pParentDirEntry->ObjectInformation->FileId.Volume,
1493 pParentDirEntry->ObjectInformation->FileId.Vnode,
1494 pParentDirEntry->ObjectInformation->FileId.Unique);
1496 ntStatus = AFSVerifyEntry( AuthGroup,
1499 if( !NT_SUCCESS( ntStatus))
1502 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1503 AFS_TRACE_LEVEL_ERROR,
1504 "AFSLocateNameEntry (FO: %08lX) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1506 &pParentDirEntry->NameInformation.FileName,
1507 pParentDirEntry->ObjectInformation->FileId.Cell,
1508 pParentDirEntry->ObjectInformation->FileId.Volume,
1509 pParentDirEntry->ObjectInformation->FileId.Vnode,
1510 pParentDirEntry->ObjectInformation->FileId.Unique,
1513 try_return( ntStatus);
1516 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1517 AFS_TRACE_LEVEL_VERBOSE,
1518 "AFSLocateNameEntry (FO: %08lX) Reprocessing component %wZ in parent %wZ\n",
1521 &pParentDirEntry->NameInformation.FileName);
1530 // Increment our dir entry ref count
1533 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1535 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1536 AFS_TRACE_LEVEL_VERBOSE,
1537 "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1538 &pDirEntry->NameInformation.FileName,
1541 pDirEntry->OpenReferenceCount);
1544 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1546 } // End while( pDirEntry == NULL)
1549 // If we have a dirEntry for this component, perform some basic validation on it
1552 if( pDirEntry != NULL &&
1553 BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1556 pCurrentObject = pDirEntry->ObjectInformation;
1558 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1559 AFS_TRACE_LEVEL_ERROR,
1560 "AFSLocateNameEntry (FO: %08lX) Deleted parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1562 &pDirEntry->NameInformation.FileName,
1563 pCurrentObject->FileId.Cell,
1564 pCurrentObject->FileId.Volume,
1565 pCurrentObject->FileId.Vnode,
1566 pCurrentObject->FileId.Unique);
1569 // This entry was deleted through the invalidation call back so perform cleanup
1573 ASSERT( pCurrentObject->ParentObjectInformation != NULL);
1575 AFSAcquireExcl( pCurrentObject->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1578 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1581 if( InterlockedDecrement( &pDirEntry->OpenReferenceCount) == 0)
1584 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1585 AFS_TRACE_LEVEL_VERBOSE,
1586 "AFSLocateNameEntry Deleting dir entry %08lX (%08lX) for %wZ\n",
1589 &pDirEntry->NameInformation.FileName);
1592 // Remove and delete the directory entry from the parent list
1595 AFSDeleteDirEntry( pCurrentObject->ParentObjectInformation,
1598 if( pCurrentObject->ObjectReferenceCount == 0)
1601 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
1604 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1605 AFS_TRACE_LEVEL_VERBOSE,
1606 "AFSLocateNameEntry Removing object %08lX from volume tree\n",
1609 AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
1610 &pCurrentObject->TreeEntry);
1612 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
1619 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1620 AFS_TRACE_LEVEL_VERBOSE,
1621 "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
1623 &pDirEntry->NameInformation.FileName);
1625 SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
1627 AFSRemoveNameEntry( pCurrentObject->ParentObjectInformation,
1631 AFSReleaseResource( pCurrentObject->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1633 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
1636 // We deleted the dir entry so check if there is any remaining portion
1637 // of the name to process.
1640 if( uniRemainingPath.Length > 0)
1642 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1647 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1649 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1650 AFS_TRACE_LEVEL_VERBOSE,
1651 "AFSLocateNameEntry (FO: %08lX) Returning name not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1654 pCurrentObject->FileId.Cell,
1655 pCurrentObject->FileId.Volume,
1656 pCurrentObject->FileId.Vnode,
1657 pCurrentObject->FileId.Unique);
1660 // Pass back the directory entries
1663 *ParentDirectoryCB = pParentDirEntry;
1665 *DirectoryCB = NULL;
1667 *VolumeCB = pCurrentVolume;
1669 if( ComponentName != NULL)
1672 *ComponentName = uniComponentName;
1675 *RootPathName = uniFullPathName;
1679 if( ntStatus != STATUS_SUCCESS)
1682 try_return( ntStatus);
1686 // Decrement the previous parent
1689 InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
1691 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1692 AFS_TRACE_LEVEL_VERBOSE,
1693 "AFSLocateNameEntry Decrement5 count on Parent %wZ DE %p Ccb %p Cnt %d\n",
1694 &pParentDirEntry->NameInformation.FileName,
1697 pParentDirEntry->OpenReferenceCount);
1700 // If we ended up substituting a name in the component then update
1701 // the full path and update the pointers
1704 if( bSubstituteName)
1707 BOOLEAN bRelativeOpen = FALSE;
1709 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1710 AFS_TRACE_LEVEL_VERBOSE_2,
1711 "AFSLocateNameEntry (FO: %08lX) Substituting %wZ into %wZ Index %08lX\n",
1717 if( FileObject != NULL &&
1718 FileObject->RelatedFileObject != NULL)
1721 bRelativeOpen = TRUE;
1725 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
1726 // and free the prior Buffer contents but only if the fourth
1727 // parameter is TRUE.
1730 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
1735 bAllocatedSymLinkBuffer ||
1738 if( !NT_SUCCESS( ntStatus))
1741 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1742 AFS_TRACE_LEVEL_ERROR,
1743 "AFSLocateNameEntry (FO: %08lX) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
1750 try_return( ntStatus);
1754 // We have substituted a name into the buffer so if we do this again for this
1755 // path, we need to free up the buffer we allocated.
1758 bSubstitutedName = TRUE;
1762 // Update the search parameters
1765 uniPathName = uniRemainingPath;
1768 // Check if the is a SymLink entry but has no Target FileID or Name. In this
1769 // case it might be a DFS Link so let's go and evaluate it to be sure
1772 if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
1773 pCurrentObject->TargetFileId.Vnode == 0 &&
1774 pCurrentObject->TargetFileId.Unique == 0 &&
1775 pDirEntry->NameInformation.TargetName.Length == 0)
1778 ntStatus = AFSValidateSymLink( AuthGroup,
1781 if( !NT_SUCCESS( ntStatus))
1784 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1785 AFS_TRACE_LEVEL_ERROR,
1786 "AFSLocateNameEntry (FO: %08lX) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1788 &pDirEntry->NameInformation.FileName,
1789 pCurrentObject->FileId.Cell,
1790 pCurrentObject->FileId.Volume,
1791 pCurrentObject->FileId.Vnode,
1792 pCurrentObject->FileId.Unique,
1795 try_return( ntStatus);
1800 // Update the name array
1803 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1804 AFS_TRACE_LEVEL_VERBOSE,
1805 "AFSLocateNameEntry (FO: %08lX) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1807 &pDirEntry->NameInformation.FileName,
1808 pCurrentObject->FileId.Cell,
1809 pCurrentObject->FileId.Volume,
1810 pCurrentObject->FileId.Vnode,
1811 pCurrentObject->FileId.Unique);
1813 ntStatus = AFSInsertNextElement( pNameArray,
1816 if( !NT_SUCCESS( ntStatus))
1819 try_return( ntStatus);
1825 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1826 AFS_TRACE_LEVEL_VERBOSE,
1827 "AFSLocateNameEntry (FO: %08lX) Completed processing %wZ Status %08lX\n",
1832 if( ( !NT_SUCCESS( ntStatus) &&
1833 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
1834 ntStatus == STATUS_REPARSE)
1837 if( pDirEntry != NULL)
1840 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
1842 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1843 AFS_TRACE_LEVEL_VERBOSE,
1844 "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
1845 &pDirEntry->NameInformation.FileName,
1848 pDirEntry->OpenReferenceCount);
1850 else if( pParentDirEntry != NULL)
1853 InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
1855 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1856 AFS_TRACE_LEVEL_VERBOSE,
1857 "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
1858 &pParentDirEntry->NameInformation.FileName,
1861 pParentDirEntry->OpenReferenceCount);
1864 if( bReleaseCurrentVolume)
1867 ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
1869 InterlockedDecrement( &pCurrentVolume->VolumeReferenceCount);
1871 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1872 AFS_TRACE_LEVEL_VERBOSE,
1873 "AFSLocateNameEntry Decrement3 count on volume %08lX Cnt %d\n",
1875 pCurrentVolume->VolumeReferenceCount);
1878 if( RootPathName->Buffer != uniFullPathName.Buffer)
1881 AFSExFreePool( uniFullPathName.Buffer);
1887 if( *ParentDirectoryCB != NULL)
1890 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1891 AFS_TRACE_LEVEL_VERBOSE,
1892 "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
1893 &(*ParentDirectoryCB)->NameInformation.FileName,
1896 (*ParentDirectoryCB)->OpenReferenceCount);
1899 if( *DirectoryCB != NULL)
1902 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1903 AFS_TRACE_LEVEL_VERBOSE,
1904 "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
1905 &(*DirectoryCB)->NameInformation.FileName,
1908 (*DirectoryCB)->OpenReferenceCount);
1912 if( bSubstituteName &&
1913 uniSearchName.Buffer != NULL)
1916 AFSExFreePool( uniSearchName.Buffer);
1924 AFSCreateDirEntry( IN GUID *AuthGroup,
1925 IN AFSObjectInfoCB *ParentObjectInfo,
1926 IN AFSDirectoryCB *ParentDirCB,
1927 IN PUNICODE_STRING FileName,
1928 IN PUNICODE_STRING ComponentName,
1929 IN ULONG Attributes,
1930 IN OUT AFSDirectoryCB **DirEntry)
1933 NTSTATUS ntStatus = STATUS_SUCCESS;
1934 AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
1935 UNICODE_STRING uniShortName;
1936 LARGE_INTEGER liFileSize = {0,0};
1941 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1942 AFS_TRACE_LEVEL_VERBOSE_2,
1943 "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
1944 &ParentDirCB->NameInformation.FileName,
1945 ParentObjectInfo->FileId.Cell,
1946 ParentObjectInfo->FileId.Volume,
1947 ParentObjectInfo->FileId.Vnode,
1948 ParentObjectInfo->FileId.Unique,
1953 // OK, before inserting the node into the parent tree, issue
1954 // the request to the service for node creation
1955 // We will need to drop the lock on the parent node since the create
1956 // could cause a callback into the file system to invalidate it's cache
1959 ntStatus = AFSNotifyFileCreate( AuthGroup,
1967 // If the returned status is STATUS_REPARSE then the entry exists
1968 // and we raced, get out.
1970 if( ntStatus == STATUS_REPARSE)
1973 *DirEntry = pDirNode;
1975 try_return( ntStatus = STATUS_SUCCESS);
1978 if( !NT_SUCCESS( ntStatus))
1981 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1982 AFS_TRACE_LEVEL_ERROR,
1983 "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
1984 &ParentDirCB->NameInformation.FileName,
1985 ParentObjectInfo->FileId.Cell,
1986 ParentObjectInfo->FileId.Volume,
1987 ParentObjectInfo->FileId.Vnode,
1988 ParentObjectInfo->FileId.Unique,
1993 try_return( ntStatus);
1996 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2000 // Before attempting to insert the new entry, check if we need to validate the parent
2003 if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2006 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2007 AFS_TRACE_LEVEL_VERBOSE,
2008 "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2009 &ParentDirCB->NameInformation.FileName,
2010 ParentObjectInfo->FileId.Cell,
2011 ParentObjectInfo->FileId.Volume,
2012 ParentObjectInfo->FileId.Vnode,
2013 ParentObjectInfo->FileId.Unique);
2015 ntStatus = AFSVerifyEntry( AuthGroup,
2018 if( !NT_SUCCESS( ntStatus))
2021 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2022 AFS_TRACE_LEVEL_ERROR,
2023 "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2024 &ParentDirCB->NameInformation.FileName,
2025 ParentObjectInfo->FileId.Cell,
2026 ParentObjectInfo->FileId.Volume,
2027 ParentObjectInfo->FileId.Vnode,
2028 ParentObjectInfo->FileId.Unique,
2031 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2033 try_return( ntStatus);
2038 // Check for the entry in the event we raced with some other thread
2041 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2042 (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2045 if( pExistingDirNode != NULL)
2048 AFSDeleteDirEntry( ParentObjectInfo,
2051 InterlockedIncrement( &pExistingDirNode->OpenReferenceCount);
2053 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2054 AFS_TRACE_LEVEL_VERBOSE,
2055 "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2056 &pExistingDirNode->NameInformation.FileName,
2058 pExistingDirNode->OpenReferenceCount);
2060 *DirEntry = pExistingDirNode;
2062 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2064 try_return( ntStatus = STATUS_SUCCESS);
2067 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2068 AFS_TRACE_LEVEL_VERBOSE_2,
2069 "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2070 &ParentDirCB->NameInformation.FileName,
2071 ParentObjectInfo->FileId.Cell,
2072 ParentObjectInfo->FileId.Volume,
2073 ParentObjectInfo->FileId.Vnode,
2074 ParentObjectInfo->FileId.Unique,
2078 // Insert the directory node
2081 AFSInsertDirectoryNode( ParentObjectInfo,
2085 InterlockedIncrement( &pDirNode->OpenReferenceCount);
2087 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2088 AFS_TRACE_LEVEL_VERBOSE,
2089 "AFSCreateDirEntry Increment2 count on %wZ DE %p Cnt %d\n",
2090 &pDirNode->NameInformation.FileName,
2092 pDirNode->OpenReferenceCount);
2095 // Pass back the dir entry
2098 *DirEntry = pDirNode;
2100 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2111 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2112 IN AFSDirectoryCB *DirEntry,
2113 IN BOOLEAN InsertInEnumList)
2119 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2122 // Insert the node into the directory node tree
2125 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2126 AFS_TRACE_LEVEL_VERBOSE,
2127 "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2129 &DirEntry->NameInformation.FileName);
2131 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2133 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2136 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2138 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2139 AFS_TRACE_LEVEL_VERBOSE,
2140 "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2142 &DirEntry->NameInformation.FileName);
2147 AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2150 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2151 AFS_TRACE_LEVEL_VERBOSE,
2152 "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2154 &DirEntry->NameInformation.FileName);
2157 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2160 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2162 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2164 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2165 AFS_TRACE_LEVEL_VERBOSE,
2166 "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2168 &DirEntry->NameInformation.FileName);
2173 AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2176 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2177 AFS_TRACE_LEVEL_VERBOSE,
2178 "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2180 &DirEntry->NameInformation.FileName);
2184 // Into the shortname tree
2187 if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2190 if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2193 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2195 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2196 AFS_TRACE_LEVEL_VERBOSE,
2197 "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2199 &DirEntry->NameInformation.FileName);
2201 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2206 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2209 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2210 AFS_TRACE_LEVEL_VERBOSE,
2211 "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2213 &DirEntry->NameInformation.FileName);
2217 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2219 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2220 AFS_TRACE_LEVEL_VERBOSE,
2221 "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2223 &DirEntry->NameInformation.FileName);
2228 if( InsertInEnumList)
2232 // And insert the node into the directory list
2235 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2236 AFS_TRACE_LEVEL_VERBOSE,
2237 "AFSInsertDirectoryNode Inserting entry %08lX %wZ FID %08lX-%08lX-%08lX-%08lXStatus %08lX\n",
2239 &DirEntry->NameInformation.FileName,
2240 DirEntry->ObjectInformation->FileId.Cell,
2241 DirEntry->ObjectInformation->FileId.Volume,
2242 DirEntry->ObjectInformation->FileId.Vnode,
2243 DirEntry->ObjectInformation->FileId.Unique);
2245 if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2248 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2253 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2255 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2258 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2260 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2262 InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2264 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2265 AFS_TRACE_LEVEL_VERBOSE,
2266 "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2267 &DirEntry->NameInformation.FileName,
2268 ParentObjectInfo->Specific.Directory.DirectoryNodeCount,
2269 ParentObjectInfo->FileId.Cell,
2270 ParentObjectInfo->FileId.Volume,
2271 ParentObjectInfo->FileId.Vnode,
2272 ParentObjectInfo->FileId.Unique);
2280 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2281 IN AFSDirectoryCB *DirEntry)
2284 NTSTATUS ntStatus = STATUS_SUCCESS;
2289 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2290 AFS_TRACE_LEVEL_VERBOSE,
2291 "AFSDeleteDirEntry Deleting dir entry in parent %08lX Entry %08lX %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2294 &DirEntry->NameInformation.FileName,
2295 DirEntry->ObjectInformation->FileId.Cell,
2296 DirEntry->ObjectInformation->FileId.Volume,
2297 DirEntry->ObjectInformation->FileId.Vnode,
2298 DirEntry->ObjectInformation->FileId.Unique);
2300 AFSRemoveDirNodeFromParent( ParentObjectInfo,
2305 // Free up the name buffer if it was reallocated
2308 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2311 AFSExFreePool( DirEntry->NameInformation.FileName.Buffer);
2314 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2317 AFSExFreePool( DirEntry->NameInformation.TargetName.Buffer);
2321 // Dereference the object for this dir entry
2324 ASSERT( DirEntry->ObjectInformation->ObjectReferenceCount > 0);
2326 if( InterlockedDecrement( &DirEntry->ObjectInformation->ObjectReferenceCount) == 0)
2328 SetFlag( DirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2331 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2332 AFS_TRACE_LEVEL_VERBOSE,
2333 "AFSDeleteDirEntry Decrement count on object %08lX Cnt %d\n",
2334 DirEntry->ObjectInformation,
2335 DirEntry->ObjectInformation->ObjectReferenceCount);
2337 ExDeleteResourceLite( &DirEntry->NonPaged->Lock);
2339 AFSExFreePool( DirEntry->NonPaged);
2342 // Free up the dir entry
2345 AFSExFreePool( DirEntry);
2352 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2353 IN AFSDirectoryCB *DirEntry,
2354 IN BOOLEAN RemoveFromEnumList)
2357 NTSTATUS ntStatus = STATUS_SUCCESS;
2363 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2365 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2366 AFS_TRACE_LEVEL_VERBOSE,
2367 "AFSRemoveDirNodeFromParent Removing DirEntry %08lX %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %08lX\n",
2369 &DirEntry->NameInformation.FileName,
2370 DirEntry->ObjectInformation->FileId.Cell,
2371 DirEntry->ObjectInformation->FileId.Volume,
2372 DirEntry->ObjectInformation->FileId.Vnode,
2373 DirEntry->ObjectInformation->FileId.Unique,
2376 if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2379 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2380 AFS_TRACE_LEVEL_VERBOSE,
2381 "AFSRemoveDirNodeFromParent Removing DirEntry %08lX name %wZ\n",
2383 &DirEntry->NameInformation.FileName);
2385 AFSRemoveNameEntry( ParentObjectInfo,
2391 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2392 AFS_TRACE_LEVEL_VERBOSE,
2393 "AFSRemoveDirNodeFromParent DE %p for %wZ NOT removing entry due to flag set\n",
2395 &DirEntry->NameInformation.FileName);
2399 if( RemoveFromEnumList &&
2400 BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST))
2404 // And remove the entry from the enumeration list
2407 if( DirEntry->ListEntry.fLink == NULL)
2410 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = (AFSDirectoryCB *)DirEntry->ListEntry.bLink;
2415 ((AFSDirectoryCB *)DirEntry->ListEntry.fLink)->ListEntry.bLink = DirEntry->ListEntry.bLink;
2418 if( DirEntry->ListEntry.bLink == NULL)
2421 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = (AFSDirectoryCB *)DirEntry->ListEntry.fLink;
2426 ((AFSDirectoryCB *)DirEntry->ListEntry.bLink)->ListEntry.fLink = DirEntry->ListEntry.fLink;
2429 ASSERT( ParentObjectInfo->Specific.Directory.DirectoryNodeCount > 0);
2431 InterlockedDecrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2433 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2435 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2436 AFS_TRACE_LEVEL_VERBOSE,
2437 "AFSRemoveDirNodeFromParent Removing entry %wZ Dec Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2438 &DirEntry->NameInformation.FileName,
2439 ParentObjectInfo->Specific.Directory.DirectoryNodeCount,
2440 ParentObjectInfo->FileId.Cell,
2441 ParentObjectInfo->FileId.Volume,
2442 ParentObjectInfo->FileId.Vnode,
2443 ParentObjectInfo->FileId.Unique);
2445 DirEntry->ListEntry.fLink = NULL;
2446 DirEntry->ListEntry.bLink = NULL;
2454 AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
2455 IN OUT PUNICODE_STRING TargetFileName)
2458 NTSTATUS ntStatus = STATUS_SUCCESS;
2459 UNICODE_STRING uniFileName;
2465 // We will process backwards from the end of the name looking
2466 // for the first \ we encounter
2469 uniFileName.Length = FileName->Length;
2470 uniFileName.MaximumLength = FileName->MaximumLength;
2472 uniFileName.Buffer = FileName->Buffer;
2477 if( uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
2481 // Subtract one more character off of the filename if it is not the root
2484 if( uniFileName.Length > sizeof( WCHAR))
2487 uniFileName.Length -= sizeof( WCHAR);
2491 // Now build up the target name
2494 TargetFileName->Length = FileName->Length - uniFileName.Length;
2497 // If we are not on the root then fixup the name
2500 if( uniFileName.Length > sizeof( WCHAR))
2503 TargetFileName->Length -= sizeof( WCHAR);
2505 TargetFileName->Buffer = &uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) + 1];
2510 TargetFileName->Buffer = &uniFileName.Buffer[ uniFileName.Length/sizeof( WCHAR)];
2514 // Fixup the passed back filename length
2517 FileName->Length = uniFileName.Length;
2519 TargetFileName->MaximumLength = TargetFileName->Length;
2524 uniFileName.Length -= sizeof( WCHAR);
2532 AFSParseName( IN PIRP Irp,
2534 OUT PUNICODE_STRING FileName,
2535 OUT PUNICODE_STRING ParsedFileName,
2536 OUT PUNICODE_STRING RootFileName,
2537 OUT ULONG *ParseFlags,
2538 OUT AFSVolumeCB **VolumeCB,
2539 OUT AFSDirectoryCB **ParentDirectoryCB,
2540 OUT AFSNameArrayHdr **NameArray)
2543 NTSTATUS ntStatus = STATUS_SUCCESS;
2544 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2545 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2546 UNICODE_STRING uniFullName, uniComponentName, uniRemainingPath;
2548 AFSDirectoryCB *pDirEntry = NULL, *pShareDirEntry = NULL, *pTargetDirEntry = NULL;
2549 USHORT usIndex = 0, usDriveIndex = 0;
2550 AFSCcb *pRelatedCcb = NULL;
2551 AFSNameArrayHdr *pNameArray = NULL, *pRelatedNameArray = NULL;
2552 USHORT usComponentIndex = 0;
2553 USHORT usComponentLength = 0;
2554 AFSVolumeCB *pVolumeCB = NULL;
2555 AFSFcb *pRelatedFcb = NULL;
2556 BOOLEAN bReleaseTreeLock = FALSE;
2557 BOOLEAN bIsAllShare = FALSE;
2563 // Indicate we are opening a root ...
2566 *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
2568 if( pIrpSp->FileObject->RelatedFileObject != NULL)
2571 pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
2573 pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
2575 pRelatedNameArray = pRelatedCcb->NameArray;
2577 uniFullName = pIrpSp->FileObject->FileName;
2579 ASSERT( pRelatedFcb != NULL);
2582 // No wild cards in the name
2585 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2586 AFS_TRACE_LEVEL_VERBOSE_2,
2587 "AFSParseName (%08lX) Relative open for %wZ FID %08lX-%08lX-%08lX-%08lX component %wZ\n",
2589 &pRelatedCcb->DirectoryCB->NameInformation.FileName,
2590 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Cell,
2591 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Volume,
2592 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
2593 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Unique,
2596 if( FsRtlDoesNameContainWildCards( &uniFullName))
2599 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2600 AFS_TRACE_LEVEL_ERROR,
2601 "AFSParseName (%08lX) Component %wZ contains wild cards\n",
2605 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
2608 pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
2610 pDirEntry = pRelatedCcb->DirectoryCB;
2612 *FileName = pIrpSp->FileObject->FileName;
2615 // Grab the root node while checking state
2618 AFSAcquireShared( pVolumeCB->VolumeLock,
2621 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
2622 BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
2626 // The volume has been taken off line so fail the access
2629 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2630 AFS_TRACE_LEVEL_ERROR,
2631 "AFSParseName (%08lX) Volume %08lX:%08lX OFFLINE/INVALID\n",
2633 pVolumeCB->ObjectInformation.FileId.Cell,
2634 pVolumeCB->ObjectInformation.FileId.Volume);
2636 AFSReleaseResource( pVolumeCB->VolumeLock);
2638 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
2641 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
2644 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2645 AFS_TRACE_LEVEL_VERBOSE,
2646 "AFSParseName (%08lX) Verifying root of volume %08lX:%08lX\n",
2648 pVolumeCB->ObjectInformation.FileId.Cell,
2649 pVolumeCB->ObjectInformation.FileId.Volume);
2651 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
2654 if( !NT_SUCCESS( ntStatus))
2657 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2658 AFS_TRACE_LEVEL_ERROR,
2659 "AFSParseName (%08lX) Failed verification of root Status %08lX\n",
2663 AFSReleaseResource( pVolumeCB->VolumeLock);
2665 try_return( ntStatus);
2669 AFSReleaseResource( pVolumeCB->VolumeLock);
2671 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
2674 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2675 AFS_TRACE_LEVEL_VERBOSE,
2676 "AFSParseName (%08lX) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2678 &pDirEntry->NameInformation.FileName,
2679 pDirEntry->ObjectInformation->FileId.Cell,
2680 pDirEntry->ObjectInformation->FileId.Volume,
2681 pDirEntry->ObjectInformation->FileId.Vnode,
2682 pDirEntry->ObjectInformation->FileId.Unique);
2684 ntStatus = AFSVerifyEntry( AuthGroup,
2687 if( !NT_SUCCESS( ntStatus))
2690 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2691 AFS_TRACE_LEVEL_VERBOSE,
2692 "AFSParseName (%08lX) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2694 &pDirEntry->NameInformation.FileName,
2695 pDirEntry->ObjectInformation->FileId.Cell,
2696 pDirEntry->ObjectInformation->FileId.Volume,
2697 pDirEntry->ObjectInformation->FileId.Vnode,
2698 pDirEntry->ObjectInformation->FileId.Unique,
2701 try_return( ntStatus);
2706 // Create our full path name buffer
2709 uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length +
2711 pIrpSp->FileObject->FileName.Length +
2714 uniFullName.Length = 0;
2716 uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2717 uniFullName.MaximumLength,
2718 AFS_NAME_BUFFER_THREE_TAG);
2720 if( uniFullName.Buffer == NULL)
2723 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2724 AFS_TRACE_LEVEL_ERROR,
2725 "AFSParseName (%08lX) Failed to allocate full name buffer\n",
2728 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2731 RtlZeroMemory( uniFullName.Buffer,
2732 uniFullName.MaximumLength);
2734 RtlCopyMemory( uniFullName.Buffer,
2735 pRelatedCcb->FullFileName.Buffer,
2736 pRelatedCcb->FullFileName.Length);
2738 uniFullName.Length = pRelatedCcb->FullFileName.Length;
2740 usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
2742 usComponentLength = pIrpSp->FileObject->FileName.Length;
2744 if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
2745 pIrpSp->FileObject->FileName.Length > 0 &&
2746 pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
2747 pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
2750 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
2752 uniFullName.Length += sizeof( WCHAR);
2754 usComponentLength += sizeof( WCHAR);
2757 if( pIrpSp->FileObject->FileName.Length > 0)
2760 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
2761 pIrpSp->FileObject->FileName.Buffer,
2762 pIr
\epSp->FileObject->FileName.Length);
2764 uniFullName.Length += pIrpSp->FileObject->FileName.Length;
2767 *RootFileName = uniFullName;
2770 // We populate up to the current parent
2773 if( pRelatedNameArray == NULL)
2777 // Init and populate our name array
2780 pNameArray = AFSInitNameArray( NULL,
2783 if( pNameArray == NULL)
2786 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2787 AFS_TRACE_LEVEL_VERBOSE,
2788 "AFSParseName (%08lX) Failed to initialize name array\n",
2791 AFSExFreePool( uniFullName.Buffer);
2793 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2796 ntStatus = AFSPopulateNameArray( pNameArray,
2798 pRelatedCcb->DirectoryCB);
2804 // Init and populate our name array
2807 pNameArray = AFSInitNameArray( NULL,
2808 pRelatedNameArray->MaxElementCount);
2810 if( pNameArray == NULL)
2813 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2814 AFS_TRACE_LEVEL_VERBOSE,
2815 "AFSParseName (%08lX) Failed to initialize name array\n",
2818 AFSExFreePool( uniFullName.Buffer);
2820 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2823 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
2825 pRelatedCcb->DirectoryCB);
2828 if( !NT_SUCCESS( ntStatus))
2831 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2832 AFS_TRACE_LEVEL_VERBOSE,
2833 "AFSParseName (%08lX) Failed to populate name array\n",
2836 AFSExFreePool( uniFullName.Buffer);
2838 try_return( ntStatus);
2841 ParsedFileName->Length = usComponentLength;
2842 ParsedFileName->MaximumLength = uniFullName.MaximumLength;
2844 ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
2847 // Indicate to caller that RootFileName must be freed
2850 SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
2852 *NameArray = pNameArray;
2854 *VolumeCB = pVolumeCB;
2857 // Increment our volume reference count
2860 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2862 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2863 AFS_TRACE_LEVEL_VERBOSE,