2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSNameSupport.cpp
39 #include "AFSCommon.h"
44 // On entry, *VolumeCB must have a held ReferenceCount provided by
45 // the caller which will not be released. On successful exit, *OutVolumeCB
46 // will be assigned the new current volume with a held ReferenceCount.
48 // On entry, *ParentDirectoryCB must have a held DirOpenReferenceCount
49 // provided by the caller. This reference will not be released.
50 // On exit, if OutParentDirectoryCB is set, it will have a new reference.
52 // On exit, if OutDirectoryCB is set, it will have a reference.
56 AFSLocateNameEntry( IN GUID *AuthGroup,
57 IN PFILE_OBJECT FileObject,
58 IN OUT UNICODE_STRING *RootPathName,
59 IN UNICODE_STRING *ParsedPathName,
60 IN AFSNameArrayHdr *NameArray,
62 IN AFSVolumeCB *VolumeCB,
63 IN AFSDirectoryCB *ParentDirectoryCB,
64 OUT AFSVolumeCB **OutVolumeCB,
65 OUT LONG *OutVolumeReferenceReason,
66 OUT AFSDirectoryCB **OutParentDirectoryCB,
67 OUT AFSDirectoryCB **OutDirectoryCB,
68 OUT PUNICODE_STRING ComponentName)
71 NTSTATUS ntStatus = STATUS_SUCCESS;
72 UNICODE_STRING uniPathName, uniComponentName, uniRemainingPath, uniSearchName, uniFullPathName;
74 AFSDirectoryCB *pDirEntry = NULL, *pParentDirEntry = NULL;
75 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
76 UNICODE_STRING uniSysName;
77 ULONG ulSubstituteIndex = 0;
78 BOOLEAN bSubstituteName = FALSE;
79 AFSNameArrayHdr *pNameArray = NameArray;
80 BOOLEAN bAllocatedSymLinkBuffer = FALSE;
81 UNICODE_STRING uniRelativeName, uniNoOpName;
82 AFSObjectInfoCB *pCurrentObject = NULL;
83 AFSObjectInfoCB *pParentObjectInfo = NULL;
84 AFSVolumeCB *pCurrentVolume = NULL;
85 AFSVolumeCB *pTargetVolume = NULL;
86 BOOLEAN bReleaseCurrentVolume = FALSE;
87 LONG VolumeReferenceReason;
88 BOOLEAN bSubstitutedName = FALSE;
94 ASSERT( *OutVolumeCB != VolumeCB);
96 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
97 AFS_TRACE_LEVEL_VERBOSE_2,
98 "AFSLocateNameEntry (FO: %p) Processing full name %wZ\n",
102 RtlInitUnicodeString( &uniSysName,
105 RtlInitUnicodeString( &uniRelativeName,
108 RtlInitUnicodeString( &uniNoOpName,
112 // Cleanup some parameters
115 if( ComponentName != NULL)
118 ComponentName->Length = 0;
119 ComponentName->MaximumLength = 0;
120 ComponentName->Buffer = NULL;
124 // We will parse through the filename, locating the directory nodes until we encounter a cache miss
125 // Starting at the root node
128 pParentDirEntry = NULL;
130 pDirEntry = ParentDirectoryCB;
133 // Increment our reference on this dir entry
136 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
138 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
139 AFS_TRACE_LEVEL_VERBOSE,
140 "AFSLocateNameEntry Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
141 &pDirEntry->NameInformation.FileName,
146 pCurrentVolume = VolumeCB;
148 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
150 lCount = AFSVolumeIncrement( pCurrentVolume,
151 VolumeReferenceReason);
153 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
154 AFS_TRACE_LEVEL_VERBOSE,
155 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
157 VolumeReferenceReason,
160 bReleaseCurrentVolume = TRUE;
162 uniPathName = *ParsedPathName;
164 uniFullPathName = *RootPathName;
166 uniComponentName.Length = uniComponentName.MaximumLength = 0;
167 uniComponentName.Buffer = NULL;
169 uniRemainingPath.Length = uniRemainingPath.MaximumLength = 0;
170 uniRemainingPath.Buffer = NULL;
172 uniSearchName.Length = uniSearchName.MaximumLength = 0;
173 uniSearchName.Buffer = NULL;
178 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
180 ASSERT( pDirEntry->DirOpenReferenceCount > 0);
183 // Check our total link count for this name array
186 if( pNameArray->LinkCount >= (LONG)pDevExt->Specific.RDR.MaxLinkCount)
189 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
192 pCurrentObject = pDirEntry->ObjectInformation;
194 KeQueryTickCount( &pCurrentObject->LastAccessCount);
197 // Check that the directory entry is not deleted or pending delete
200 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
203 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
204 AFS_TRACE_LEVEL_ERROR,
205 "AFSLocateNameEntry (FO: %p) Deleted parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
207 &pDirEntry->NameInformation.FileName,
208 pCurrentObject->FileId.Cell,
209 pCurrentObject->FileId.Volume,
210 pCurrentObject->FileId.Vnode,
211 pCurrentObject->FileId.Unique,
212 STATUS_FILE_DELETED));
214 try_return( ntStatus = STATUS_FILE_DELETED);
217 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
220 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
221 AFS_TRACE_LEVEL_ERROR,
222 "AFSLocateNameEntry (FO: %p) Delete pending on %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
224 &pDirEntry->NameInformation.FileName,
225 pCurrentObject->FileId.Cell,
226 pCurrentObject->FileId.Volume,
227 pCurrentObject->FileId.Vnode,
228 pCurrentObject->FileId.Unique,
229 STATUS_DELETE_PENDING));
231 try_return( ntStatus = STATUS_DELETE_PENDING);
235 // Check if the directory requires verification
238 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
239 ( pCurrentObject->FileType != AFS_FILE_TYPE_DIRECTORY ||
240 !AFSIsEnumerationInProcess( pCurrentObject)))
243 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
244 AFS_TRACE_LEVEL_VERBOSE,
245 "AFSLocateNameEntry (FO: %p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
247 &pDirEntry->NameInformation.FileName,
248 pCurrentObject->FileId.Cell,
249 pCurrentObject->FileId.Volume,
250 pCurrentObject->FileId.Vnode,
251 pCurrentObject->FileId.Unique));
254 // Directory TreeLock should be exclusively held
257 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
260 ntStatus = AFSVerifyEntry( AuthGroup,
264 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
266 if( !NT_SUCCESS( ntStatus))
269 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
270 AFS_TRACE_LEVEL_ERROR,
271 "AFSLocateNameEntry (FO: %p) Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
273 &pDirEntry->NameInformation.FileName,
274 pCurrentObject->FileId.Cell,
275 pCurrentObject->FileId.Volume,
276 pCurrentObject->FileId.Vnode,
277 pCurrentObject->FileId.Unique,
280 try_return( ntStatus);
285 // Ensure the parent node has been evaluated, if not then go do it now
288 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) ||
289 pCurrentObject->FileType == AFS_FILE_TYPE_UNKNOWN)
292 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
293 AFS_TRACE_LEVEL_VERBOSE,
294 "AFSLocateNameEntry (FO: %p) Evaluating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
296 &pDirEntry->NameInformation.FileName,
297 pCurrentObject->FileId.Cell,
298 pCurrentObject->FileId.Volume,
299 pCurrentObject->FileId.Vnode,
300 pCurrentObject->FileId.Unique));
302 ntStatus = AFSEvaluateNode( AuthGroup,
305 if( !NT_SUCCESS( ntStatus))
308 if ( ntStatus == STATUS_NOT_A_DIRECTORY)
311 if ( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
314 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
315 AFS_TRACE_LEVEL_ERROR,
316 "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT NULL Status %08lX\n",
318 &pDirEntry->NameInformation.FileName,
319 pCurrentObject->FileId.Cell,
320 pCurrentObject->FileId.Volume,
321 pCurrentObject->FileId.Vnode,
322 pCurrentObject->FileId.Unique,
328 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
329 AFS_TRACE_LEVEL_ERROR,
330 "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT %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,
337 pCurrentObject->ParentFileId.Cell,
338 pCurrentObject->ParentFileId.Volume,
339 pCurrentObject->ParentFileId.Vnode,
340 pCurrentObject->ParentFileId.Unique,
346 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
347 AFS_TRACE_LEVEL_ERROR,
348 "AFSLocateNameEntry (FO: %p) Failed to evaluate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
350 &pDirEntry->NameInformation.FileName,
351 pCurrentObject->FileId.Cell,
352 pCurrentObject->FileId.Volume,
353 pCurrentObject->FileId.Vnode,
354 pCurrentObject->FileId.Unique,
358 try_return( ntStatus);
361 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
365 // If this is a mount point or symlink then go get the real directory node
368 switch( pCurrentObject->FileType)
371 case AFS_FILE_TYPE_SYMLINK:
374 UNICODE_STRING uniTempName;
375 WCHAR *pTmpBuffer = NULL;
379 // Check if the flag is set to NOT evaluate a symlink
380 // and we are done with the parsing
383 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL) &&
384 uniRemainingPath.Length == 0)
388 // Pass back the directory entries
391 *OutParentDirectoryCB = pParentDirEntry;
393 pParentDirEntry = NULL;
395 *OutDirectoryCB = pDirEntry;
399 *OutVolumeCB = pCurrentVolume;
401 *OutVolumeReferenceReason = VolumeReferenceReason;
403 bReleaseCurrentVolume = FALSE;
405 *RootPathName = uniFullPathName;
407 try_return( ntStatus);
410 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
413 AFSAcquireExcl( &pDirEntry->NonPaged->Lock,
416 if( pDirEntry->NameInformation.TargetName.Length == 0)
420 // We'll reset the DV to ensure we validate the metadata content
423 pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
425 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
427 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
428 AFS_TRACE_LEVEL_VERBOSE,
429 "AFSLocateNameEntry (FO: %p) Verifying symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
431 &pDirEntry->NameInformation.FileName,
432 pCurrentObject->FileId.Cell,
433 pCurrentObject->FileId.Volume,
434 pCurrentObject->FileId.Vnode,
435 pCurrentObject->FileId.Unique));
438 // Directory TreeLock should be exclusively held
441 ntStatus = AFSVerifyEntry( AuthGroup,
445 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
447 if( !NT_SUCCESS( ntStatus))
450 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
451 AFS_TRACE_LEVEL_ERROR,
452 "AFSLocateNameEntry (FO: %p) Failed to verify symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
454 &pDirEntry->NameInformation.FileName,
455 pCurrentObject->FileId.Cell,
456 pCurrentObject->FileId.Volume,
457 pCurrentObject->FileId.Vnode,
458 pCurrentObject->FileId.Unique,
461 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
463 try_return( ntStatus);
467 // If the type changed then reprocess this entry
470 if( pCurrentObject->FileType != AFS_FILE_TYPE_SYMLINK)
473 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
481 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
485 // If we were given a zero length target name then deny access to the entry
488 if( pDirEntry->NameInformation.TargetName.Length == 0)
491 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
493 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
494 AFS_TRACE_LEVEL_ERROR,
495 "AFSLocateNameEntry (FO: %p) Failed to retrieve target name for symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
497 &pDirEntry->NameInformation.FileName,
498 pCurrentObject->FileId.Cell,
499 pCurrentObject->FileId.Volume,
500 pCurrentObject->FileId.Vnode,
501 pCurrentObject->FileId.Unique,
504 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
506 try_return( ntStatus);
509 if( AFSIsRelativeName( &pDirEntry->NameInformation.TargetName))
512 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
513 AFS_TRACE_LEVEL_VERBOSE,
514 "AFSLocateNameEntry (FO: %p) Processing relative symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
516 &pDirEntry->NameInformation.TargetName,
517 &pDirEntry->NameInformation.FileName,
518 pCurrentObject->FileId.Cell,
519 pCurrentObject->FileId.Volume,
520 pCurrentObject->FileId.Vnode,
521 pCurrentObject->FileId.Unique));
524 // We'll substitute this name into the current process name
525 // starting at where we sit in the path
528 uniTempName.Length = 0;
529 uniTempName.MaximumLength = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer) +
530 pDirEntry->NameInformation.TargetName.Length +
532 uniRemainingPath.Length;
534 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
535 uniTempName.MaximumLength,
536 AFS_NAME_BUFFER_ONE_TAG);
538 if( uniTempName.Buffer == NULL)
541 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
543 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
547 // We have so first copy in the portion up to the component
551 RtlCopyMemory( uniTempName.Buffer,
552 uniFullPathName.Buffer,
553 (ULONG)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer));
555 uniTempName.Length = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer);
557 if( bAllocatedSymLinkBuffer ||
561 pTmpBuffer = uniFullPathName.Buffer;
564 bAllocatedSymLinkBuffer = TRUE;
567 // Have we parsed this name yet? Better have at least once ...
570 if( uniComponentName.Length == 0)
576 // Copy in the target name ...
579 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
580 pDirEntry->NameInformation.TargetName.Buffer,
581 pDirEntry->NameInformation.TargetName.Length);
583 uniPathName.Buffer = &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)];
585 uniPathName.Length += pDirEntry->NameInformation.TargetName.Length;
586 uniPathName.MaximumLength = uniTempName.MaximumLength;
588 uniTempName.Length += pDirEntry->NameInformation.TargetName.Length;
591 // And now any remaining portion of the name
594 if( uniRemainingPath.Length > 0)
597 if( uniRemainingPath.Buffer[ 0] != L'\\')
600 uniRemainingPath.Buffer--;
601 uniRemainingPath.Length += sizeof( WCHAR);
603 uniPathName.Length += sizeof( WCHAR);
606 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
607 uniRemainingPath.Buffer,
608 uniRemainingPath.Length);
610 uniTempName.Length += uniRemainingPath.Length;
613 uniFullPathName = uniTempName;
615 if( pTmpBuffer != NULL)
618 AFSExFreePoolWithTag( pTmpBuffer, 0);
621 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
624 // Dereference the current entry ..
627 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
629 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
630 AFS_TRACE_LEVEL_VERBOSE,
631 "AFSLocateNameEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
632 &pDirEntry->NameInformation.FileName,
637 ASSERT( lCount >= 0);
640 // OK, need to back up one entry for the correct parent since the current
641 // entry we are on is the symlink itself
644 pDirEntry = AFSBackupEntry( pNameArray);
646 pCurrentObject = pDirEntry->ObjectInformation;
649 // Increment our reference on this dir entry
652 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
654 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
655 AFS_TRACE_LEVEL_VERBOSE,
656 "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
657 &pDirEntry->NameInformation.FileName,
662 if ( pParentDirEntry)
665 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
667 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
668 AFS_TRACE_LEVEL_VERBOSE,
669 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
670 &pParentDirEntry->NameInformation.FileName,
675 pParentDirEntry = NULL;
678 if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
681 pParentDirEntry = AFSGetParentEntry( pNameArray);
683 ASSERT( pParentDirEntry != pDirEntry);
685 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
687 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
688 AFS_TRACE_LEVEL_VERBOSE,
689 "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
690 &pParentDirEntry->NameInformation.FileName,
696 if ( pDirEntry->ObjectInformation->VolumeCB != pCurrentVolume)
699 lCount = AFSVolumeDecrement( pCurrentVolume,
700 VolumeReferenceReason);
702 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
703 AFS_TRACE_LEVEL_VERBOSE,
704 "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
706 VolumeReferenceReason,
709 pCurrentVolume = pDirEntry->ObjectInformation->VolumeCB;
711 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
713 lCount = AFSVolumeIncrement( pCurrentVolume,
714 VolumeReferenceReason);
716 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
717 AFS_TRACE_LEVEL_VERBOSE,
718 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
720 VolumeReferenceReason,
727 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
728 AFS_TRACE_LEVEL_VERBOSE,
729 "AFSLocateNameEntry (FO: %p) Processing absolute symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
731 &pDirEntry->NameInformation.TargetName,
732 &pDirEntry->NameInformation.FileName,
733 pCurrentObject->FileId.Cell,
734 pCurrentObject->FileId.Volume,
735 pCurrentObject->FileId.Vnode,
736 pCurrentObject->FileId.Unique));
738 if ( !AFSIsAbsoluteAFSName( &pDirEntry->NameInformation.TargetName))
741 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
742 AFS_TRACE_LEVEL_ERROR,
743 "AFSLocateNameEntry Name %wZ contains invalid server name\n",
744 &pDirEntry->NameInformation.TargetName));
747 // The correct response would be STATUS_OBJECT_PATH_INVALID
748 // but that prevents cmd.exe from performing a recursive
749 // directory enumeration when opening a directory entry
750 // that represents a symlink to an invalid path is discovered.
753 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
755 try_return( ntStatus = STATUS_OBJECT_PATH_NOT_FOUND);
759 // We'll substitute this name into the current process name
760 // starting at where we sit in the path
763 uniTempName.Length = 0;
764 uniTempName.MaximumLength = pDirEntry->NameInformation.TargetName.Length +
766 uniRemainingPath.Length;
768 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
769 uniTempName.MaximumLength,
770 AFS_NAME_BUFFER_TWO_TAG);
772 if( uniTempName.Buffer == NULL)
775 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
777 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
780 if( bAllocatedSymLinkBuffer ||
784 pTmpBuffer = uniFullPathName.Buffer;
787 bAllocatedSymLinkBuffer = TRUE;
790 // Have we parsed this name yet? Better have at least once ...
793 if( uniComponentName.Length == 0)
799 // Copy in the target name ...
802 RtlCopyMemory( uniTempName.Buffer,
803 &pDirEntry->NameInformation.TargetName.Buffer[ AFSMountRootName.Length/sizeof( WCHAR)],
804 pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length);
806 uniTempName.Length = pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length;
809 // And now any remaining portion of the name
812 if( uniRemainingPath.Length > 0)
815 if( uniRemainingPath.Buffer[ 0] != L'\\')
818 uniRemainingPath.Buffer--;
819 uniRemainingPath.Length += sizeof( WCHAR);
822 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
823 uniRemainingPath.Buffer,
824 uniRemainingPath.Length);
826 uniTempName.Length += uniRemainingPath.Length;
829 uniFullPathName = uniTempName;
831 uniPathName = uniTempName;
833 if( pTmpBuffer != NULL)
836 AFSExFreePoolWithTag( pTmpBuffer, 0);
839 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
842 // If our current volume is not the global root then make it so ...
845 if( pCurrentVolume != AFSGlobalRoot)
848 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
849 AFS_TRACE_LEVEL_VERBOSE,
850 "AFSLocateNameEntry (FO: %p) Current volume not global, resetting 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 lCount = AFSVolumeDecrement( pCurrentVolume,
859 VolumeReferenceReason);
861 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
862 AFS_TRACE_LEVEL_VERBOSE,
863 "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
865 VolumeReferenceReason,
868 pCurrentVolume = AFSGlobalRoot;
870 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
872 lCount = AFSVolumeIncrement( pCurrentVolume,
873 VolumeReferenceReason);
875 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
876 AFS_TRACE_LEVEL_VERBOSE,
877 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
879 VolumeReferenceReason,
884 // Dereference our current dir entry
887 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
889 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
890 AFS_TRACE_LEVEL_VERBOSE,
891 "AFSLocateNameEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
892 &pDirEntry->NameInformation.FileName,
897 ASSERT( lCount >= 0);
899 pDirEntry = pCurrentVolume->DirectoryCB;
901 pCurrentObject = pDirEntry->ObjectInformation;
904 // Reference the new dir entry
907 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
909 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
910 AFS_TRACE_LEVEL_VERBOSE,
911 "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
912 &pDirEntry->NameInformation.FileName,
918 // Reset the name array
919 // Persist the link count in the name array
922 lLinkCount = pNameArray->LinkCount;
924 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
925 AFS_TRACE_LEVEL_VERBOSE,
926 "AFSLocateNameEntry (FO: %p) Resetting name array for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
928 &pDirEntry->NameInformation.FileName,
929 pCurrentObject->FileId.Cell,
930 pCurrentObject->FileId.Volume,
931 pCurrentObject->FileId.Vnode,
932 pCurrentObject->FileId.Unique));
934 AFSResetNameArray( pNameArray,
937 pNameArray->LinkCount = lLinkCount;
939 if ( pParentDirEntry)
942 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
944 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
945 AFS_TRACE_LEVEL_VERBOSE,
946 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
947 &pParentDirEntry->NameInformation.FileName,
952 pParentDirEntry = NULL;
957 // Increment our link count
960 lCount = InterlockedIncrement( &pNameArray->LinkCount);
965 case AFS_FILE_TYPE_MOUNTPOINT:
969 // Check if the flag is set to NOT evaluate a mount point
970 // and we are done with the parsing
973 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL) &&
974 uniRemainingPath.Length == 0)
978 // Pass back the directory entries
981 *OutParentDirectoryCB = pParentDirEntry;
983 pParentDirEntry = NULL;
985 *OutDirectoryCB = pDirEntry;
989 *OutVolumeCB = pCurrentVolume;
991 *OutVolumeReferenceReason = VolumeReferenceReason;
993 bReleaseCurrentVolume = FALSE;
995 *RootPathName = uniFullPathName;
997 try_return( ntStatus);
1000 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1001 AFS_TRACE_LEVEL_VERBOSE,
1002 "AFSLocateNameEntry (FO: %p) Building MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1004 &pDirEntry->NameInformation.FileName,
1005 pCurrentObject->FileId.Cell,
1006 pCurrentObject->FileId.Volume,
1007 pCurrentObject->FileId.Vnode,
1008 pCurrentObject->FileId.Unique));
1011 // Go retrieve the target entry for this node
1012 // Release the current volume cb entry since we would
1013 // have lock inversion in the following call
1014 // Also decrement the ref count on the volume
1017 ntStatus = AFSBuildMountPointTarget( AuthGroup,
1021 if( !NT_SUCCESS( ntStatus))
1024 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1025 AFS_TRACE_LEVEL_ERROR,
1026 "AFSLocateNameEntry (FO: %p) Failed to build MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1028 &pDirEntry->NameInformation.FileName,
1029 pCurrentObject->FileId.Cell,
1030 pCurrentObject->FileId.Volume,
1031 pCurrentObject->FileId.Vnode,
1032 pCurrentObject->FileId.Unique,
1035 try_return( ntStatus);
1038 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
1040 lCount = AFSVolumeDecrement( pCurrentVolume,
1041 VolumeReferenceReason);
1043 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1044 AFS_TRACE_LEVEL_VERBOSE,
1045 "AFSLocateNameEntry Decrement2 count on volume %p Reason %u Cnt %d\n",
1047 VolumeReferenceReason,
1050 pCurrentVolume = pTargetVolume;
1052 pTargetVolume = NULL;
1054 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
1056 VolumeReferenceReason = AFS_VOLUME_REFERENCE_MOUNTPT;
1059 // We want to restart processing here on the new parent ...
1060 // Deref and ref count the entries
1063 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1065 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1066 AFS_TRACE_LEVEL_VERBOSE,
1067 "AFSLocateNameEntry Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
1068 &pDirEntry->NameInformation.FileName,
1073 ASSERT( lCount >= 0);
1075 pDirEntry = pCurrentVolume->DirectoryCB;
1077 pCurrentObject = pDirEntry->ObjectInformation;
1079 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1081 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1082 AFS_TRACE_LEVEL_VERBOSE,
1083 "AFSLocateNameEntry Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
1084 &pDirEntry->NameInformation.FileName,
1090 // The name array stores both the mount point and the target.
1091 // Insert the target.
1094 AFSInsertNextElement( pNameArray,
1097 if ( pParentDirEntry)
1100 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1102 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1103 AFS_TRACE_LEVEL_VERBOSE,
1104 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1105 &pParentDirEntry->NameInformation.FileName,
1110 pParentDirEntry = NULL;
1114 // Increment our link count
1117 lCount = InterlockedIncrement( &pNameArray->LinkCount);
1122 case AFS_FILE_TYPE_DFSLINK:
1125 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL))
1129 // Pass back the directory entries
1132 *OutParentDirectoryCB = pParentDirEntry;
1134 pParentDirEntry = NULL;
1136 *OutDirectoryCB = pDirEntry;
1140 *OutVolumeCB = pCurrentVolume;
1142 *OutVolumeReferenceReason = VolumeReferenceReason;
1144 bReleaseCurrentVolume = FALSE;
1146 *RootPathName = uniFullPathName;
1148 try_return( ntStatus);
1152 // This is a DFS link so we need to update the file name and return STATUS_REPARSE to the
1153 // system for it to reevaluate it
1156 if( FileObject != NULL)
1159 ntStatus = AFSProcessDFSLink( pDirEntry,
1168 // This is where we have been re-entered from an NP evaluation call via the BuildBranch()
1172 ntStatus = STATUS_INVALID_PARAMETER;
1175 if( ntStatus != STATUS_SUCCESS &&
1176 ntStatus != STATUS_REPARSE)
1179 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1180 AFS_TRACE_LEVEL_ERROR,
1181 "AFSLocateNameEntry (FO: %p) Failed to process DFSLink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1183 &pDirEntry->NameInformation.FileName,
1184 pCurrentObject->FileId.Cell,
1185 pCurrentObject->FileId.Volume,
1186 pCurrentObject->FileId.Vnode,
1187 pCurrentObject->FileId.Unique,
1191 try_return( ntStatus);
1194 case AFS_FILE_TYPE_UNKNOWN:
1195 case AFS_FILE_TYPE_INVALID:
1199 // Something was not processed ...
1202 try_return( ntStatus = STATUS_ACCESS_DENIED);
1205 } /* end of switch */
1208 // If the parent is not initialized then do it now
1211 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1212 !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED) &&
1213 uniPathName.Length > 0)
1216 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1217 AFS_TRACE_LEVEL_VERBOSE,
1218 "AFSLocateNameEntry (FO: %p) Enumerating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1220 &pDirEntry->NameInformation.FileName,
1221 pCurrentObject->FileId.Cell,
1222 pCurrentObject->FileId.Volume,
1223 pCurrentObject->FileId.Vnode,
1224 pCurrentObject->FileId.Unique));
1226 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1229 if( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1232 ntStatus = AFSEnumerateDirectory( AuthGroup,
1236 if( !NT_SUCCESS( ntStatus))
1239 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1241 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1242 AFS_TRACE_LEVEL_ERROR,
1243 "AFSLocateNameEntry (FO: %p) Failed to enumerate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1245 &pDirEntry->NameInformation.FileName,
1246 pCurrentObject->FileId.Cell,
1247 pCurrentObject->FileId.Volume,
1248 pCurrentObject->FileId.Vnode,
1249 pCurrentObject->FileId.Unique,
1252 try_return( ntStatus);
1256 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1258 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1261 if( uniPathName.Length > 0)
1264 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1265 AFS_TRACE_LEVEL_ERROR,
1266 "AFSLocateNameEntry (FO: %p) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1268 &pDirEntry->NameInformation.FileName,
1269 pCurrentObject->FileId.Cell,
1270 pCurrentObject->FileId.Volume,
1271 pCurrentObject->FileId.Vnode,
1272 pCurrentObject->FileId.Unique));
1274 // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1275 // one of the components of the path is not a directory. However, returning
1276 // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1277 // Instead IIS insists on treating the target file as if it is a directory containing
1278 // a potential web.config file. NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1279 // AFS will follow suit.
1281 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1286 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1287 AFS_TRACE_LEVEL_VERBOSE,
1288 "AFSLocateNameEntry (FO: %p) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1290 &pDirEntry->NameInformation.FileName,
1291 pCurrentObject->FileId.Cell,
1292 pCurrentObject->FileId.Volume,
1293 pCurrentObject->FileId.Vnode,
1294 pCurrentObject->FileId.Unique));
1297 // Pass back the directory entries
1300 *OutParentDirectoryCB = pParentDirEntry;
1302 pParentDirEntry = NULL;
1304 *OutDirectoryCB = pDirEntry;
1308 *OutVolumeCB = pCurrentVolume;
1310 *OutVolumeReferenceReason = VolumeReferenceReason;
1312 bReleaseCurrentVolume = FALSE;
1314 *RootPathName = uniFullPathName;
1317 try_return( ntStatus);
1321 // If we are at the end of the processing, set our returned information and get out
1324 if( uniPathName.Length == 0)
1327 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1328 AFS_TRACE_LEVEL_VERBOSE,
1329 "AFSLocateNameEntry (FO: %p) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1331 &pDirEntry->NameInformation.FileName,
1332 pCurrentObject->FileId.Cell,
1333 pCurrentObject->FileId.Volume,
1334 pCurrentObject->FileId.Vnode,
1335 pCurrentObject->FileId.Unique));
1338 // Pass back the directory entries
1341 *OutParentDirectoryCB = pParentDirEntry;
1343 pParentDirEntry = NULL;
1345 *OutDirectoryCB = pDirEntry;
1349 *OutVolumeCB = pCurrentVolume;
1351 *OutVolumeReferenceReason = VolumeReferenceReason;
1353 bReleaseCurrentVolume = FALSE;
1355 *RootPathName = uniFullPathName;
1357 try_return( ntStatus);
1361 // We may have returned to the top of the while( TRUE)
1363 if( bSubstituteName &&
1364 uniSearchName.Buffer != NULL)
1367 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1369 bSubstituteName = FALSE;
1371 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1372 uniSearchName.Buffer = NULL;
1375 ulSubstituteIndex = 1;
1377 ntStatus = STATUS_SUCCESS;
1380 // Get the next component name
1383 FsRtlDissectName( uniPathName,
1388 // Check for the . and .. in the path
1391 if( RtlCompareUnicodeString( &uniComponentName,
1396 uniPathName = uniRemainingPath;
1401 if( RtlCompareUnicodeString( &uniComponentName,
1406 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1407 AFS_TRACE_LEVEL_VERBOSE,
1408 "AFSLocateNameEntry (FO: %p) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1410 &pDirEntry->NameInformation.FileName,
1411 pCurrentObject->FileId.Cell,
1412 pCurrentObject->FileId.Volume,
1413 pCurrentObject->FileId.Vnode,
1414 pCurrentObject->FileId.Unique));
1417 // Need to back up one entry in the name array
1419 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1421 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1422 AFS_TRACE_LEVEL_VERBOSE,
1423 "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1424 &pDirEntry->NameInformation.FileName,
1429 ASSERT( lCount >= 0);
1431 pDirEntry = AFSBackupEntry( NameArray);
1433 if( pDirEntry == NULL)
1436 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1437 AFS_TRACE_LEVEL_ERROR,
1438 "AFSLocateNameEntry AFSBackupEntry failed\n"));
1440 try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1443 pCurrentObject = pDirEntry->ObjectInformation;
1445 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1447 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1448 AFS_TRACE_LEVEL_VERBOSE,
1449 "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1450 &pDirEntry->NameInformation.FileName,
1455 if ( pParentDirEntry)
1458 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1460 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1461 AFS_TRACE_LEVEL_VERBOSE,
1462 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1463 &pParentDirEntry->NameInformation.FileName,
1468 pParentDirEntry = NULL;
1471 if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1474 pParentDirEntry = AFSGetParentEntry( pNameArray);
1476 ASSERT( pParentDirEntry != pDirEntry);
1478 if ( pParentDirEntry)
1481 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
1483 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1484 AFS_TRACE_LEVEL_VERBOSE,
1485 "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
1486 &pParentDirEntry->NameInformation.FileName,
1493 if ( pDirEntry->ObjectInformation->VolumeCB != pCurrentVolume)
1496 lCount = AFSVolumeDecrement( pCurrentVolume,
1497 VolumeReferenceReason);
1499 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1500 AFS_TRACE_LEVEL_VERBOSE,
1501 "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
1503 VolumeReferenceReason,
1506 pCurrentVolume = pDirEntry->ObjectInformation->VolumeCB;
1508 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
1510 lCount = AFSVolumeIncrement( pCurrentVolume,
1511 VolumeReferenceReason);
1513 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1514 AFS_TRACE_LEVEL_VERBOSE,
1515 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
1517 VolumeReferenceReason,
1521 uniPathName = uniRemainingPath;
1527 // Update our pointers
1530 if ( pParentDirEntry)
1533 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1535 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1536 AFS_TRACE_LEVEL_VERBOSE,
1537 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1538 &pParentDirEntry->NameInformation.FileName,
1544 pParentDirEntry = pDirEntry;
1548 pCurrentObject = NULL;
1550 uniSearchName = uniComponentName;
1552 while( pDirEntry == NULL)
1556 // If the SearchName contains @SYS then we perform the substitution.
1557 // If there is no substitution we give up.
1560 if( !bSubstituteName &&
1561 FsRtlIsNameInExpression( &uniSysName,
1567 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1568 AFS_TRACE_LEVEL_VERBOSE_2,
1569 "AFSLocateNameEntry (FO: %p) Processing @SYS substitution for %wZ Index %08lX\n",
1572 ulSubstituteIndex));
1574 ntStatus = AFSSubstituteSysName( &uniComponentName,
1578 if ( NT_SUCCESS( ntStatus))
1581 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1582 AFS_TRACE_LEVEL_VERBOSE_2,
1583 "AFSLocateNameEntry (FO: %p) Located substitution %wZ for %wZ Index %08lX\n",
1587 ulSubstituteIndex));
1590 // Go reparse the name again
1593 bSubstituteName = TRUE;
1595 ulSubstituteIndex++; // For the next entry, if needed
1597 continue; // while( pDirEntry == NULL)
1602 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1603 AFS_TRACE_LEVEL_ERROR,
1604 "AFSLocateNameEntry (FO: %p) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1610 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1614 // Pass back the directory entries
1617 *OutParentDirectoryCB = pParentDirEntry;
1619 pParentDirEntry = NULL;
1621 *OutDirectoryCB = NULL;
1623 *OutVolumeCB = pCurrentVolume;
1625 *OutVolumeReferenceReason = VolumeReferenceReason;
1627 bReleaseCurrentVolume = FALSE;
1629 if( ComponentName != NULL)
1632 *ComponentName = uniComponentName;
1635 *RootPathName = uniFullPathName;
1639 // We can't possibly have a pDirEntry since the lookup failed
1641 try_return( ntStatus);
1646 // Generate the CRC on the node and perform a case sensitive lookup
1649 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1650 AFS_TRACE_LEVEL_VERBOSE_2,
1651 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case sensitive\n",
1655 ulCRC = AFSGenerateCRC( &uniSearchName,
1658 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1661 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1665 if( pDirEntry == NULL)
1669 // Missed so perform a case insensitive lookup
1672 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1673 AFS_TRACE_LEVEL_VERBOSE_2,
1674 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case insensitive\n",
1678 ulCRC = AFSGenerateCRC( &uniSearchName,
1681 AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1685 if( pDirEntry == NULL)
1689 // OK, if this component is a valid short name then try
1690 // a lookup in the short name tree
1693 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1694 RtlIsNameLegalDOS8Dot3( &uniSearchName,
1699 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1700 AFS_TRACE_LEVEL_VERBOSE_2,
1701 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ short name\n",
1705 AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1710 if ( pDirEntry == NULL &&
1711 pParentDirEntry->ObjectInformation->VolumeCB == AFSGlobalRoot)
1715 // Check with the service to see if this is a valid cell name
1716 // that can be automatically resolved. Drop the shared TreeLock
1717 // since AFSCheckCellName must acquire it exclusively.
1720 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1722 ntStatus = AFSCheckCellName( AuthGroup,
1726 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1730 if( pDirEntry == NULL)
1734 // If we substituted a name then reset our search name and try again
1737 if( bSubstituteName)
1740 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1742 uniSearchName = uniComponentName;
1744 bSubstituteName = FALSE;
1746 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1748 continue; // while( pDirEntry == NULL)
1752 // Node name not found so get out
1755 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1757 if( uniRemainingPath.Length > 0)
1760 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1762 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1763 AFS_TRACE_LEVEL_VERBOSE,
1764 "AFSLocateNameEntry (FO: %p) Returning path not found for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
1767 pParentDirEntry->ObjectInformation->FileId.Cell,
1768 pParentDirEntry->ObjectInformation->FileId.Volume,
1769 pParentDirEntry->ObjectInformation->FileId.Vnode,
1770 pParentDirEntry->ObjectInformation->FileId.Unique));
1775 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1777 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1778 AFS_TRACE_LEVEL_VERBOSE,
1779 "AFSLocateNameEntry (FO: %p) Returning name not found for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
1782 pParentDirEntry->ObjectInformation->FileId.Cell,
1783 pParentDirEntry->ObjectInformation->FileId.Volume,
1784 pParentDirEntry->ObjectInformation->FileId.Vnode,
1785 pParentDirEntry->ObjectInformation->FileId.Unique));
1788 // Pass back the directory entries
1791 *OutParentDirectoryCB = pParentDirEntry;
1793 pParentDirEntry = NULL;
1795 *OutDirectoryCB = NULL;
1797 *OutVolumeCB = pCurrentVolume;
1799 *OutVolumeReferenceReason = VolumeReferenceReason;
1801 bReleaseCurrentVolume = FALSE;
1803 if( ComponentName != NULL)
1806 *ComponentName = uniComponentName;
1809 *RootPathName = uniFullPathName;
1812 try_return( ntStatus);
1819 // Here we have a match on the case insensitive lookup for the name. If there
1820 // Is more than one link entry for this node then fail the lookup request
1823 pCurrentObject = pDirEntry->ObjectInformation;
1825 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1826 pDirEntry->CaseInsensitiveList.fLink != NULL)
1830 // Increment our dir entry ref count since we will decrement it on exit
1833 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1835 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1836 AFS_TRACE_LEVEL_VERBOSE,
1837 "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1838 &pDirEntry->NameInformation.FileName,
1843 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1845 try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1850 if( pDirEntry != NULL)
1854 // If the verify flag is set on the parent and the current entry is deleted
1855 // revalidate the parent and search again.
1858 pCurrentObject = pDirEntry->ObjectInformation;
1860 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1861 BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1864 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1866 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1867 AFS_TRACE_LEVEL_VERBOSE,
1868 "AFSLocateNameEntry (FO: %p) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1870 &pParentDirEntry->NameInformation.FileName,
1871 pParentDirEntry->ObjectInformation->FileId.Cell,
1872 pParentDirEntry->ObjectInformation->FileId.Volume,
1873 pParentDirEntry->ObjectInformation->FileId.Vnode,
1874 pParentDirEntry->ObjectInformation->FileId.Unique));
1877 // Directory TreeLock should be exclusively held
1880 AFSAcquireExcl( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1883 ntStatus = AFSVerifyEntry( AuthGroup,
1887 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1889 if( !NT_SUCCESS( ntStatus))
1892 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1893 AFS_TRACE_LEVEL_ERROR,
1894 "AFSLocateNameEntry (FO: %p) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1896 &pParentDirEntry->NameInformation.FileName,
1897 pParentDirEntry->ObjectInformation->FileId.Cell,
1898 pParentDirEntry->ObjectInformation->FileId.Volume,
1899 pParentDirEntry->ObjectInformation->FileId.Vnode,
1900 pParentDirEntry->ObjectInformation->FileId.Unique,
1903 try_return( ntStatus);
1906 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1907 AFS_TRACE_LEVEL_VERBOSE,
1908 "AFSLocateNameEntry (FO: %p) Reprocessing component %wZ in parent %wZ\n",
1911 &pParentDirEntry->NameInformation.FileName));
1916 pCurrentObject = NULL;
1922 // Increment our dir entry ref count
1925 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1927 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1928 AFS_TRACE_LEVEL_VERBOSE,
1929 "AFSLocateNameEntry Increment6 count on %wZ DE %p Ccb %p Cnt %d\n",
1930 &pDirEntry->NameInformation.FileName,
1936 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1938 } // End while( pDirEntry == NULL)
1941 // If we have a dirEntry for this component, perform some basic validation on it
1944 if( pDirEntry != NULL)
1947 pCurrentObject = pDirEntry->ObjectInformation;
1949 if (BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1952 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1953 AFS_TRACE_LEVEL_ERROR,
1954 "AFSLocateNameEntry (FO: %p) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1956 &pDirEntry->NameInformation.FileName,
1957 pCurrentObject->FileId.Cell,
1958 pCurrentObject->FileId.Volume,
1959 pCurrentObject->FileId.Vnode,
1960 pCurrentObject->FileId.Unique));
1963 // This entry was deleted through the invalidation call back so perform cleanup
1967 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1970 pParentObjectInfo = AFSFindObjectInfo( pCurrentObject->VolumeCB,
1971 &pCurrentObject->ParentFileId,
1975 ASSERT( pParentObjectInfo != NULL);
1977 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1980 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1983 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1985 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1986 AFS_TRACE_LEVEL_VERBOSE,
1987 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1988 &pDirEntry->NameInformation.FileName,
1993 ASSERT( lCount >= 0);
1996 pDirEntry->NameArrayReferenceCount <= 0)
1999 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2000 AFS_TRACE_LEVEL_VERBOSE,
2001 "AFSLocateNameEntry Deleting dir entry %p (%p) for %wZ\n",
2004 &pDirEntry->NameInformation.FileName));
2007 // Remove and delete the directory entry from the parent list
2010 AFSDeleteDirEntry( pParentObjectInfo,
2013 AFSAcquireShared( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
2016 if( pCurrentObject->ObjectReferenceCount <= 0)
2019 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
2022 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2023 AFS_TRACE_LEVEL_VERBOSE,
2024 "AFSLocateNameEntry Removing object %p from volume tree\n",
2027 AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
2028 &pCurrentObject->TreeEntry);
2030 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
2034 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
2039 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2040 AFS_TRACE_LEVEL_VERBOSE,
2041 "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
2043 &pDirEntry->NameInformation.FileName));
2045 SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
2047 AFSRemoveNameEntry( pParentObjectInfo,
2051 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2053 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
2056 // We deleted the dir entry so check if there is any remaining portion
2057 // of the name to process.
2060 if( uniRemainingPath.Length > 0)
2063 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
2065 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2066 AFS_TRACE_LEVEL_VERBOSE,
2067 "AFSLocateNameEntry (FO: %p) Returning path not found(2) for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
2070 pParentObjectInfo->FileId.Cell,
2071 pParentObjectInfo->FileId.Volume,
2072 pParentObjectInfo->FileId.Vnode,
2073 pParentObjectInfo->FileId.Unique));
2075 AFSReleaseObjectInfo( &pParentObjectInfo);
2080 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
2082 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2083 AFS_TRACE_LEVEL_VERBOSE,
2084 "AFSLocateNameEntry (FO: %p) Returning name not found(2) for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
2087 pParentObjectInfo->FileId.Cell,
2088 pParentObjectInfo->FileId.Volume,
2089 pParentObjectInfo->FileId.Vnode,
2090 pParentObjectInfo->FileId.Unique));
2092 AFSReleaseObjectInfo( &pParentObjectInfo);
2095 // Pass back the directory entries
2098 *OutParentDirectoryCB = pParentDirEntry;
2100 pParentDirEntry = NULL;
2102 *OutDirectoryCB = NULL;
2104 *OutVolumeCB = pCurrentVolume;
2106 *OutVolumeReferenceReason = VolumeReferenceReason;
2108 bReleaseCurrentVolume = FALSE;
2110 if( ComponentName != NULL)
2113 *ComponentName = uniComponentName;
2116 *RootPathName = uniFullPathName;
2121 if( ntStatus != STATUS_SUCCESS)
2124 try_return( ntStatus);
2128 // If we ended up substituting a name in the component then update
2129 // the full path and update the pointers
2132 if( bSubstituteName)
2135 BOOLEAN bRelativeOpen = FALSE;
2137 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2138 AFS_TRACE_LEVEL_VERBOSE_2,
2139 "AFSLocateNameEntry (FO: %p) Substituting %wZ into %wZ Index %08lX\n",
2143 ulSubstituteIndex));
2145 if( FileObject != NULL &&
2146 FileObject->RelatedFileObject != NULL)
2149 bRelativeOpen = TRUE;
2153 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
2154 // and free the prior Buffer contents but only if the fourth
2155 // parameter is TRUE.
2158 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
2163 bAllocatedSymLinkBuffer ||
2166 if( !NT_SUCCESS( ntStatus))
2169 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2170 AFS_TRACE_LEVEL_ERROR,
2171 "AFSLocateNameEntry (FO: %p) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
2178 try_return( ntStatus);
2182 // We have substituted a name into the buffer so if we do this again for this
2183 // path, we need to free up the buffer we allocated.
2186 bSubstitutedName = TRUE;
2190 // Update the search parameters
2193 uniPathName = uniRemainingPath;
2196 // Check if the is a SymLink entry but has no Target FileID or Name. In this
2197 // case it might be a DFS Link so let's go and evaluate it to be sure
2200 if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
2201 ( pCurrentObject->TargetFileId.Vnode == 0 ||
2202 pDirEntry->NameInformation.TargetName.Length == 0))
2205 ntStatus = AFSValidateSymLink( AuthGroup,
2208 if( !NT_SUCCESS( ntStatus))
2211 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2212 AFS_TRACE_LEVEL_ERROR,
2213 "AFSLocateNameEntry (FO: %p) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2215 &pDirEntry->NameInformation.FileName,
2216 pCurrentObject->FileId.Cell,
2217 pCurrentObject->FileId.Volume,
2218 pCurrentObject->FileId.Vnode,
2219 pCurrentObject->FileId.Unique,
2222 try_return( ntStatus);
2227 // Update the name array
2230 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2231 AFS_TRACE_LEVEL_VERBOSE,
2232 "AFSLocateNameEntry (FO: %p) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2234 &pDirEntry->NameInformation.FileName,
2235 pCurrentObject->FileId.Cell,
2236 pCurrentObject->FileId.Volume,
2237 pCurrentObject->FileId.Vnode,
2238 pCurrentObject->FileId.Unique));
2240 ntStatus = AFSInsertNextElement( pNameArray,
2243 if( !NT_SUCCESS( ntStatus))
2246 try_return( ntStatus);
2252 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2253 AFS_TRACE_LEVEL_VERBOSE,
2254 "AFSLocateNameEntry (FO: %p) Completed processing %wZ Status %08lX\n",
2259 if( ( !NT_SUCCESS( ntStatus) &&
2260 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
2261 ntStatus == STATUS_REPARSE)
2263 if( RootPathName->Buffer != uniFullPathName.Buffer)
2266 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
2272 if( *OutParentDirectoryCB != NULL)
2275 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2276 AFS_TRACE_LEVEL_VERBOSE,
2277 "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
2278 &(*OutParentDirectoryCB)->NameInformation.FileName,
2279 *OutParentDirectoryCB,
2281 (*OutParentDirectoryCB)->DirOpenReferenceCount));
2284 if( *OutDirectoryCB != NULL)
2287 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2288 AFS_TRACE_LEVEL_VERBOSE,
2289 "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
2290 &(*OutDirectoryCB)->NameInformation.FileName,
2293 (*OutDirectoryCB)->DirOpenReferenceCount));
2297 if( pDirEntry != NULL)
2300 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
2302 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2303 AFS_TRACE_LEVEL_VERBOSE,
2304 "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
2305 &pDirEntry->NameInformation.FileName,
2310 ASSERT( lCount >= 0);
2313 if( pParentDirEntry != NULL)
2316 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
2318 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2319 AFS_TRACE_LEVEL_VERBOSE,
2320 "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
2321 &pParentDirEntry->NameInformation.FileName,
2326 ASSERT( lCount >= 0);
2329 if( bReleaseCurrentVolume)
2332 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
2334 lCount = AFSVolumeDecrement( pCurrentVolume,
2335 VolumeReferenceReason);
2337 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2338 AFS_TRACE_LEVEL_VERBOSE,
2339 "AFSLocateNameEntry Decrement7 count on volume %p Reason %u Cnt %d\n",
2341 VolumeReferenceReason,
2344 bReleaseCurrentVolume = FALSE;
2347 if( bSubstituteName &&
2348 uniSearchName.Buffer != NULL)
2351 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
2359 AFSCreateDirEntry( IN GUID *AuthGroup,
2360 IN AFSObjectInfoCB *ParentObjectInfo,
2361 IN AFSDirectoryCB *ParentDirCB,
2362 IN PUNICODE_STRING FileName,
2363 IN PUNICODE_STRING ComponentName,
2364 IN ULONG Attributes,
2365 IN OUT AFSDirectoryCB **DirEntry)
2368 UNREFERENCED_PARAMETER(FileName);
2369 NTSTATUS ntStatus = STATUS_SUCCESS;
2370 AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
2371 LARGE_INTEGER liFileSize = {0,0};
2377 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2378 AFS_TRACE_LEVEL_VERBOSE_2,
2379 "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
2380 &ParentDirCB->NameInformation.FileName,
2381 ParentObjectInfo->FileId.Cell,
2382 ParentObjectInfo->FileId.Volume,
2383 ParentObjectInfo->FileId.Vnode,
2384 ParentObjectInfo->FileId.Unique,
2389 // OK, before inserting the node into the parent tree, issue
2390 // the request to the service for node creation
2391 // We will need to drop the lock on the parent node since the create
2392 // could cause a callback into the file system to invalidate it's cache
2395 ntStatus = AFSNotifyFileCreate( AuthGroup,
2403 // If the returned status is STATUS_REPARSE then the entry exists
2404 // and we raced, get out.
2406 if( ntStatus == STATUS_REPARSE)
2409 *DirEntry = pDirNode;
2411 try_return( ntStatus = STATUS_SUCCESS);
2414 if( !NT_SUCCESS( ntStatus))
2417 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2418 AFS_TRACE_LEVEL_ERROR,
2419 "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
2420 &ParentDirCB->NameInformation.FileName,
2421 ParentObjectInfo->FileId.Cell,
2422 ParentObjectInfo->FileId.Volume,
2423 ParentObjectInfo->FileId.Vnode,
2424 ParentObjectInfo->FileId.Unique,
2429 try_return( ntStatus);
2433 // If AFSNotifyFileCreate returns pDirNode != NULL, then its
2434 // DirOpenReferenceCount is held.
2437 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2441 // Before attempting to insert the new entry, check if we need to validate the parent
2444 if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2447 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2448 AFS_TRACE_LEVEL_VERBOSE,
2449 "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2450 &ParentDirCB->NameInformation.FileName,
2451 ParentObjectInfo->FileId.Cell,
2452 ParentObjectInfo->FileId.Volume,
2453 ParentObjectInfo->FileId.Vnode,
2454 ParentObjectInfo->FileId.Unique));
2456 ntStatus = AFSVerifyEntry( AuthGroup,
2460 if( !NT_SUCCESS( ntStatus))
2463 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2464 AFS_TRACE_LEVEL_ERROR,
2465 "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2466 &ParentDirCB->NameInformation.FileName,
2467 ParentObjectInfo->FileId.Cell,
2468 ParentObjectInfo->FileId.Volume,
2469 ParentObjectInfo->FileId.Vnode,
2470 ParentObjectInfo->FileId.Unique,
2473 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2475 try_return( ntStatus);
2480 // Check for the entry in the event we raced with some other thread
2483 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2484 (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2487 if( pExistingDirNode != NULL)
2489 if (AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2490 &pExistingDirNode->ObjectInformation->FileId))
2493 if ( pExistingDirNode != pDirNode)
2496 lCount = InterlockedDecrement( &pDirNode->DirOpenReferenceCount);
2498 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2499 AFS_TRACE_LEVEL_VERBOSE,
2500 "AFSCreateDirEntry Decrement count on %wZ DE %p Cnt %d\n",
2501 &pDirNode->NameInformation.FileName,
2505 AFSDeleteDirEntry( ParentObjectInfo,
2508 lCount = InterlockedIncrement( &pExistingDirNode->DirOpenReferenceCount);
2510 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2511 AFS_TRACE_LEVEL_VERBOSE,
2512 "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2513 &pExistingDirNode->NameInformation.FileName,
2517 *DirEntry = pExistingDirNode;
2520 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2522 try_return( ntStatus = STATUS_SUCCESS);
2528 // Need to tear down this entry and rebuild it below
2531 if( pExistingDirNode->DirOpenReferenceCount <= 0 &&
2532 pExistingDirNode->NameArrayReferenceCount <= 0)
2535 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2536 AFS_TRACE_LEVEL_VERBOSE,
2537 "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2539 &pExistingDirNode->NameInformation.FileName,
2540 pExistingDirNode->ObjectInformation->FileId.Cell,
2541 pExistingDirNode->ObjectInformation->FileId.Volume,
2542 pExistingDirNode->ObjectInformation->FileId.Vnode,
2543 pExistingDirNode->ObjectInformation->FileId.Unique,
2544 pDirNode->ObjectInformation->FileId.Cell,
2545 pDirNode->ObjectInformation->FileId.Volume,
2546 pDirNode->ObjectInformation->FileId.Vnode,
2547 pDirNode->ObjectInformation->FileId.Unique));
2549 AFSDeleteDirEntry( ParentObjectInfo,
2555 SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2557 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2558 AFS_TRACE_LEVEL_VERBOSE,
2559 "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2561 &pExistingDirNode->NameInformation.FileName,
2562 pExistingDirNode->ObjectInformation->FileId.Cell,
2563 pExistingDirNode->ObjectInformation->FileId.Volume,
2564 pExistingDirNode->ObjectInformation->FileId.Vnode,
2565 pExistingDirNode->ObjectInformation->FileId.Unique,
2566 pDirNode->ObjectInformation->FileId.Cell,
2567 pDirNode->ObjectInformation->FileId.Volume,
2568 pDirNode->ObjectInformation->FileId.Vnode,
2569 pDirNode->ObjectInformation->FileId.Unique));
2571 AFSRemoveNameEntry( ParentObjectInfo,
2577 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2578 AFS_TRACE_LEVEL_VERBOSE_2,
2579 "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2580 &ParentDirCB->NameInformation.FileName,
2581 ParentObjectInfo->FileId.Cell,
2582 ParentObjectInfo->FileId.Volume,
2583 ParentObjectInfo->FileId.Vnode,
2584 ParentObjectInfo->FileId.Unique,
2588 // Insert the directory node
2591 AFSInsertDirectoryNode( ParentObjectInfo,
2596 // Pass back the dir entry
2599 *DirEntry = pDirNode;
2601 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2612 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2613 IN AFSDirectoryCB *DirEntry,
2614 IN BOOLEAN InsertInEnumList)
2622 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2625 // Insert the node into the directory node tree
2628 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2629 AFS_TRACE_LEVEL_VERBOSE,
2630 "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2632 &DirEntry->NameInformation.FileName));
2634 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2636 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2639 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2641 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2642 AFS_TRACE_LEVEL_VERBOSE,
2643 "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2645 &DirEntry->NameInformation.FileName));
2650 AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2653 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2654 AFS_TRACE_LEVEL_VERBOSE,
2655 "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2657 &DirEntry->NameInformation.FileName));
2660 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2663 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2665 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2667 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2668 AFS_TRACE_LEVEL_VERBOSE,
2669 "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2671 &DirEntry->NameInformation.FileName));
2676 AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2679 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2680 AFS_TRACE_LEVEL_VERBOSE,
2681 "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2683 &DirEntry->NameInformation.FileName));
2687 // Into the shortname tree
2690 if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2693 if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2696 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2698 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2699 AFS_TRACE_LEVEL_VERBOSE,
2700 "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2702 &DirEntry->NameInformation.FileName));
2704 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2709 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2712 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2713 AFS_TRACE_LEVEL_VERBOSE,
2714 "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2716 &DirEntry->NameInformation.FileName));
2720 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2722 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2723 AFS_TRACE_LEVEL_VERBOSE,
2724 "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2726 &DirEntry->NameInformation.FileName));
2731 if( InsertInEnumList)
2735 // And insert the node into the directory list
2738 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2739 AFS_TRACE_LEVEL_VERBOSE,
2740 "AFSInsertDirectoryNode Inserting entry %p %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2742 &DirEntry->NameInformation.FileName,
2743 DirEntry->ObjectInformation->FileId.Cell,
2744 DirEntry->ObjectInformation->FileId.Volume,
2745 DirEntry->ObjectInformation->FileId.Vnode,
2746 DirEntry->ObjectInformation->FileId.Unique));
2748 if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2751 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2756 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2758 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2761 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2763 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2765 lCount = InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2767 AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2768 AFS_TRACE_LEVEL_VERBOSE,
2769 "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2770 &DirEntry->NameInformation.FileName,
2772 ParentObjectInfo->FileId.Cell,
2773 ParentObjectInfo->FileId.Volume,
2774 ParentObjectInfo->FileId.Vnode,
2775 ParentObjectInfo->FileId.Unique));
2783 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2784 IN AFSDirectoryCB **ppDirEntry)
2788 AFSDirectoryCB *pDirEntry;
2793 pDirEntry = (AFSDirectoryCB *) InterlockedCompareExchangePointer( (PVOID *)ppDirEntry,
2797 if ( pDirEntry == NULL)
2800 try_return( NOTHING);
2803 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2804 AFS_TRACE_LEVEL_VERBOSE,
2805 "AFSDeleteDirEntry Deleting dir entry in parent %p Entry %p object %p %wZ RefCount %d\n",
2808 pDirEntry->ObjectInformation,
2809 &pDirEntry->NameInformation.FileName,
2810 pDirEntry->DirOpenReferenceCount));
2812 ASSERT( pDirEntry->DirOpenReferenceCount == 0);
2814 AFSRemoveDirNodeFromParent( ParentObjectInfo,
2819 // Free up the name buffer if it was reallocated
2822 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2825 AFSExFreePoolWithTag( pDirEntry->NameInformation.FileName.Buffer, 0);
2828 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2831 AFSExFreePoolWithTag( pDirEntry->NameInformation.TargetName.Buffer, 0);
2834 if ( pDirEntry->ObjectInformation != NULL)
2837 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
2838 pDirEntry->ObjectInformation->Links == 0)
2841 SetFlag( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2845 // Dereference the object for this dir entry
2848 AFSAcquireShared( pDirEntry->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock,
2851 lCount = AFSObjectInfoDecrement( pDirEntry->ObjectInformation,
2852 AFS_OBJECT_REFERENCE_DIRENTRY);
2854 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2855 AFS_TRACE_LEVEL_VERBOSE,
2856 "AFSDeleteDirEntry Decrement count on object %p Cnt %d\n",
2857 pDirEntry->ObjectInformation,
2860 AFSReleaseResource( pDirEntry->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock);
2863 ExDeleteResourceLite( &pDirEntry->NonPaged->Lock);
2865 AFSExFreePoolWithTag( pDirEntry->NonPaged, AFS_DIR_ENTRY_NP_TAG);
2868 // Free up the dir entry
2871 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
2872 AFS_TRACE_LEVEL_VERBOSE,
2873 "AFSDeleteDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
2876 AFSExFreePoolWithTag( pDirEntry, AFS_DIR_ENTRY_TAG);
2885 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2886 IN AFSDirectoryCB *DirEntry,
2887 IN BOOLEAN RemoveFromEnumList)
2890 NTSTATUS ntStatus = STATUS_SUCCESS;
2897 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2899 if ( DirEntry->ObjectInformation != NULL)
2902 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2903 AFS_TRACE_LEVEL_VERBOSE,
2904 "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %p\n",
2906 &DirEntry->NameInformation.FileName,
2907 DirEntry->ObjectInformation->FileId.Cell,
2908 DirEntry->ObjectInformation->FileId.Volume,
2909 DirEntry->ObjectInformation->FileId.Vnode,
2910 DirEntry->ObjectInformation->FileId.Unique,
2916 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2917 AFS_TRACE_LEVEL_VERBOSE,
2918 "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ from Parent %p\n",
2920 &DirEntry->NameInformation.FileName,
2924 if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2927 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2928 AFS_TRACE_LEVEL_VERBOSE,
2929 "AFSRemoveDirNodeFromParent Removing DirEntry %p name %wZ\n",
2931 &DirEntry->NameInformation.FileName));
2933 AFSRemoveNameEntry( ParentObjectInfo,
2939 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2940 AFS_TRACE_LEVEL_VERBOSE,
2941 "AFSRemoveDirNodeFromParent DE %p for %wZ NOT removing entry due to flag set\n",
2943 &DirEntry->NameInformation.FileName));
2947 if( RemoveFromEnumList &&
2948 BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST))
2952 // And remove the entry from the enumeration list
2955 if( DirEntry->ListEntry.fLink == NULL)
2958 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = (AFSDirectoryCB *)DirEntry->ListEntry.bLink;
2963 ((AFSDirectoryCB *)DirEntry->ListEntry.fLink)->ListEntry.bLink = DirEntry->ListEntry.bLink;
2966 if( DirEntry->ListEntry.bLink == NULL)
2969 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = (AFSDirectoryCB *)DirEntry->ListEntry.fLink;
2974 ((AFSDirectoryCB *)DirEntry->ListEntry.bLink)->ListEntry.fLink = DirEntry->ListEntry.fLink;
2977 ASSERT( ParentObjectInfo->Specific.Directory.DirectoryNodeCount > 0);
2979 lCount = InterlockedDecrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2981 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2983 AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2984 AFS_TRACE_LEVEL_VERBOSE,
2985 "AFSRemoveDirNodeFromParent Removing entry %wZ Dec Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2986 &DirEntry->NameInformation.FileName,
2988 ParentObjectInfo->FileId.Cell,
2989 ParentObjectInfo->FileId.Volume,
2990 ParentObjectInfo->FileId.Vnode,
2991 ParentObjectInfo->FileId.Unique));
2993 DirEntry->ListEntry.fLink = NULL;
2994 DirEntry->ListEntry.bLink = NULL;
3002 AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
3003 IN OUT PUNICODE_STRING TargetFileName)
3006 NTSTATUS ntStatus = STATUS_SUCCESS;
3007 UNICODE_STRING uniFileName;
3013 // We will process backwards from the end of the name looking
3014 // for the first \ we encounter
3017 uniFileName.Length = FileName->Length;
3018 uniFileName.MaximumLength = FileName->MaximumLength;
3020 uniFileName.Buffer = FileName->Buffer;
3025 if( uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
3029 // Subtract one more character off of the filename if it is not the root
3032 if( uniFileName.Length > sizeof( WCHAR))
3035 uniFileName.Length -= sizeof( WCHAR);
3039 // Now build up the target name
3042 TargetFileName->Length = FileName->Length - uniFileName.Length;
3045 // If we are not on the root then fixup the name
3048 if( uniFileName.Length > sizeof( WCHAR))
3051 TargetFileName->Length -= sizeof( WCHAR);
3053 TargetFileName->Buffer = &uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) + 1];
3058 TargetFileName->Buffer = &uniFileName.Buffer[ uniFileName.Length/sizeof( WCHAR)];
3062 // Fixup the passed back filename length
3065 FileName->Length = uniFileName.Length;
3067 TargetFileName->MaximumLength = TargetFileName->Length;
3072 uniFileName.Length -= sizeof( WCHAR);
3080 AFSParseRelatedName( IN PIRP Irp,
3082 OUT PUNICODE_STRING FileName,
3083 OUT PUNICODE_STRING ParsedFileName,
3084 OUT PUNICODE_STRING RootFileName,
3085 OUT ULONG *ParseFlags,
3086 OUT AFSVolumeCB **VolumeCB,
3087 OUT AFSDirectoryCB **ParentDirectoryCB,
3088 OUT AFSNameArrayHdr **NameArray)
3090 NTSTATUS ntStatus = STATUS_SUCCESS;
3091 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
3092 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3093 AFSCcb *pRelatedCcb = NULL;
3094 AFSFcb *pRelatedFcb = NULL;
3095 AFSNameArrayHdr *pRelatedNameArray = NULL;
3096 UNICODE_STRING uniFullName;
3097 AFSDirectoryCB *pDirEntry = NULL;
3098 AFSNameArrayHdr *pNameArray = NULL;
3099 USHORT usComponentIndex = 0;
3100 USHORT usComponentLength = 0;
3101 AFSVolumeCB *pVolumeCB = NULL;
3107 pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
3109 pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
3111 pRelatedNameArray = pRelatedCcb->NameArray;
3113 uniFullName = pIrpSp->FileObject->FileName;
3115 ASSERT( pRelatedFcb != NULL);
3118 // No wild cards in the name
3121 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3122 AFS_TRACE_LEVEL_VERBOSE_2,
3123 "AFSParseNameRelated (%p) Relative open for %wZ FID %08lX-%08lX-%08lX-%08lX component %wZ\n",
3125 &pRelatedCcb->DirectoryCB->NameInformation.FileName,
3126 pRelatedFcb->ObjectInformation->FileId.Cell,
3127 pRelatedFcb->ObjectInformation->FileId.Volume,
3128 pRelatedFcb->ObjectInformation->FileId.Vnode,
3129 pRelatedFcb->ObjectInformation->FileId.Unique,
3132 if( FsRtlDoesNameContainWildCards( &uniFullName))
3135 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3136 AFS_TRACE_LEVEL_ERROR,
3137 "AFSParseNameRelated (%p) Component %wZ contains wild cards\n",
3141 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3144 pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
3146 pDirEntry = pRelatedCcb->DirectoryCB;
3148 *FileName = pIrpSp->FileObject->FileName;
3151 // Grab the root node while checking state
3154 AFSAcquireShared( pVolumeCB->VolumeLock,
3157 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3158 BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3162 // The volume has been taken off line so fail the access
3165 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3166 AFS_TRACE_LEVEL_ERROR,
3167 "AFSParseNameRelated (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3169 pVolumeCB->ObjectInformation.FileId.Cell,
3170 pVolumeCB->ObjectInformation.FileId.Volume));
3172 AFSReleaseResource( pVolumeCB->VolumeLock);
3174 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3177 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3180 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3181 AFS_TRACE_LEVEL_VERBOSE,
3182 "AFSParseNameRelated (%p) Verifying root of volume %08lX:%08lX\n",
3184 pVolumeCB->ObjectInformation.FileId.Cell,
3185 pVolumeCB->ObjectInformation.FileId.Volume));
3187 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3190 if( !NT_SUCCESS( ntStatus))
3193 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3194 AFS_TRACE_LEVEL_ERROR,
3195 "AFSParseNameRelated (%p) Failed verification of root Status %08lX\n",
3199 AFSReleaseResource( pVolumeCB->VolumeLock);
3201 try_return( ntStatus);
3205 AFSReleaseResource( pVolumeCB->VolumeLock);
3207 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
3210 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3211 AFS_TRACE_LEVEL_VERBOSE,
3212 "AFSParseNameRelated (%p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3214 &pDirEntry->NameInformation.FileName,
3215 pDirEntry->ObjectInformation->FileId.Cell,
3216 pDirEntry->ObjectInformation->FileId.Volume,
3217 pDirEntry->ObjectInformation->FileId.Vnode,
3218 pDirEntry->ObjectInformation->FileId.Unique));
3221 // Directory TreeLock should be exclusively held
3224 AFSAcquireExcl( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
3227 ntStatus = AFSVerifyEntry( AuthGroup,
3231 AFSReleaseResource( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
3233 if( !NT_SUCCESS( ntStatus))
3236 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3237 AFS_TRACE_LEVEL_VERBOSE,
3238 "AFSParseNameRelated (%p) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3240 &pDirEntry->NameInformation.FileName,
3241 pDirEntry->ObjectInformation->FileId.Cell,
3242 pDirEntry->ObjectInformation->FileId.Volume,
3243 pDirEntry->ObjectInformation->FileId.Vnode,
3244 pDirEntry->ObjectInformation->FileId.Unique,
3247 try_return( ntStatus);
3252 // Create our full path name buffer
3255 uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length
3256 + sizeof( WCHAR) + pIrpSp->FileObject->FileName.Length
3259 uniFullName.Length = 0;
3261 uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
3262 uniFullName.MaximumLength,
3263 AFS_NAME_BUFFER_THREE_TAG);
3265 if( uniFullName.Buffer == NULL)
3268 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3269 AFS_TRACE_LEVEL_ERROR,
3270 "AFSParseNameRelated (%p) Failed to allocate full name buffer\n",
3273 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3276 SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
3278 RtlZeroMemory( uniFullName.Buffer,
3279 uniFullName.MaximumLength);
3281 RtlCopyMemory( uniFullName.Buffer,
3282 pRelatedCcb->FullFileName.Buffer,
3283 pRelatedCcb->FullFileName.Length);
3285 uniFullName.Length = pRelatedCcb->FullFileName.Length;
3287 usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
3289 usComponentLength = pIrpSp->FileObject->FileName.Length;
3291 if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
3292 pIrpSp->FileObject->FileName.Length > 0 &&
3293 pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
3294 pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
3297 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
3299 uniFullName.Length += sizeof( WCHAR);
3301 usComponentLength += sizeof( WCHAR);
3304 if( pIrpSp->FileObject->FileName.Length > 0)
3307 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
3308 pIrpSp->FileObject->FileName.Buffer,
3309 pIrpSp->FileObject->FileName.Length);
3311 uniFullName.Length += pIrpSp->FileObject->FileName.Length;
3314 *RootFileName = uniFullName;
3317 // We populate up to the current parent
3320 if( pRelatedNameArray == NULL)
3324 // Init and populate our name array
3327 pNameArray = AFSInitNameArray( NULL,
3330 if( pNameArray == NULL)
3333 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3334 AFS_TRACE_LEVEL_VERBOSE,
3335 "AFSParseNameRelated (%p) Failed to initialize name array\n",
3338 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3340 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
3342 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3345 ntStatus = AFSPopulateNameArray( pNameArray,
3347 pRelatedCcb->DirectoryCB);
3353 // Init and populate our name array
3356 pNameArray = AFSInitNameArray( NULL,
3357 pRelatedNameArray->MaxElementCount);
3359 if( pNameArray == NULL)
3362 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3363 AFS_TRACE_LEVEL_VERBOSE,
3364 "AFSParseNameRelated (%p) Failed to initialize name array\n",
3367 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3369 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
3371 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3374 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
3376 pRelatedCcb->DirectoryCB);
3379 if( !NT_SUCCESS( ntStatus))
3382 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3383 AFS_TRACE_LEVEL_VERBOSE,
3384 "AFSParseNameRelated (%p) Failed to populate name array\n",
3387 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3389 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
3391 try_return( ntStatus);
3394 ParsedFileName->Length = usComponentLength;
3396 ParsedFileName->MaximumLength = uniFullName.MaximumLength;
3398 ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
3400 *NameArray = pNameArray;
3403 // Increment our volume reference count
3406 lCount = AFSVolumeIncrement( pVolumeCB,
3407 AFS_VOLUME_REFERENCE_PARSE_NAME);
3409 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3410 AFS_TRACE_LEVEL_VERBOSE,
3411 "AFSParseNameRelated Increment count on volume %p Cnt %d\n",
3415 *VolumeCB = pVolumeCB;
3417 *ParentDirectoryCB = pDirEntry;
3419 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3420 AFS_TRACE_LEVEL_VERBOSE_2,
3421 "AFSParseNameRelated (%p) Returning full name %wZ\n",
3425 try_return( ntStatus);
3429 if( NT_SUCCESS( ntStatus))
3432 if( *ParentDirectoryCB != NULL)
3435 lCount = InterlockedIncrement( &(*ParentDirectoryCB)->DirOpenReferenceCount);
3437 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3438 AFS_TRACE_LEVEL_VERBOSE,
3439 "AFSParseRelatedName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
3440 &(*ParentDirectoryCB)->NameInformation.FileName,
3441 (*ParentDirectoryCB),
3447 if( *VolumeCB != NULL)
3449 ASSERT( (*VolumeCB)->VolumeReferenceCount > 0);
3452 if( ntStatus != STATUS_SUCCESS)
3455 if( pNameArray != NULL)
3458 AFSFreeNameArray( pNameArray);
3467 AFSParseName( IN PIRP Irp,
3469 OUT PUNICODE_STRING FileName,
3470 OUT PUNICODE_STRING ParsedFileName,
3471 OUT PUNICODE_STRING RootFileName,
3472 OUT ULONG *ParseFlags,
3473 OUT AFSVolumeCB **VolumeCB,
3474 OUT AFSDirectoryCB **ParentDirectoryCB,
3475 OUT AFSNameArrayHdr **NameArray)
3478 NTSTATUS ntStatus = STATUS_SUCCESS;
3479 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
3480 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3481 UNICODE_STRING uniFullName, uniComponentName, uniRemainingPath;
3483 AFSDirectoryCB *pDirEntry = NULL;
3484 USHORT usIndex = 0, usDriveIndex = 0;
3485 AFSNameArrayHdr *pNameArray = NULL;
3486 USHORT usComponentIndex = 0;
3487 USHORT usComponentLength = 0;
3488 AFSVolumeCB *pVolumeCB = NULL;
3489 BOOLEAN bReleaseTreeLock = FALSE;
3490 BOOLEAN bIsAllShare = FALSE;
3496 if( pIrpSp->FileObject->RelatedFileObject != NULL)
3499 return AFSParseRelatedName( Irp, AuthGroup, FileName,
3500 ParsedFileName, RootFileName,
3501 ParseFlags, VolumeCB,
3502 ParentDirectoryCB, NameArray);
3506 // Indicate we are opening a root ...
3509 *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
3511 *ParentDirectoryCB = NULL;
3514 // No wild cards in the name
3517 uniFullName = pIrpSp->FileObject->FileName;
3519 if( FsRtlDoesNameContainWildCards( &uniFullName) ||
3520 uniFullName.Length < AFSServerName.Length)
3523 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3524 AFS_TRACE_LEVEL_ERROR,
3525 "AFSParseName (%p) Name %wZ contains wild cards or too short\n",
3529 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3533 // The name is a fully qualified name. Parse out the server/share names and
3534 // point to the root qualified name
3535 // First thing is to locate the server name
3538 FsRtlDissectName( uniFullName,
3542 uniFullName = uniRemainingPath;
3545 // This component is the server name we are serving
3548 if( RtlCompareUnicodeString( &uniComponentName,
3554 // Drive letter based name?
3557 uniFullName = pIrpSp->FileObject->FileName;
3559 while( usIndex < uniFullName.Length/sizeof( WCHAR))
3562 if( uniFullName.Buffer[ usIndex] == L':')
3565 uniFullName.Buffer = &uniFullName.Buffer[ usIndex + 2];
3567 uniFullName.Length -= (usIndex + 2) * sizeof( WCHAR);
3569 usDriveIndex = usIndex - 1;
3578 // Do we have the right server name now?
3581 FsRtlDissectName( uniFullName,
3585 uniFullName = uniRemainingPath;
3588 // This component is the server name we are serving
3591 if( RtlCompareUnicodeString( &uniComponentName,
3596 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3597 AFS_TRACE_LEVEL_ERROR,
3598 "AFSParseName (%p) Name %wZ does not have server name\n",
3600 &pIrpSp->FileObject->FileName));
3602 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3606 // Validate this drive letter is actively mapped
3609 if( usDriveIndex > 0 &&
3610 !AFSIsDriveMapped( pIrpSp->FileObject->FileName.Buffer[ usDriveIndex]))
3613 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3614 AFS_TRACE_LEVEL_ERROR,
3615 "AFSParseName (%p) Name %wZ contains invalid drive mapping\n",
3617 &pIrpSp->FileObject->FileName));
3619 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3623 if( FsRtlDoesNameContainWildCards( &uniFullName))
3626 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3627 AFS_TRACE_LEVEL_ERROR,
3628 "AFSParseName (%p) Component %wZ contains wild cards\n",
3632 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3635 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3636 AFS_TRACE_LEVEL_VERBOSE_2,
3637 "AFSParseName (%p) Processing full name %wZ\n",
3641 if( uniFullName.Length > 0 &&
3642 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] == L'\\')
3645 uniFullName.Length -= sizeof( WCHAR);
3649 // Be sure we are online and ready to go
3652 AFSAcquireShared( AFSGlobalRoot->VolumeLock,
3655 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3656 BooleanFlagOn( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3660 // The volume has been taken off line so fail the access
3663 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3664 AFS_TRACE_LEVEL_ERROR,
3665 "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3667 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3668 AFSGlobalRoot->ObjectInformation.FileId.Volume));
3670 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3672 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3675 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3678 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3679 AFS_TRACE_LEVEL_VERBOSE,
3680 "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
3682 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3683 AFSGlobalRoot->ObjectInformation.FileId.Volume));
3685 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3688 if( !NT_SUCCESS( ntStatus))
3691 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3692 AFS_TRACE_LEVEL_ERROR,
3693 "AFSParseName (%p) Failed verification of root Status %08lX\n",
3697 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3699 try_return( ntStatus);
3703 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3705 if( !BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3708 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3709 AFS_TRACE_LEVEL_VERBOSE,
3710 "AFSParseName (%p) Enumerating global root of volume %08lX:%08lX\n",
3712 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3713 AFSGlobalRoot->ObjectInformation.FileId.Volume));
3715 ntStatus = AFSEnumerateGlobalRoot( AuthGroup);
3717 if( !NT_SUCCESS( ntStatus))
3720 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3721 AFS_TRACE_LEVEL_ERROR,
3722 "AFSParseName (%p) Failed enumeraiton of root Status %08lX\n",
3726 try_return( ntStatus);
3731 // Check for the \\Server access and return it as though it were \\Server\Globalroot
3734 if( uniRemainingPath.Buffer == NULL ||
3735 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3736 uniRemainingPath.Buffer[ 0] == L'\\'))
3739 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3740 AFS_TRACE_LEVEL_VERBOSE_2,
3741 "AFSParseName (%p) Returning global root access\n",
3744 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3746 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3747 AFS_TRACE_LEVEL_VERBOSE,
3748 "AFSParseName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3749 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3750 AFSGlobalRoot->DirectoryCB,
3756 FileName->Length = 0;
3757 FileName->MaximumLength = 0;
3758 FileName->Buffer = NULL;
3760 try_return( ntStatus = STATUS_SUCCESS);
3763 *RootFileName = uniFullName;
3766 // Include the starting \ in the root name
3769 if( RootFileName->Buffer[ 0] != L'\\')
3771 RootFileName->Buffer--;
3772 RootFileName->Length += sizeof( WCHAR);
3773 RootFileName->MaximumLength += sizeof( WCHAR);
3777 // Get the 'share' name
3780 FsRtlDissectName( uniFullName,
3784 if( FsRtlDoesNameContainWildCards( &uniFullName))
3787 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3788 AFS_TRACE_LEVEL_ERROR,
3789 "AFSParseName (%p) Component %wZ contains wild cards\n",
3791 &uniComponentName));
3793 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3797 // If this is the ALL access then perform some additional processing
3800 if( uniComponentName.Length == 0 ||
3801 RtlCompareUnicodeString( &uniComponentName,
3809 // If there is nothing else then get out
3812 if( uniRemainingPath.Buffer == NULL ||
3813 uniRemainingPath.Length == 0 ||
3814 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3815 uniRemainingPath.Buffer[ 0] == L'\\'))
3818 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3819 AFS_TRACE_LEVEL_VERBOSE_2,
3820 "AFSParseName (%p) Returning global root access\n",
3823 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3825 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3826 AFS_TRACE_LEVEL_VERBOSE,
3827 "AFSParseName Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
3828 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3829 AFSGlobalRoot->DirectoryCB,
3835 FileName->Length = 0;
3836 FileName->MaximumLength = 0;
3837 FileName->Buffer = NULL;
3839 try_return( ntStatus = STATUS_SUCCESS);
3843 // Process the name again to strip off the ALL portion
3846 uniFullName = uniRemainingPath;
3848 FsRtlDissectName( uniFullName,
3853 // Check for the PIOCtl name
3856 if( RtlCompareUnicodeString( &uniComponentName,
3861 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3862 AFS_TRACE_LEVEL_VERBOSE_2,
3863 "AFSParseName (%p) Returning root PIOCtl access\n",
3866 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3868 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3869 AFS_TRACE_LEVEL_VERBOSE,
3870 "AFSParseName Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
3871 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3872 AFSGlobalRoot->DirectoryCB,
3876 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3880 *FileName = AFSPIOCtlName;
3882 try_return( ntStatus = STATUS_SUCCESS);
3885 else if( (pDirEntry = AFSGetSpecialShareNameEntry( &uniComponentName,
3886 &uniRemainingPath)) != NULL)
3889 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3890 AFS_TRACE_LEVEL_VERBOSE_2,
3891 "AFSParseName (%p) Returning root share name %wZ access\n",
3893 &uniComponentName));
3896 // Add in the full share name to pass back
3899 if( uniRemainingPath.Buffer != NULL)
3903 // This routine strips off the leading slash so add it back in
3906 uniRemainingPath.Buffer--;
3907 uniRemainingPath.Length += sizeof( WCHAR);
3908 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3911 // And the cell name
3914 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3915 uniRemainingPath.Length += uniComponentName.Length;
3916 uniRemainingPath.MaximumLength += uniComponentName.Length;
3918 uniComponentName = uniRemainingPath;
3923 *FileName = uniComponentName;
3925 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3927 *ParentDirectoryCB = pDirEntry;
3929 try_return( ntStatus = STATUS_SUCCESS);
3933 // Determine the 'share' we are accessing
3936 ulCRC = AFSGenerateCRC( &uniComponentName,
3939 AFSAcquireShared( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3942 bReleaseTreeLock = TRUE;
3944 AFSLocateCaseSensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
3948 if( pDirEntry == NULL)
3951 ulCRC = AFSGenerateCRC( &uniComponentName,
3954 AFSLocateCaseInsensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
3958 if( pDirEntry == NULL)
3962 // OK, if this component is a valid short name then try
3963 // a lookup in the short name tree
3966 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3967 RtlIsNameLegalDOS8Dot3( &uniComponentName,
3972 AFSLocateShortNameDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.ShortNameTree,
3977 if( pDirEntry == NULL)
3981 // Check with the service whether it is a valid cell name
3984 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3986 bReleaseTreeLock = FALSE;
3988 ntStatus = AFSCheckCellName( AuthGroup,
3992 if( !NT_SUCCESS( ntStatus))
3996 uniRemainingPath.Length == 0 &&
3997 ntStatus == STATUS_OBJECT_PATH_NOT_FOUND)
4000 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4001 AFS_TRACE_LEVEL_VERBOSE,
4002 "AFSParseName (%p) AFSCheckCellName %wZ returned path not found; ntStatus %08X\n",
4005 STATUS_OBJECT_NAME_NOT_FOUND));
4007 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
4010 try_return( ntStatus);
4016 if( bReleaseTreeLock)
4018 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4023 // Be sure we are starting from the correct volume
4026 if( pDirEntry->ObjectInformation->VolumeCB != AFSGlobalRoot)
4030 // We dropped the global root in the CheckCellName routine which is the
4031 // only way we can be here
4034 pVolumeCB = pDirEntry->ObjectInformation->VolumeCB;
4037 // Init our name array
4040 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
4043 if( pNameArray == NULL)
4046 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4047 AFS_TRACE_LEVEL_VERBOSE,
4048 "AFSParseName (%p) Failed to initialize name array\n",
4051 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4054 ntStatus = AFSInsertNextElement( pNameArray,
4055 pVolumeCB->DirectoryCB);
4060 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4061 AFS_TRACE_LEVEL_VERBOSE,
4062 "AFSParseName (%p) Failed to insert name array element\n",
4065 try_return( ntStatus);
4069 // In this case don't add back in the 'share' name since that is where we are
4070 // starting. Just put the leading slash back in
4073 if( uniRemainingPath.Buffer != NULL)
4076 uniRemainingPath.Buffer--;
4077 uniRemainingPath.Length += sizeof( WCHAR);
4078 uniRemainingPath.MaximumLength += sizeof( WCHAR);
4080 if( uniRemainingPath.Length > sizeof( WCHAR))
4083 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
4087 // Pass back the parent being the root of the volume
4090 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
4096 // Pass back a root slash
4099 uniRemainingPath = uniComponentName;
4101 uniRemainingPath.Buffer--;
4102 uniRemainingPath.Length = sizeof( WCHAR);
4103 uniRemainingPath.MaximumLength = sizeof( WCHAR);
4106 // This is a root open so pass back no parent
4113 pVolumeCB = AFSGlobalRoot;
4116 // Init our name array
4119 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
4121 if( pNameArray == NULL)
4124 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4125 AFS_TRACE_LEVEL_VERBOSE,
4126 "AFSParseName (%p) Failed to initialize name array\n",
4129 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4133 // Add back in the 'share' portion of the name since we will parse it out on return
4136 if( uniRemainingPath.Buffer != NULL)
4140 // This routine strips off the leading slash so add it back in
4143 uniRemainingPath.Buffer--;
4144 uniRemainingPath.Length += sizeof( WCHAR);
4145 uniRemainingPath.MaximumLength += sizeof( WCHAR);
4147 if( uniRemainingPath.Length > sizeof( WCHAR))
4150 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
4154 // And the cell name
4157 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
4158 uniRemainingPath.Length += uniComponentName.Length;
4159 uniRemainingPath.MaximumLength += uniComponentName.Length;
4164 uniRemainingPath = uniComponentName;
4168 // And the leading slash again ...
4171 uniRemainingPath.Buffer--;
4172 uniRemainingPath.Length += sizeof( WCHAR);
4173 uniRemainingPath.MaximumLength += sizeof( WCHAR);
4176 // Pass back the parent being the volume root
4179 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
4183 // Return the remaining portion as the file name
4186 *FileName = uniRemainingPath;
4188 *ParsedFileName = uniRemainingPath;
4190 *NameArray = pNameArray;
4192 *VolumeCB = pVolumeCB;
4195 // Increment our reference on the volume
4198 lCount = AFSVolumeIncrement( pVolumeCB,
4199 AFS_VOLUME_REFERENCE_PARSE_NAME);
4201 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4202 AFS_TRACE_LEVEL_VERBOSE,
4203 "AFSParseName Increment2 count on global volume %p Cnt %d\n",
4209 if( NT_SUCCESS( ntStatus))
4212 if( *ParentDirectoryCB != NULL)
4215 lCount = InterlockedIncrement( &(*ParentDirectoryCB)->DirOpenReferenceCount);
4217 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4218 AFS_TRACE_LEVEL_VERBOSE,
4219 "AFSParseName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4220 &(*ParentDirectoryCB)->NameInformation.FileName,
4221 (*ParentDirectoryCB),
4227 if( *VolumeCB != NULL)
4229 ASSERT( (*VolumeCB)->VolumeReferenceCount > 0);
4232 if( ntStatus != STATUS_SUCCESS)
4235 if( pNameArray != NULL)
4238 AFSFreeNameArray( pNameArray);
4247 AFSCheckCellName( IN GUID *AuthGroup,
4248 IN UNICODE_STRING *CellName,
4249 OUT AFSDirectoryCB **ShareDirEntry)
4252 NTSTATUS ntStatus = STATUS_SUCCESS;
4253 UNICODE_STRING uniName;
4254 AFSDirEnumEntry *pDirEnumEntry = NULL;
4255 AFSDirHdr *pDirHdr = &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr;
4256 AFSDirectoryCB *pDirNode = NULL;
4257 UNICODE_STRING uniDirName, uniTargetName;
4258 AFSVolumeCB *pVolumeCB = NULL;
4265 // Look for some default names we will not handle
4268 RtlInitUnicodeString( &uniName,
4271 if( RtlCompareUnicodeString( &uniName,
4276 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4279 RtlInitUnicodeString( &uniName,
4282 if( RtlCompareUnicodeString( &uniName,
4287 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4290 RtlInitUnicodeString( &uniName,
4293 if( RtlCompareUnicodeString( &uniName,
4298 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4301 RtlInitUnicodeString( &uniName,
4304 if( RtlCompareUnicodeString( &uniName,
4309 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4313 // OK, ask the CM about this component name
4316 ntStatus = AFSEvaluateTargetByName( AuthGroup,
4317 &AFSGlobalRoot->ObjectInformation,
4322 if( !NT_SUCCESS( ntStatus))
4325 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4326 AFS_TRACE_LEVEL_WARNING,
4327 "AFSCheckCellName entry %wZ does not exist parent FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4329 AFSGlobalRoot->ObjectInformation.FileId.Cell,
4330 AFSGlobalRoot->ObjectInformation.FileId.Volume,
4331 AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4332 AFSGlobalRoot->ObjectInformation.FileId.Unique,
4335 try_return( ntStatus);
4339 // OK, we have a dir enum entry back so add it to the root node
4342 uniDirName = *CellName;
4344 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
4345 uniTargetName.MaximumLength = uniTargetName.Length;
4346 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
4349 // Is this entry a root volume entry?
4352 if( pDirEnumEntry->FileId.Cell != AFSGlobalRoot->ObjectInformation.FileId.Cell ||
4353 pDirEnumEntry->FileId.Volume != AFSGlobalRoot->ObjectInformation.FileId.Volume)
4357 // Build the root volume entry
4360 ntStatus = AFSBuildRootVolume( AuthGroup,
4361 &pDirEnumEntry->FileId,
4365 // On success returns with a volume reference count held
4368 if( !NT_SUCCESS( ntStatus))
4370 try_return( ntStatus);
4373 *ShareDirEntry = pVolumeCB->DirectoryCB;
4375 lCount = InterlockedIncrement( &pVolumeCB->DirectoryCB->DirOpenReferenceCount);
4377 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4378 AFS_TRACE_LEVEL_VERBOSE,
4379 "AFSCheckCellName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4380 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4381 pVolumeCB->DirectoryCB,
4385 lCount = AFSVolumeDecrement( pVolumeCB,
4386 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4388 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4389 AFS_TRACE_LEVEL_VERBOSE,
4390 "AFSCheckCellName Decrement count on volume %p Cnt %d\n",
4397 lCount = InterlockedIncrement( &pDirHdr->ContentIndex);
4399 pDirNode = AFSInitDirEntry( &AFSGlobalRoot->ObjectInformation,
4405 if( pDirNode == NULL)
4408 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4412 // Init the short name if we have one
4415 if( pDirEnumEntry->ShortNameLength > 0)
4418 pDirNode->NameInformation.ShortNameLength = pDirEnumEntry->ShortNameLength;
4420 RtlCopyMemory( pDirNode->NameInformation.ShortName,
4421 pDirEnumEntry->ShortName,
4422 pDirNode->NameInformation.ShortNameLength);
4425 AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4429 // Insert the node into the name tree
4432 ASSERT( ExIsResourceAcquiredExclusiveLite( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock));
4434 if( pDirHdr->CaseSensitiveTreeHead == NULL)
4437 pDirHdr->CaseSensitiveTreeHead = pDirNode;
4442 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( pDirHdr->CaseSensitiveTreeHead,
4446 AFSDeleteDirEntry( &AFSGlobalRoot->ObjectInformation,
4449 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4451 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4455 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
4457 if( pDirHdr->CaseInsensitiveTreeHead == NULL)
4460 pDirHdr->CaseInsensitiveTreeHead = pDirNode;
4462 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
4467 AFSInsertCaseInsensitiveDirEntry( pDirHdr->CaseInsensitiveTreeHead,
4471 if( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead == NULL)
4474 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead = pDirNode;
4479 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
4481 pDirNode->ListEntry.bLink = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail;
4484 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail = pDirNode;
4486 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
4488 lCount = InterlockedIncrement( &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeCount);
4490 AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
4491 AFS_TRACE_LEVEL_VERBOSE,
4492 "AFSCheckCellName Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
4493 &pDirNode->NameInformation.FileName,
4495 AFSGlobalRoot->ObjectInformation.FileId.Cell,
4496 AFSGlobalRoot->ObjectInformation.FileId.Volume,
4497 AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4498 AFSGlobalRoot->ObjectInformation.FileId.Unique));
4500 lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
4502 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4503 AFS_TRACE_LEVEL_VERBOSE,
4504 "AFSCheckCellName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
4505 &pDirNode->NameInformation.FileName,
4510 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4513 // Pass back the dir node
4516 *ShareDirEntry = pDirNode;
4521 if( pDirEnumEntry != NULL)
4524 AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_31_TAG);
4532 AFSBuildMountPointTarget( IN GUID *AuthGroup,
4533 IN AFSDirectoryCB *DirectoryCB,
4534 OUT AFSVolumeCB **TargetVolumeCB)
4537 NTSTATUS ntStatus = STATUS_SUCCESS;
4538 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4539 AFSDirEnumEntry *pDirEntry = NULL;
4540 ULONGLONG ullIndex = 0;
4541 AFSVolumeCB *pVolumeCB = NULL;
4542 AFSFileID stTargetFileID;
4544 BOOLEAN bReleaseVolumeLock = FALSE;
4550 // Loop on each entry, building the chain until we encounter the final target
4553 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4554 AFS_TRACE_LEVEL_VERBOSE_2,
4555 "AFSBuildMountPointTarget Building target directory for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4556 &DirectoryCB->NameInformation.FileName,
4557 DirectoryCB->ObjectInformation->FileId.Cell,
4558 DirectoryCB->ObjectInformation->FileId.Volume,
4559 DirectoryCB->ObjectInformation->FileId.Vnode,
4560 DirectoryCB->ObjectInformation->FileId.Unique));
4563 // Do we need to evaluate the node?
4566 //if( DirectoryCB->ObjectInformation->TargetFileId.Vnode == 0 &&
4567 // DirectoryCB->ObjectInformation->TargetFileId.Unique == 0)
4571 // Go evaluate the current target to get the target fid
4574 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4575 AFS_TRACE_LEVEL_VERBOSE_2,
4576 "AFSBuildMountPointTarget Evaluating target %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4577 &DirectoryCB->NameInformation.FileName,
4578 DirectoryCB->ObjectInformation->FileId.Cell,
4579 DirectoryCB->ObjectInformation->FileId.Volume,
4580 DirectoryCB->ObjectInformation->FileId.Vnode,
4581 DirectoryCB->ObjectInformation->FileId.Unique));
4583 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
4588 if( !NT_SUCCESS( ntStatus))
4591 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4592 AFS_TRACE_LEVEL_ERROR,
4593 "AFSBuildMountPointTarget Failed to evaluate target %wZ Status %08lX\n",
4594 &DirectoryCB->NameInformation.FileName,
4597 try_return( ntStatus);
4600 if( pDirEntry->TargetFileId.Vnode == 0 &&
4601 pDirEntry->TargetFileId.Unique == 0)
4604 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4605 AFS_TRACE_LEVEL_ERROR,
4606 "AFSBuildMountPointTarget Target %wZ FID %08lX-%08lX-%08lX-%08lX service returned zero FID\n",
4607 &DirectoryCB->NameInformation.FileName,
4608 DirectoryCB->ObjectInformation->FileId.Cell,
4609 DirectoryCB->ObjectInformation->FileId.Volume,
4610 DirectoryCB->ObjectInformation->FileId.Vnode,
4611 DirectoryCB->ObjectInformation->FileId.Unique));
4613 try_return( ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED);
4616 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
4619 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
4620 &DirectoryCB->Flags,
4621 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4622 (USHORT)pDirEntry->TargetNameLength);
4624 if( !NT_SUCCESS( ntStatus))
4627 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4629 try_return( ntStatus);
4632 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4634 DirectoryCB->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
4637 stTargetFileID = DirectoryCB->ObjectInformation->TargetFileId;
4640 // Try to locate this FID. First the volume then the
4644 ullIndex = AFSCreateHighIndex( &stTargetFileID);
4646 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4647 AFS_TRACE_LEVEL_VERBOSE,
4648 "AFSBuildMountPointTarget Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4649 &pDevExt->Specific.RDR.VolumeTreeLock,
4650 PsGetCurrentThread()));
4652 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4655 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4656 AFS_TRACE_LEVEL_VERBOSE_2,
4657 "AFSBuildMountPointTarget Locating volume for target %I64X\n",
4660 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4662 (AFSBTreeEntry **)&pVolumeCB);
4665 // We can be processing a request for a target that is on a volume
4666 // we have never seen before.
4669 if( pVolumeCB == NULL)
4673 // Locking is held correctly in init routine
4676 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4679 // Go init the root of the volume
4682 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4683 AFS_TRACE_LEVEL_VERBOSE_2,
4684 "AFSBuildMountPointTarget Initializing root for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4685 &DirectoryCB->NameInformation.FileName,
4686 DirectoryCB->ObjectInformation->FileId.Cell,
4687 DirectoryCB->ObjectInformation->FileId.Volume,
4688 DirectoryCB->ObjectInformation->FileId.Vnode,
4689 DirectoryCB->ObjectInformation->FileId.Unique));
4691 ntStatus = AFSInitVolume( AuthGroup,
4693 AFS_VOLUME_REFERENCE_MOUNTPT,
4696 if( !NT_SUCCESS( ntStatus))
4699 try_return( ntStatus);
4703 // pVolumeCB->VolumeLock held exclusive and
4704 // pVolumeCB->VolumeReferenceCount has been incremented
4705 // pVolumeCB->RootFcb == NULL
4708 bReleaseVolumeLock = TRUE;
4714 // AFSInitVolume returns with a VolumeReferenceCount
4715 // obtain one to match
4718 lCount = AFSVolumeIncrement( pVolumeCB,
4719 AFS_VOLUME_REFERENCE_MOUNTPT);
4721 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4722 AFS_TRACE_LEVEL_VERBOSE,
4723 "AFSBuildMountPointTarget Increment count on volume %p Cnt %d\n",
4727 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4730 if( pVolumeCB->RootFcb == NULL)
4733 if ( bReleaseVolumeLock == FALSE)
4736 AFSAcquireExcl( pVolumeCB->VolumeLock,
4739 bReleaseVolumeLock = TRUE;
4743 // Initialize the root fcb for this volume
4746 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4749 if( !NT_SUCCESS( ntStatus))
4752 lCount = AFSVolumeDecrement( pVolumeCB,
4753 AFS_VOLUME_REFERENCE_MOUNTPT);
4755 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4756 AFS_TRACE_LEVEL_VERBOSE,
4757 "AFSBuildMountPoint Decrement count on volume %p Cnt %d\n",
4761 AFSReleaseResource( pVolumeCB->VolumeLock);
4763 try_return( ntStatus);
4767 // Drop the lock acquired above
4770 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4773 if ( bReleaseVolumeLock == TRUE)
4776 AFSReleaseResource( pVolumeCB->VolumeLock);
4779 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4780 AFS_TRACE_LEVEL_VERBOSE_2,
4781 "AFSBuildMountPointTarget Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4782 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4783 pVolumeCB->ObjectInformation.FileId.Cell,
4784 pVolumeCB->ObjectInformation.FileId.Volume,
4785 pVolumeCB->ObjectInformation.FileId.Vnode,
4786 pVolumeCB->ObjectInformation.FileId.Unique));
4788 *TargetVolumeCB = pVolumeCB;
4795 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
4803 AFSBuildRootVolume( IN GUID *AuthGroup,
4804 IN AFSFileID *FileId,
4805 OUT AFSVolumeCB **TargetVolumeCB)
4808 NTSTATUS ntStatus = STATUS_SUCCESS;
4809 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4810 ULONGLONG ullIndex = 0;
4811 AFSVolumeCB *pVolumeCB = NULL;
4813 BOOLEAN bReleaseVolumeLock = FALSE;
4818 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4819 AFS_TRACE_LEVEL_VERBOSE_2,
4820 "AFSBuildRootVolume Building target volume for FID %08lX-%08lX-%08lX-%08lX\n",
4826 ullIndex = AFSCreateHighIndex( FileId);
4828 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4829 AFS_TRACE_LEVEL_VERBOSE,
4830 "AFSBuildRootVolume Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4831 &pDevExt->Specific.RDR.VolumeTreeLock,
4832 PsGetCurrentThread()));
4834 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4837 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4838 AFS_TRACE_LEVEL_VERBOSE_2,
4839 "AFSBuildRootVolume Locating volume for target %I64X\n",
4842 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4844 (AFSBTreeEntry **)&pVolumeCB);
4847 // We can be processing a request for a target that is on a volume
4848 // we have never seen before.
4851 if( pVolumeCB == NULL)
4855 // Locking is held correctly in init routine
4858 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4861 // Go init the root of the volume
4864 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4865 AFS_TRACE_LEVEL_VERBOSE_2,
4866 "AFSBuildRootVolume Initializing root for FID %08lX-%08lX-%08lX-%08lX\n",
4872 ntStatus = AFSInitVolume( AuthGroup,
4874 AFS_VOLUME_REFERENCE_BUILD_ROOT,
4877 if( !NT_SUCCESS( ntStatus))
4880 try_return( ntStatus);
4884 // pVolumeCB->VolumeLock is held exclusive
4885 // pVolumeCB->VolumeReferenceCount has been incremented
4886 // pVolumeCB->RootFcb == NULL
4889 bReleaseVolumeLock = TRUE;
4895 // AFSInitVolume returns with a VolumeReferenceCount
4896 // obtain one to match
4899 lCount = AFSVolumeIncrement( pVolumeCB,
4900 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4902 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4903 AFS_TRACE_LEVEL_VERBOSE,
4904 "AFSBuildRootVolume Increment count on volume %p Cnt %d\n",
4908 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4912 if( pVolumeCB->RootFcb == NULL)
4915 if ( bReleaseVolumeLock == FALSE)
4918 AFSAcquireExcl( pVolumeCB->VolumeLock,
4921 bReleaseVolumeLock = TRUE;
4925 // Initialize the root fcb for this volume
4928 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4931 if( !NT_SUCCESS( ntStatus))
4934 lCount = AFSVolumeDecrement( pVolumeCB,
4935 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4937 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4938 AFS_TRACE_LEVEL_VERBOSE,
4939 "AFSBuildRootVolume Decrement count on volume %p Cnt %d\n",
4943 AFSReleaseResource( pVolumeCB->VolumeLock);
4945 try_return( ntStatus);
4949 // Drop the lock acquired above
4952 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4955 if ( bReleaseVolumeLock == TRUE)
4958 AFSReleaseResource( pVolumeCB->VolumeLock);
4961 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4962 AFS_TRACE_LEVEL_VERBOSE_2,
4963 "AFSBuildRootVolume Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4964 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4965 pVolumeCB->ObjectInformation.FileId.Cell,
4966 pVolumeCB->ObjectInformation.FileId.Volume,
4967 pVolumeCB->ObjectInformation.FileId.Vnode,
4968 pVolumeCB->ObjectInformation.FileId.Unique));
4970 *TargetVolumeCB = pVolumeCB;
4981 AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
4982 IN PFILE_OBJECT FileObject,
4983 IN UNICODE_STRING *RemainingPath,
4987 NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
4988 UNICODE_STRING uniReparseName;
4989 UNICODE_STRING uniMUPDeviceName;
4990 UNICODE_STRING uniIOMgrDeviceName;
4991 AFSDirEnumEntry *pDirEntry = NULL;
4997 // Build up the name to reparse
5000 RtlInitUnicodeString( &uniMUPDeviceName,
5003 RtlInitUnicodeString( &uniIOMgrDeviceName,
5006 uniReparseName.Length = 0;
5007 uniReparseName.Buffer = NULL;
5010 // Be sure we have a target name
5013 if( DirEntry->NameInformation.TargetName.Length == 0)
5016 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
5021 if( !NT_SUCCESS( ntStatus) ||
5022 pDirEntry->TargetNameLength == 0)
5025 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5026 AFS_TRACE_LEVEL_ERROR,
5027 "AFSProcessDFSLink EvaluateTargetByID failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
5028 &DirEntry->NameInformation.FileName,
5029 DirEntry->ObjectInformation->FileId.Cell,
5030 DirEntry->ObjectInformation->FileId.Volume,
5031 DirEntry->ObjectInformation->FileId.Vnode,
5032 DirEntry->ObjectInformation->FileId.Unique,
5035 if( NT_SUCCESS( ntStatus))
5038 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
5041 try_return( ntStatus);
5045 // Update the target name
5048 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
5051 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
5053 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
5054 (USHORT)pDirEntry->TargetNameLength);
5056 if( !NT_SUCCESS( ntStatus))
5059 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5060 AFS_TRACE_LEVEL_ERROR,
5061 "AFSProcessDFSLink UpdateTargetName failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
5062 &DirEntry->NameInformation.FileName,
5063 DirEntry->ObjectInformation->FileId.Cell,
5064 DirEntry->ObjectInformation->FileId.Volume,
5065 DirEntry->ObjectInformation->FileId.Vnode,
5066 DirEntry->ObjectInformation->FileId.Unique,
5069 AFSReleaseResource( &DirEntry->NonPaged->Lock);
5071 try_return( ntStatus);
5074 AFSConvertToShared( &DirEntry->NonPaged->Lock);
5078 AFSAcquireShared( &DirEntry->NonPaged->Lock,
5082 uniReparseName.MaximumLength = uniMUPDeviceName.Length +
5084 DirEntry->NameInformation.TargetName.Length +
5087 if( RemainingPath != NULL &&
5088 RemainingPath->Length > 0)
5091 uniReparseName.MaximumLength += RemainingPath->Length;
5095 // Allocate the reparse buffer
5098 uniReparseName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5099 uniReparseName.MaximumLength,
5100 AFS_REPARSE_NAME_TAG);
5102 if( uniReparseName.Buffer == NULL)
5105 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5106 AFS_TRACE_LEVEL_ERROR,
5107 "AFSProcessDFSLink uniReparseName.Buffer == NULL Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
5108 &DirEntry->NameInformation.FileName,
5109 DirEntry->ObjectInformation->FileId.Cell,
5110 DirEntry->ObjectInformation->FileId.Volume,
5111 DirEntry->ObjectInformation->FileId.Vnode,
5112 DirEntry->ObjectInformation->FileId.Unique,
5113 STATUS_INSUFFICIENT_RESOURCES));
5115 AFSReleaseResource( &DirEntry->NonPaged->Lock);
5117 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5121 // Start building the name
5124 if ( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\' &&
5125 DirEntry->NameInformation.TargetName.Buffer[ 1] == L':')
5128 RtlCopyMemory( uniReparseName.Buffer,
5129 uniIOMgrDeviceName.Buffer,
5130 uniIOMgrDeviceName.Length);
5132 uniReparseName.Length = uniIOMgrDeviceName.Length;
5137 RtlCopyMemory( uniReparseName.Buffer,
5138 uniMUPDeviceName.Buffer,
5139 uniMUPDeviceName.Length);
5141 uniReparseName.Length = uniMUPDeviceName.Length;
5143 if( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\')
5146 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
5148 uniReparseName.Length += sizeof( WCHAR);
5152 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
5153 DirEntry->NameInformation.TargetName.Buffer,
5154 DirEntry->NameInformation.TargetName.Length);
5156 uniReparseName.Length += DirEntry->NameInformation.TargetName.Length;
5158 AFSReleaseResource( &DirEntry->NonPaged->Lock);
5160 if( RemainingPath != NULL &&
5161 RemainingPath->Length > 0)
5164 if( uniReparseName.Buffer[ (uniReparseName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
5165 RemainingPath->Buffer[ 0] != L'\\')
5168 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
5170 uniReparseName.Length += sizeof( WCHAR);
5173 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
5174 RemainingPath->Buffer,
5175 RemainingPath->Length);
5177 uniReparseName.Length += RemainingPath->Length;
5181 // Update the name in the file object
5184 if( FileObject->FileName.Buffer != NULL)
5187 AFSExFreePoolWithTag( FileObject->FileName.Buffer, 0);
5190 FileObject->FileName = uniReparseName;
5192 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5193 AFS_TRACE_LEVEL_VERBOSE,
5194 "AFSProcessDFSLink Reparsing access to Fcb %wZ FID %08lX-%08lX-%08lX-%08lX to %wZ\n",
5195 &DirEntry->NameInformation.FileName,
5196 DirEntry->ObjectInformation->FileId.Cell,
5197 DirEntry->ObjectInformation->FileId.Volume,
5198 DirEntry->ObjectInformation->FileId.Vnode,
5199 DirEntry->ObjectInformation->FileId.Unique,
5203 // Return status reparse ...
5206 ntStatus = STATUS_REPARSE;
5213 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);