2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSNameSupport.cpp
39 #include "AFSCommon.h"
44 // On entry, *VolumeCB must have a held ReferenceCount provided by
45 // the caller which will not be released. On successful exit, *OutVolumeCB
46 // will be assigned the new current volume with a held ReferenceCount.
48 // On entry, *ParentDirectoryCB must have a held DirOpenReferenceCount
49 // provided by the caller. This reference will not be released.
50 // On exit, if OutParentDirectoryCB is set, it will have a new reference.
52 // On exit, if OutDirectoryCB is set, it will have a reference.
56 AFSLocateNameEntry( IN GUID *AuthGroup,
57 IN PFILE_OBJECT FileObject,
58 IN OUT UNICODE_STRING *RootPathName,
59 IN UNICODE_STRING *ParsedPathName,
60 IN AFSNameArrayHdr *NameArray,
62 IN AFSVolumeCB *VolumeCB,
63 IN AFSDirectoryCB *ParentDirectoryCB,
64 OUT AFSVolumeCB **OutVolumeCB,
65 OUT LONG *OutVolumeReferenceReason,
66 OUT AFSDirectoryCB **OutParentDirectoryCB,
67 OUT AFSDirectoryCB **OutDirectoryCB,
68 OUT PUNICODE_STRING ComponentName)
71 NTSTATUS ntStatus = STATUS_SUCCESS;
72 UNICODE_STRING uniPathName, uniComponentName, uniRemainingPath, uniSearchName, uniFullPathName;
74 AFSDirectoryCB *pDirEntry = NULL, *pParentDirEntry = NULL;
75 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
76 UNICODE_STRING uniSysName;
77 ULONG ulSubstituteIndex = 0;
78 BOOLEAN bSubstituteName = FALSE;
79 AFSNameArrayHdr *pNameArray = NameArray;
80 BOOLEAN bAllocatedSymLinkBuffer = FALSE;
81 UNICODE_STRING uniRelativeName, uniNoOpName;
82 AFSObjectInfoCB *pCurrentObject = NULL;
83 AFSObjectInfoCB *pParentObjectInfo = NULL;
84 AFSVolumeCB *pCurrentVolume = NULL;
85 AFSVolumeCB *pTargetVolume = NULL;
86 BOOLEAN bReleaseCurrentVolume = FALSE;
87 LONG VolumeReferenceReason;
88 BOOLEAN bSubstitutedName = FALSE;
94 ASSERT( *OutVolumeCB != VolumeCB);
96 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
97 AFS_TRACE_LEVEL_VERBOSE_2,
98 "AFSLocateNameEntry (FO: %p) Processing full name %wZ\n",
102 RtlInitUnicodeString( &uniSysName,
105 RtlInitUnicodeString( &uniRelativeName,
108 RtlInitUnicodeString( &uniNoOpName,
112 // Cleanup some parameters
115 if( ComponentName != NULL)
118 ComponentName->Length = 0;
119 ComponentName->MaximumLength = 0;
120 ComponentName->Buffer = NULL;
124 // We will parse through the filename, locating the directory nodes until we encounter a cache miss
125 // Starting at the root node
128 pParentDirEntry = NULL;
130 pDirEntry = ParentDirectoryCB;
133 // Increment our reference on this dir entry
136 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
138 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
139 AFS_TRACE_LEVEL_VERBOSE,
140 "AFSLocateNameEntry Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
141 &pDirEntry->NameInformation.FileName,
146 pCurrentVolume = VolumeCB;
148 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
150 lCount = AFSVolumeIncrement( pCurrentVolume,
151 VolumeReferenceReason);
153 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
154 AFS_TRACE_LEVEL_VERBOSE,
155 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
157 VolumeReferenceReason,
160 bReleaseCurrentVolume = TRUE;
162 uniPathName = *ParsedPathName;
164 uniFullPathName = *RootPathName;
166 uniComponentName.Length = uniComponentName.MaximumLength = 0;
167 uniComponentName.Buffer = NULL;
169 uniRemainingPath.Length = uniRemainingPath.MaximumLength = 0;
170 uniRemainingPath.Buffer = NULL;
172 uniSearchName.Length = uniSearchName.MaximumLength = 0;
173 uniSearchName.Buffer = NULL;
178 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
180 ASSERT( pDirEntry->DirOpenReferenceCount > 0);
183 // Check our total link count for this name array
186 if( pNameArray->LinkCount >= (LONG)pDevExt->Specific.RDR.MaxLinkCount)
189 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
192 pCurrentObject = pDirEntry->ObjectInformation;
194 KeQueryTickCount( &pCurrentObject->LastAccessCount);
197 // Check that the directory entry is not deleted or pending delete
200 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
203 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
204 AFS_TRACE_LEVEL_ERROR,
205 "AFSLocateNameEntry (FO: %p) Deleted parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
207 &pDirEntry->NameInformation.FileName,
208 pCurrentObject->FileId.Cell,
209 pCurrentObject->FileId.Volume,
210 pCurrentObject->FileId.Vnode,
211 pCurrentObject->FileId.Unique,
212 STATUS_FILE_DELETED));
214 try_return( ntStatus = STATUS_FILE_DELETED);
217 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
220 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
221 AFS_TRACE_LEVEL_ERROR,
222 "AFSLocateNameEntry (FO: %p) Delete pending on %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
224 &pDirEntry->NameInformation.FileName,
225 pCurrentObject->FileId.Cell,
226 pCurrentObject->FileId.Volume,
227 pCurrentObject->FileId.Vnode,
228 pCurrentObject->FileId.Unique,
229 STATUS_DELETE_PENDING));
231 try_return( ntStatus = STATUS_DELETE_PENDING);
235 // Check if the directory requires verification
238 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
239 ( pCurrentObject->FileType != AFS_FILE_TYPE_DIRECTORY ||
240 !AFSIsEnumerationInProcess( pCurrentObject)))
243 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
244 AFS_TRACE_LEVEL_VERBOSE,
245 "AFSLocateNameEntry (FO: %p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
247 &pDirEntry->NameInformation.FileName,
248 pCurrentObject->FileId.Cell,
249 pCurrentObject->FileId.Volume,
250 pCurrentObject->FileId.Vnode,
251 pCurrentObject->FileId.Unique));
254 // Directory TreeLock should be exclusively held
257 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
260 ntStatus = AFSVerifyEntry( AuthGroup,
263 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
265 if( !NT_SUCCESS( ntStatus))
268 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
269 AFS_TRACE_LEVEL_ERROR,
270 "AFSLocateNameEntry (FO: %p) Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
272 &pDirEntry->NameInformation.FileName,
273 pCurrentObject->FileId.Cell,
274 pCurrentObject->FileId.Volume,
275 pCurrentObject->FileId.Vnode,
276 pCurrentObject->FileId.Unique,
279 try_return( ntStatus);
284 // Ensure the parent node has been evaluated, if not then go do it now
287 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) ||
288 pCurrentObject->FileType == AFS_FILE_TYPE_UNKNOWN)
291 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
292 AFS_TRACE_LEVEL_VERBOSE,
293 "AFSLocateNameEntry (FO: %p) Evaluating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
295 &pDirEntry->NameInformation.FileName,
296 pCurrentObject->FileId.Cell,
297 pCurrentObject->FileId.Volume,
298 pCurrentObject->FileId.Vnode,
299 pCurrentObject->FileId.Unique));
301 ntStatus = AFSEvaluateNode( AuthGroup,
304 if( !NT_SUCCESS( ntStatus))
307 if ( ntStatus == STATUS_NOT_A_DIRECTORY)
310 if ( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
313 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
314 AFS_TRACE_LEVEL_ERROR,
315 "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT NULL Status %08lX\n",
317 &pDirEntry->NameInformation.FileName,
318 pCurrentObject->FileId.Cell,
319 pCurrentObject->FileId.Volume,
320 pCurrentObject->FileId.Vnode,
321 pCurrentObject->FileId.Unique,
327 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
328 AFS_TRACE_LEVEL_ERROR,
329 "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT %08lX-%08lX-%08lX-%08lX Status %08lX\n",
331 &pDirEntry->NameInformation.FileName,
332 pCurrentObject->FileId.Cell,
333 pCurrentObject->FileId.Volume,
334 pCurrentObject->FileId.Vnode,
335 pCurrentObject->FileId.Unique,
336 pCurrentObject->ParentFileId.Cell,
337 pCurrentObject->ParentFileId.Volume,
338 pCurrentObject->ParentFileId.Vnode,
339 pCurrentObject->ParentFileId.Unique,
345 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
346 AFS_TRACE_LEVEL_ERROR,
347 "AFSLocateNameEntry (FO: %p) Failed to evaluate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
349 &pDirEntry->NameInformation.FileName,
350 pCurrentObject->FileId.Cell,
351 pCurrentObject->FileId.Volume,
352 pCurrentObject->FileId.Vnode,
353 pCurrentObject->FileId.Unique,
357 try_return( ntStatus);
360 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
364 // If this is a mount point or symlink then go get the real directory node
367 switch( pCurrentObject->FileType)
370 case AFS_FILE_TYPE_SYMLINK:
373 UNICODE_STRING uniTempName;
374 WCHAR *pTmpBuffer = NULL;
378 // Check if the flag is set to NOT evaluate a symlink
379 // and we are done with the parsing
382 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL) &&
383 uniRemainingPath.Length == 0)
387 // Pass back the directory entries
390 *OutParentDirectoryCB = pParentDirEntry;
392 pParentDirEntry = NULL;
394 *OutDirectoryCB = pDirEntry;
398 *OutVolumeCB = pCurrentVolume;
400 *OutVolumeReferenceReason = VolumeReferenceReason;
402 bReleaseCurrentVolume = FALSE;
404 *RootPathName = uniFullPathName;
406 try_return( ntStatus);
409 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
412 AFSAcquireExcl( &pDirEntry->NonPaged->Lock,
415 if( pDirEntry->NameInformation.TargetName.Length == 0)
419 // We'll reset the DV to ensure we validate the metadata content
422 pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
424 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
426 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
427 AFS_TRACE_LEVEL_VERBOSE,
428 "AFSLocateNameEntry (FO: %p) Verifying symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
430 &pDirEntry->NameInformation.FileName,
431 pCurrentObject->FileId.Cell,
432 pCurrentObject->FileId.Volume,
433 pCurrentObject->FileId.Vnode,
434 pCurrentObject->FileId.Unique));
437 // Directory TreeLock should be exclusively held
440 ntStatus = AFSVerifyEntry( AuthGroup,
443 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
445 if( !NT_SUCCESS( ntStatus))
448 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
449 AFS_TRACE_LEVEL_ERROR,
450 "AFSLocateNameEntry (FO: %p) Failed to verify symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
452 &pDirEntry->NameInformation.FileName,
453 pCurrentObject->FileId.Cell,
454 pCurrentObject->FileId.Volume,
455 pCurrentObject->FileId.Vnode,
456 pCurrentObject->FileId.Unique,
459 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
461 try_return( ntStatus);
465 // If the type changed then reprocess this entry
468 if( pCurrentObject->FileType != AFS_FILE_TYPE_SYMLINK)
471 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
479 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
483 // If we were given a zero length target name then deny access to the entry
486 if( pDirEntry->NameInformation.TargetName.Length == 0)
489 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
491 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
492 AFS_TRACE_LEVEL_ERROR,
493 "AFSLocateNameEntry (FO: %p) Failed to retrieve target name for symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
495 &pDirEntry->NameInformation.FileName,
496 pCurrentObject->FileId.Cell,
497 pCurrentObject->FileId.Volume,
498 pCurrentObject->FileId.Vnode,
499 pCurrentObject->FileId.Unique,
502 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
504 try_return( ntStatus);
507 if( AFSIsRelativeName( &pDirEntry->NameInformation.TargetName))
510 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
511 AFS_TRACE_LEVEL_VERBOSE,
512 "AFSLocateNameEntry (FO: %p) Processing relative symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
514 &pDirEntry->NameInformation.TargetName,
515 &pDirEntry->NameInformation.FileName,
516 pCurrentObject->FileId.Cell,
517 pCurrentObject->FileId.Volume,
518 pCurrentObject->FileId.Vnode,
519 pCurrentObject->FileId.Unique));
522 // We'll substitute this name into the current process name
523 // starting at where we sit in the path
526 uniTempName.Length = 0;
527 uniTempName.MaximumLength = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer) +
528 pDirEntry->NameInformation.TargetName.Length +
530 uniRemainingPath.Length;
532 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
533 uniTempName.MaximumLength,
534 AFS_NAME_BUFFER_ONE_TAG);
536 if( uniTempName.Buffer == NULL)
539 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
541 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
545 // We have so first copy in the portion up to the component
549 RtlCopyMemory( uniTempName.Buffer,
550 uniFullPathName.Buffer,
551 (ULONG)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer));
553 uniTempName.Length = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer);
555 if( bAllocatedSymLinkBuffer ||
559 pTmpBuffer = uniFullPathName.Buffer;
562 bAllocatedSymLinkBuffer = TRUE;
565 // Have we parsed this name yet? Better have at least once ...
568 if( uniComponentName.Length == 0)
574 // Copy in the target name ...
577 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
578 pDirEntry->NameInformation.TargetName.Buffer,
579 pDirEntry->NameInformation.TargetName.Length);
581 uniPathName.Buffer = &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)];
583 uniPathName.Length += pDirEntry->NameInformation.TargetName.Length;
584 uniPathName.MaximumLength = uniTempName.MaximumLength;
586 uniTempName.Length += pDirEntry->NameInformation.TargetName.Length;
589 // And now any remaining portion of the name
592 if( uniRemainingPath.Length > 0)
595 if( uniRemainingPath.Buffer[ 0] != L'\\')
598 uniRemainingPath.Buffer--;
599 uniRemainingPath.Length += sizeof( WCHAR);
601 uniPathName.Length += sizeof( WCHAR);
604 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
605 uniRemainingPath.Buffer,
606 uniRemainingPath.Length);
608 uniTempName.Length += uniRemainingPath.Length;
611 uniFullPathName = uniTempName;
613 if( pTmpBuffer != NULL)
616 AFSExFreePoolWithTag( pTmpBuffer, 0);
619 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
622 // Dereference the current entry ..
625 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
627 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
628 AFS_TRACE_LEVEL_VERBOSE,
629 "AFSLocateNameEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
630 &pDirEntry->NameInformation.FileName,
635 ASSERT( lCount >= 0);
638 // OK, need to back up one entry for the correct parent since the current
639 // entry we are on is the symlink itself
642 pDirEntry = AFSBackupEntry( pNameArray);
644 pCurrentObject = pDirEntry->ObjectInformation;
647 // Increment our reference on this dir entry
650 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
652 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
653 AFS_TRACE_LEVEL_VERBOSE,
654 "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
655 &pDirEntry->NameInformation.FileName,
660 if ( pParentDirEntry)
663 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
665 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
666 AFS_TRACE_LEVEL_VERBOSE,
667 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
668 &pParentDirEntry->NameInformation.FileName,
673 pParentDirEntry = NULL;
676 if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
679 pParentDirEntry = AFSGetParentEntry( pNameArray);
681 ASSERT( pParentDirEntry != pDirEntry);
683 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
685 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
686 AFS_TRACE_LEVEL_VERBOSE,
687 "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
688 &pParentDirEntry->NameInformation.FileName,
694 if ( pDirEntry->ObjectInformation->VolumeCB != pCurrentVolume)
697 lCount = AFSVolumeDecrement( pCurrentVolume,
698 VolumeReferenceReason);
700 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
701 AFS_TRACE_LEVEL_VERBOSE,
702 "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
704 VolumeReferenceReason,
707 pCurrentVolume = pDirEntry->ObjectInformation->VolumeCB;
709 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
711 lCount = AFSVolumeIncrement( pCurrentVolume,
712 VolumeReferenceReason);
714 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
715 AFS_TRACE_LEVEL_VERBOSE,
716 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
718 VolumeReferenceReason,
725 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
726 AFS_TRACE_LEVEL_VERBOSE,
727 "AFSLocateNameEntry (FO: %p) Processing absolute symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
729 &pDirEntry->NameInformation.TargetName,
730 &pDirEntry->NameInformation.FileName,
731 pCurrentObject->FileId.Cell,
732 pCurrentObject->FileId.Volume,
733 pCurrentObject->FileId.Vnode,
734 pCurrentObject->FileId.Unique));
736 if ( !AFSIsAbsoluteAFSName( &pDirEntry->NameInformation.TargetName))
739 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
740 AFS_TRACE_LEVEL_ERROR,
741 "AFSLocateNameEntry Name %wZ contains invalid server name\n",
742 &pDirEntry->NameInformation.TargetName));
745 // The correct response would be STATUS_OBJECT_PATH_INVALID
746 // but that prevents cmd.exe from performing a recursive
747 // directory enumeration when opening a directory entry
748 // that represents a symlink to an invalid path is discovered.
751 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
753 try_return( ntStatus = STATUS_OBJECT_PATH_NOT_FOUND);
757 // We'll substitute this name into the current process name
758 // starting at where we sit in the path
761 uniTempName.Length = 0;
762 uniTempName.MaximumLength = pDirEntry->NameInformation.TargetName.Length +
764 uniRemainingPath.Length;
766 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
767 uniTempName.MaximumLength,
768 AFS_NAME_BUFFER_TWO_TAG);
770 if( uniTempName.Buffer == NULL)
773 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
775 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
778 if( bAllocatedSymLinkBuffer ||
782 pTmpBuffer = uniFullPathName.Buffer;
785 bAllocatedSymLinkBuffer = TRUE;
788 // Have we parsed this name yet? Better have at least once ...
791 if( uniComponentName.Length == 0)
797 // Copy in the target name ...
800 RtlCopyMemory( uniTempName.Buffer,
801 &pDirEntry->NameInformation.TargetName.Buffer[ AFSMountRootName.Length/sizeof( WCHAR)],
802 pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length);
804 uniTempName.Length = pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length;
807 // And now any remaining portion of the name
810 if( uniRemainingPath.Length > 0)
813 if( uniRemainingPath.Buffer[ 0] != L'\\')
816 uniRemainingPath.Buffer--;
817 uniRemainingPath.Length += sizeof( WCHAR);
820 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
821 uniRemainingPath.Buffer,
822 uniRemainingPath.Length);
824 uniTempName.Length += uniRemainingPath.Length;
827 uniFullPathName = uniTempName;
829 uniPathName = uniTempName;
831 if( pTmpBuffer != NULL)
834 AFSExFreePoolWithTag( pTmpBuffer, 0);
837 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
840 // If our current volume is not the global root then make it so ...
843 if( pCurrentVolume != AFSGlobalRoot)
846 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
847 AFS_TRACE_LEVEL_VERBOSE,
848 "AFSLocateNameEntry (FO: %p) Current volume not global, resetting for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
850 &pDirEntry->NameInformation.FileName,
851 pCurrentObject->FileId.Cell,
852 pCurrentObject->FileId.Volume,
853 pCurrentObject->FileId.Vnode,
854 pCurrentObject->FileId.Unique));
856 lCount = AFSVolumeDecrement( pCurrentVolume,
857 VolumeReferenceReason);
859 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
860 AFS_TRACE_LEVEL_VERBOSE,
861 "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
863 VolumeReferenceReason,
866 pCurrentVolume = AFSGlobalRoot;
868 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
870 lCount = AFSVolumeIncrement( pCurrentVolume,
871 VolumeReferenceReason);
873 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
874 AFS_TRACE_LEVEL_VERBOSE,
875 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
877 VolumeReferenceReason,
882 // Dereference our current dir entry
885 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
887 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
888 AFS_TRACE_LEVEL_VERBOSE,
889 "AFSLocateNameEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
890 &pDirEntry->NameInformation.FileName,
895 ASSERT( lCount >= 0);
897 pDirEntry = pCurrentVolume->DirectoryCB;
899 pCurrentObject = pDirEntry->ObjectInformation;
902 // Reference the new dir entry
905 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
907 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
908 AFS_TRACE_LEVEL_VERBOSE,
909 "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
910 &pDirEntry->NameInformation.FileName,
916 // Reset the name array
917 // Persist the link count in the name array
920 lLinkCount = pNameArray->LinkCount;
922 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
923 AFS_TRACE_LEVEL_VERBOSE,
924 "AFSLocateNameEntry (FO: %p) Resetting name array for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
926 &pDirEntry->NameInformation.FileName,
927 pCurrentObject->FileId.Cell,
928 pCurrentObject->FileId.Volume,
929 pCurrentObject->FileId.Vnode,
930 pCurrentObject->FileId.Unique));
932 AFSResetNameArray( pNameArray,
935 pNameArray->LinkCount = lLinkCount;
937 if ( pParentDirEntry)
940 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
942 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
943 AFS_TRACE_LEVEL_VERBOSE,
944 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
945 &pParentDirEntry->NameInformation.FileName,
950 pParentDirEntry = NULL;
955 // Increment our link count
958 lCount = InterlockedIncrement( &pNameArray->LinkCount);
963 case AFS_FILE_TYPE_MOUNTPOINT:
967 // Check if the flag is set to NOT evaluate a mount point
968 // and we are done with the parsing
971 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL) &&
972 uniRemainingPath.Length == 0)
976 // Pass back the directory entries
979 *OutParentDirectoryCB = pParentDirEntry;
981 pParentDirEntry = NULL;
983 *OutDirectoryCB = pDirEntry;
987 *OutVolumeCB = pCurrentVolume;
989 *OutVolumeReferenceReason = VolumeReferenceReason;
991 bReleaseCurrentVolume = FALSE;
993 *RootPathName = uniFullPathName;
995 try_return( ntStatus);
998 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
999 AFS_TRACE_LEVEL_VERBOSE,
1000 "AFSLocateNameEntry (FO: %p) Building MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1002 &pDirEntry->NameInformation.FileName,
1003 pCurrentObject->FileId.Cell,
1004 pCurrentObject->FileId.Volume,
1005 pCurrentObject->FileId.Vnode,
1006 pCurrentObject->FileId.Unique));
1009 // Go retrieve the target entry for this node
1010 // Release the current volume cb entry since we would
1011 // have lock inversion in the following call
1012 // Also decrement the ref count on the volume
1015 ntStatus = AFSBuildMountPointTarget( AuthGroup,
1019 if( !NT_SUCCESS( ntStatus))
1022 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1023 AFS_TRACE_LEVEL_ERROR,
1024 "AFSLocateNameEntry (FO: %p) Failed to build MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1026 &pDirEntry->NameInformation.FileName,
1027 pCurrentObject->FileId.Cell,
1028 pCurrentObject->FileId.Volume,
1029 pCurrentObject->FileId.Vnode,
1030 pCurrentObject->FileId.Unique,
1033 try_return( ntStatus);
1036 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
1038 lCount = AFSVolumeDecrement( pCurrentVolume,
1039 VolumeReferenceReason);
1041 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1042 AFS_TRACE_LEVEL_VERBOSE,
1043 "AFSLocateNameEntry Decrement2 count on volume %p Reason %u Cnt %d\n",
1045 VolumeReferenceReason,
1048 pCurrentVolume = pTargetVolume;
1050 pTargetVolume = NULL;
1052 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
1054 VolumeReferenceReason = AFS_VOLUME_REFERENCE_MOUNTPT;
1057 // We want to restart processing here on the new parent ...
1058 // Deref and ref count the entries
1061 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1063 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1064 AFS_TRACE_LEVEL_VERBOSE,
1065 "AFSLocateNameEntry Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
1066 &pDirEntry->NameInformation.FileName,
1071 ASSERT( lCount >= 0);
1073 pDirEntry = pCurrentVolume->DirectoryCB;
1075 pCurrentObject = pDirEntry->ObjectInformation;
1077 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1079 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1080 AFS_TRACE_LEVEL_VERBOSE,
1081 "AFSLocateNameEntry Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
1082 &pDirEntry->NameInformation.FileName,
1088 // The name array stores both the mount point and the target.
1089 // Insert the target.
1092 AFSInsertNextElement( pNameArray,
1095 if ( pParentDirEntry)
1098 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1100 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1101 AFS_TRACE_LEVEL_VERBOSE,
1102 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1103 &pParentDirEntry->NameInformation.FileName,
1108 pParentDirEntry = NULL;
1112 // Increment our link count
1115 lCount = InterlockedIncrement( &pNameArray->LinkCount);
1120 case AFS_FILE_TYPE_DFSLINK:
1123 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL))
1127 // Pass back the directory entries
1130 *OutParentDirectoryCB = pParentDirEntry;
1132 pParentDirEntry = NULL;
1134 *OutDirectoryCB = pDirEntry;
1138 *OutVolumeCB = pCurrentVolume;
1140 *OutVolumeReferenceReason = VolumeReferenceReason;
1142 bReleaseCurrentVolume = FALSE;
1144 *RootPathName = uniFullPathName;
1146 try_return( ntStatus);
1150 // This is a DFS link so we need to update the file name and return STATUS_REPARSE to the
1151 // system for it to reevaluate it
1154 if( FileObject != NULL)
1157 ntStatus = AFSProcessDFSLink( pDirEntry,
1166 // This is where we have been re-entered from an NP evaluation call via the BuildBranch()
1170 ntStatus = STATUS_INVALID_PARAMETER;
1173 if( ntStatus != STATUS_SUCCESS &&
1174 ntStatus != STATUS_REPARSE)
1177 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1178 AFS_TRACE_LEVEL_ERROR,
1179 "AFSLocateNameEntry (FO: %p) Failed to process DFSLink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1181 &pDirEntry->NameInformation.FileName,
1182 pCurrentObject->FileId.Cell,
1183 pCurrentObject->FileId.Volume,
1184 pCurrentObject->FileId.Vnode,
1185 pCurrentObject->FileId.Unique,
1189 try_return( ntStatus);
1192 case AFS_FILE_TYPE_UNKNOWN:
1193 case AFS_FILE_TYPE_INVALID:
1197 // Something was not processed ...
1200 try_return( ntStatus = STATUS_ACCESS_DENIED);
1203 } /* end of switch */
1206 // If the parent is not initialized then do it now
1209 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1210 !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED) &&
1211 uniPathName.Length > 0)
1214 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1215 AFS_TRACE_LEVEL_VERBOSE,
1216 "AFSLocateNameEntry (FO: %p) Enumerating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1218 &pDirEntry->NameInformation.FileName,
1219 pCurrentObject->FileId.Cell,
1220 pCurrentObject->FileId.Volume,
1221 pCurrentObject->FileId.Vnode,
1222 pCurrentObject->FileId.Unique));
1224 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1227 if( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1230 ntStatus = AFSEnumerateDirectory( AuthGroup,
1234 if( !NT_SUCCESS( ntStatus))
1237 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1239 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1240 AFS_TRACE_LEVEL_ERROR,
1241 "AFSLocateNameEntry (FO: %p) Failed to enumerate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1243 &pDirEntry->NameInformation.FileName,
1244 pCurrentObject->FileId.Cell,
1245 pCurrentObject->FileId.Volume,
1246 pCurrentObject->FileId.Vnode,
1247 pCurrentObject->FileId.Unique,
1250 try_return( ntStatus);
1254 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1256 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1259 if( uniPathName.Length > 0)
1262 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1263 AFS_TRACE_LEVEL_ERROR,
1264 "AFSLocateNameEntry (FO: %p) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1266 &pDirEntry->NameInformation.FileName,
1267 pCurrentObject->FileId.Cell,
1268 pCurrentObject->FileId.Volume,
1269 pCurrentObject->FileId.Vnode,
1270 pCurrentObject->FileId.Unique));
1272 // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1273 // one of the components of the path is not a directory. However, returning
1274 // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1275 // Instead IIS insists on treating the target file as if it is a directory containing
1276 // a potential web.config file. NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1277 // AFS will follow suit.
1279 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1284 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1285 AFS_TRACE_LEVEL_VERBOSE,
1286 "AFSLocateNameEntry (FO: %p) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1288 &pDirEntry->NameInformation.FileName,
1289 pCurrentObject->FileId.Cell,
1290 pCurrentObject->FileId.Volume,
1291 pCurrentObject->FileId.Vnode,
1292 pCurrentObject->FileId.Unique));
1295 // Pass back the directory entries
1298 *OutParentDirectoryCB = pParentDirEntry;
1300 pParentDirEntry = NULL;
1302 *OutDirectoryCB = pDirEntry;
1306 *OutVolumeCB = pCurrentVolume;
1308 *OutVolumeReferenceReason = VolumeReferenceReason;
1310 bReleaseCurrentVolume = FALSE;
1312 *RootPathName = uniFullPathName;
1315 try_return( ntStatus);
1319 // If we are at the end of the processing, set our returned information and get out
1322 if( uniPathName.Length == 0)
1325 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1326 AFS_TRACE_LEVEL_VERBOSE,
1327 "AFSLocateNameEntry (FO: %p) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1329 &pDirEntry->NameInformation.FileName,
1330 pCurrentObject->FileId.Cell,
1331 pCurrentObject->FileId.Volume,
1332 pCurrentObject->FileId.Vnode,
1333 pCurrentObject->FileId.Unique));
1336 // Pass back the directory entries
1339 *OutParentDirectoryCB = pParentDirEntry;
1341 pParentDirEntry = NULL;
1343 *OutDirectoryCB = pDirEntry;
1347 *OutVolumeCB = pCurrentVolume;
1349 *OutVolumeReferenceReason = VolumeReferenceReason;
1351 bReleaseCurrentVolume = FALSE;
1353 *RootPathName = uniFullPathName;
1355 try_return( ntStatus);
1359 // We may have returned to the top of the while( TRUE)
1361 if( bSubstituteName &&
1362 uniSearchName.Buffer != NULL)
1365 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1367 bSubstituteName = FALSE;
1369 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1370 uniSearchName.Buffer = NULL;
1373 ulSubstituteIndex = 1;
1375 ntStatus = STATUS_SUCCESS;
1378 // Get the next component name
1381 FsRtlDissectName( uniPathName,
1386 // Check for the . and .. in the path
1389 if( RtlCompareUnicodeString( &uniComponentName,
1394 uniPathName = uniRemainingPath;
1399 if( RtlCompareUnicodeString( &uniComponentName,
1404 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1405 AFS_TRACE_LEVEL_VERBOSE,
1406 "AFSLocateNameEntry (FO: %p) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1408 &pDirEntry->NameInformation.FileName,
1409 pCurrentObject->FileId.Cell,
1410 pCurrentObject->FileId.Volume,
1411 pCurrentObject->FileId.Vnode,
1412 pCurrentObject->FileId.Unique));
1415 // Need to back up one entry in the name array
1417 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1419 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1420 AFS_TRACE_LEVEL_VERBOSE,
1421 "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1422 &pDirEntry->NameInformation.FileName,
1427 ASSERT( lCount >= 0);
1429 pDirEntry = AFSBackupEntry( NameArray);
1431 if( pDirEntry == NULL)
1434 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1435 AFS_TRACE_LEVEL_ERROR,
1436 "AFSLocateNameEntry AFSBackupEntry failed\n"));
1438 try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1441 pCurrentObject = pDirEntry->ObjectInformation;
1443 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1445 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1446 AFS_TRACE_LEVEL_VERBOSE,
1447 "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1448 &pDirEntry->NameInformation.FileName,
1453 if ( pParentDirEntry)
1456 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1458 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1459 AFS_TRACE_LEVEL_VERBOSE,
1460 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1461 &pParentDirEntry->NameInformation.FileName,
1466 pParentDirEntry = NULL;
1469 if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1472 pParentDirEntry = AFSGetParentEntry( pNameArray);
1474 ASSERT( pParentDirEntry != pDirEntry);
1476 if ( pParentDirEntry)
1479 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
1481 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1482 AFS_TRACE_LEVEL_VERBOSE,
1483 "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
1484 &pParentDirEntry->NameInformation.FileName,
1491 if ( pDirEntry->ObjectInformation->VolumeCB != pCurrentVolume)
1494 lCount = AFSVolumeDecrement( pCurrentVolume,
1495 VolumeReferenceReason);
1497 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1498 AFS_TRACE_LEVEL_VERBOSE,
1499 "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
1501 VolumeReferenceReason,
1504 pCurrentVolume = pDirEntry->ObjectInformation->VolumeCB;
1506 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
1508 lCount = AFSVolumeIncrement( pCurrentVolume,
1509 VolumeReferenceReason);
1511 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1512 AFS_TRACE_LEVEL_VERBOSE,
1513 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
1515 VolumeReferenceReason,
1519 uniPathName = uniRemainingPath;
1525 // Update our pointers
1528 if ( pParentDirEntry)
1531 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1533 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1534 AFS_TRACE_LEVEL_VERBOSE,
1535 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1536 &pParentDirEntry->NameInformation.FileName,
1542 pParentDirEntry = pDirEntry;
1546 pCurrentObject = NULL;
1548 uniSearchName = uniComponentName;
1550 while( pDirEntry == NULL)
1554 // If the SearchName contains @SYS then we perform the substitution.
1555 // If there is no substitution we give up.
1558 if( !bSubstituteName &&
1559 FsRtlIsNameInExpression( &uniSysName,
1565 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1566 AFS_TRACE_LEVEL_VERBOSE_2,
1567 "AFSLocateNameEntry (FO: %p) Processing @SYS substitution for %wZ Index %08lX\n",
1570 ulSubstituteIndex));
1572 ntStatus = AFSSubstituteSysName( &uniComponentName,
1576 if ( NT_SUCCESS( ntStatus))
1579 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1580 AFS_TRACE_LEVEL_VERBOSE_2,
1581 "AFSLocateNameEntry (FO: %p) Located substitution %wZ for %wZ Index %08lX\n",
1585 ulSubstituteIndex));
1588 // Go reparse the name again
1591 bSubstituteName = TRUE;
1593 ulSubstituteIndex++; // For the next entry, if needed
1595 continue; // while( pDirEntry == NULL)
1600 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1601 AFS_TRACE_LEVEL_ERROR,
1602 "AFSLocateNameEntry (FO: %p) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1608 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1612 // Pass back the directory entries
1615 *OutParentDirectoryCB = pParentDirEntry;
1617 pParentDirEntry = NULL;
1619 *OutDirectoryCB = NULL;
1621 *OutVolumeCB = pCurrentVolume;
1623 *OutVolumeReferenceReason = VolumeReferenceReason;
1625 bReleaseCurrentVolume = FALSE;
1627 if( ComponentName != NULL)
1630 *ComponentName = uniComponentName;
1633 *RootPathName = uniFullPathName;
1637 // We can't possibly have a pDirEntry since the lookup failed
1639 try_return( ntStatus);
1644 // Generate the CRC on the node and perform a case sensitive lookup
1647 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1648 AFS_TRACE_LEVEL_VERBOSE_2,
1649 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case sensitive\n",
1653 ulCRC = AFSGenerateCRC( &uniSearchName,
1656 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1659 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1663 if( pDirEntry == NULL)
1667 // Missed so perform a case insensitive lookup
1670 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1671 AFS_TRACE_LEVEL_VERBOSE_2,
1672 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case insensitive\n",
1676 ulCRC = AFSGenerateCRC( &uniSearchName,
1679 AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1683 if( pDirEntry == NULL)
1687 // OK, if this component is a valid short name then try
1688 // a lookup in the short name tree
1691 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1692 RtlIsNameLegalDOS8Dot3( &uniSearchName,
1697 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1698 AFS_TRACE_LEVEL_VERBOSE_2,
1699 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ short name\n",
1703 AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1708 if ( pDirEntry == NULL &&
1709 pParentDirEntry->ObjectInformation->VolumeCB == AFSGlobalRoot)
1713 // Check with the service to see if this is a valid cell name
1714 // that can be automatically resolved. Drop the shared TreeLock
1715 // since AFSCheckCellName must acquire it exclusively.
1718 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1720 ntStatus = AFSCheckCellName( AuthGroup,
1724 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1728 if( pDirEntry == NULL)
1732 // If we substituted a name then reset our search name and try again
1735 if( bSubstituteName)
1738 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1740 uniSearchName = uniComponentName;
1742 bSubstituteName = FALSE;
1744 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1746 continue; // while( pDirEntry == NULL)
1750 // Node name not found so get out
1753 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1755 if( uniRemainingPath.Length > 0)
1758 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1760 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1761 AFS_TRACE_LEVEL_VERBOSE,
1762 "AFSLocateNameEntry (FO: %p) Returning path not found for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
1765 pParentDirEntry->ObjectInformation->FileId.Cell,
1766 pParentDirEntry->ObjectInformation->FileId.Volume,
1767 pParentDirEntry->ObjectInformation->FileId.Vnode,
1768 pParentDirEntry->ObjectInformation->FileId.Unique));
1773 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1775 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1776 AFS_TRACE_LEVEL_VERBOSE,
1777 "AFSLocateNameEntry (FO: %p) Returning name not found for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
1780 pParentDirEntry->ObjectInformation->FileId.Cell,
1781 pParentDirEntry->ObjectInformation->FileId.Volume,
1782 pParentDirEntry->ObjectInformation->FileId.Vnode,
1783 pParentDirEntry->ObjectInformation->FileId.Unique));
1786 // Pass back the directory entries
1789 *OutParentDirectoryCB = pParentDirEntry;
1791 pParentDirEntry = NULL;
1793 *OutDirectoryCB = NULL;
1795 *OutVolumeCB = pCurrentVolume;
1797 *OutVolumeReferenceReason = VolumeReferenceReason;
1799 bReleaseCurrentVolume = FALSE;
1801 if( ComponentName != NULL)
1804 *ComponentName = uniComponentName;
1807 *RootPathName = uniFullPathName;
1810 try_return( ntStatus);
1817 // Here we have a match on the case insensitive lookup for the name. If there
1818 // Is more than one link entry for this node then fail the lookup request
1821 pCurrentObject = pDirEntry->ObjectInformation;
1823 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1824 pDirEntry->CaseInsensitiveList.fLink != NULL)
1828 // Increment our dir entry ref count since we will decrement it on exit
1831 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1833 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1834 AFS_TRACE_LEVEL_VERBOSE,
1835 "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1836 &pDirEntry->NameInformation.FileName,
1841 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1843 try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1848 if( pDirEntry != NULL)
1852 // If the verify flag is set on the parent and the current entry is deleted
1853 // revalidate the parent and search again.
1856 pCurrentObject = pDirEntry->ObjectInformation;
1858 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1859 BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1862 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1864 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1865 AFS_TRACE_LEVEL_VERBOSE,
1866 "AFSLocateNameEntry (FO: %p) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1868 &pParentDirEntry->NameInformation.FileName,
1869 pParentDirEntry->ObjectInformation->FileId.Cell,
1870 pParentDirEntry->ObjectInformation->FileId.Volume,
1871 pParentDirEntry->ObjectInformation->FileId.Vnode,
1872 pParentDirEntry->ObjectInformation->FileId.Unique));
1875 // Directory TreeLock should be exclusively held
1878 AFSAcquireExcl( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1881 ntStatus = AFSVerifyEntry( AuthGroup,
1884 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1886 if( !NT_SUCCESS( ntStatus))
1889 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1890 AFS_TRACE_LEVEL_ERROR,
1891 "AFSLocateNameEntry (FO: %p) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1893 &pParentDirEntry->NameInformation.FileName,
1894 pParentDirEntry->ObjectInformation->FileId.Cell,
1895 pParentDirEntry->ObjectInformation->FileId.Volume,
1896 pParentDirEntry->ObjectInformation->FileId.Vnode,
1897 pParentDirEntry->ObjectInformation->FileId.Unique,
1900 try_return( ntStatus);
1903 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1904 AFS_TRACE_LEVEL_VERBOSE,
1905 "AFSLocateNameEntry (FO: %p) Reprocessing component %wZ in parent %wZ\n",
1908 &pParentDirEntry->NameInformation.FileName));
1913 pCurrentObject = NULL;
1919 // Increment our dir entry ref count
1922 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1924 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1925 AFS_TRACE_LEVEL_VERBOSE,
1926 "AFSLocateNameEntry Increment6 count on %wZ DE %p Ccb %p Cnt %d\n",
1927 &pDirEntry->NameInformation.FileName,
1933 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1935 } // End while( pDirEntry == NULL)
1938 // If we have a dirEntry for this component, perform some basic validation on it
1941 if( pDirEntry != NULL)
1944 pCurrentObject = pDirEntry->ObjectInformation;
1946 if (BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1949 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1950 AFS_TRACE_LEVEL_ERROR,
1951 "AFSLocateNameEntry (FO: %p) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1953 &pDirEntry->NameInformation.FileName,
1954 pCurrentObject->FileId.Cell,
1955 pCurrentObject->FileId.Volume,
1956 pCurrentObject->FileId.Vnode,
1957 pCurrentObject->FileId.Unique));
1960 // This entry was deleted through the invalidation call back so perform cleanup
1964 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1967 pParentObjectInfo = AFSFindObjectInfo( pCurrentObject->VolumeCB,
1968 &pCurrentObject->ParentFileId,
1972 ASSERT( pParentObjectInfo != NULL);
1974 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1977 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1980 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1982 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1983 AFS_TRACE_LEVEL_VERBOSE,
1984 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1985 &pDirEntry->NameInformation.FileName,
1990 ASSERT( lCount >= 0);
1993 pDirEntry->NameArrayReferenceCount <= 0)
1996 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1997 AFS_TRACE_LEVEL_VERBOSE,
1998 "AFSLocateNameEntry Deleting dir entry %p (%p) for %wZ\n",
2001 &pDirEntry->NameInformation.FileName));
2004 // Remove and delete the directory entry from the parent list
2007 AFSDeleteDirEntry( pParentObjectInfo,
2010 AFSAcquireShared( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
2013 if( pCurrentObject->ObjectReferenceCount <= 0)
2016 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
2019 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2020 AFS_TRACE_LEVEL_VERBOSE,
2021 "AFSLocateNameEntry Removing object %p from volume tree\n",
2024 AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
2025 &pCurrentObject->TreeEntry);
2027 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
2031 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
2036 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2037 AFS_TRACE_LEVEL_VERBOSE,
2038 "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
2040 &pDirEntry->NameInformation.FileName));
2042 SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
2044 AFSRemoveNameEntry( pParentObjectInfo,
2048 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2050 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
2053 // We deleted the dir entry so check if there is any remaining portion
2054 // of the name to process.
2057 if( uniRemainingPath.Length > 0)
2060 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
2062 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2063 AFS_TRACE_LEVEL_VERBOSE,
2064 "AFSLocateNameEntry (FO: %p) Returning path not found(2) for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
2067 pParentObjectInfo->FileId.Cell,
2068 pParentObjectInfo->FileId.Volume,
2069 pParentObjectInfo->FileId.Vnode,
2070 pParentObjectInfo->FileId.Unique));
2072 AFSReleaseObjectInfo( &pParentObjectInfo);
2077 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
2079 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2080 AFS_TRACE_LEVEL_VERBOSE,
2081 "AFSLocateNameEntry (FO: %p) Returning name not found(2) for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
2084 pParentObjectInfo->FileId.Cell,
2085 pParentObjectInfo->FileId.Volume,
2086 pParentObjectInfo->FileId.Vnode,
2087 pParentObjectInfo->FileId.Unique));
2089 AFSReleaseObjectInfo( &pParentObjectInfo);
2092 // Pass back the directory entries
2095 *OutParentDirectoryCB = pParentDirEntry;
2097 pParentDirEntry = NULL;
2099 *OutDirectoryCB = NULL;
2101 *OutVolumeCB = pCurrentVolume;
2103 *OutVolumeReferenceReason = VolumeReferenceReason;
2105 bReleaseCurrentVolume = FALSE;
2107 if( ComponentName != NULL)
2110 *ComponentName = uniComponentName;
2113 *RootPathName = uniFullPathName;
2118 if( ntStatus != STATUS_SUCCESS)
2121 try_return( ntStatus);
2125 // If we ended up substituting a name in the component then update
2126 // the full path and update the pointers
2129 if( bSubstituteName)
2132 BOOLEAN bRelativeOpen = FALSE;
2134 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2135 AFS_TRACE_LEVEL_VERBOSE_2,
2136 "AFSLocateNameEntry (FO: %p) Substituting %wZ into %wZ Index %08lX\n",
2140 ulSubstituteIndex));
2142 if( FileObject != NULL &&
2143 FileObject->RelatedFileObject != NULL)
2146 bRelativeOpen = TRUE;
2150 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
2151 // and free the prior Buffer contents but only if the fourth
2152 // parameter is TRUE.
2155 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
2160 bAllocatedSymLinkBuffer ||
2163 if( !NT_SUCCESS( ntStatus))
2166 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2167 AFS_TRACE_LEVEL_ERROR,
2168 "AFSLocateNameEntry (FO: %p) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
2175 try_return( ntStatus);
2179 // We have substituted a name into the buffer so if we do this again for this
2180 // path, we need to free up the buffer we allocated.
2183 bSubstitutedName = TRUE;
2187 // Update the search parameters
2190 uniPathName = uniRemainingPath;
2193 // Check if the is a SymLink entry but has no Target FileID or Name. In this
2194 // case it might be a DFS Link so let's go and evaluate it to be sure
2197 if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
2198 ( pCurrentObject->TargetFileId.Vnode == 0 ||
2199 pDirEntry->NameInformation.TargetName.Length == 0))
2202 ntStatus = AFSValidateSymLink( AuthGroup,
2205 if( !NT_SUCCESS( ntStatus))
2208 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2209 AFS_TRACE_LEVEL_ERROR,
2210 "AFSLocateNameEntry (FO: %p) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2212 &pDirEntry->NameInformation.FileName,
2213 pCurrentObject->FileId.Cell,
2214 pCurrentObject->FileId.Volume,
2215 pCurrentObject->FileId.Vnode,
2216 pCurrentObject->FileId.Unique,
2219 try_return( ntStatus);
2224 // Update the name array
2227 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2228 AFS_TRACE_LEVEL_VERBOSE,
2229 "AFSLocateNameEntry (FO: %p) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2231 &pDirEntry->NameInformation.FileName,
2232 pCurrentObject->FileId.Cell,
2233 pCurrentObject->FileId.Volume,
2234 pCurrentObject->FileId.Vnode,
2235 pCurrentObject->FileId.Unique));
2237 ntStatus = AFSInsertNextElement( pNameArray,
2240 if( !NT_SUCCESS( ntStatus))
2243 try_return( ntStatus);
2249 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2250 AFS_TRACE_LEVEL_VERBOSE,
2251 "AFSLocateNameEntry (FO: %p) Completed processing %wZ Status %08lX\n",
2256 if( ( !NT_SUCCESS( ntStatus) &&
2257 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
2258 ntStatus == STATUS_REPARSE)
2260 if( RootPathName->Buffer != uniFullPathName.Buffer)
2263 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
2269 if( *OutParentDirectoryCB != NULL)
2272 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2273 AFS_TRACE_LEVEL_VERBOSE,
2274 "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
2275 &(*OutParentDirectoryCB)->NameInformation.FileName,
2276 *OutParentDirectoryCB,
2278 (*OutParentDirectoryCB)->DirOpenReferenceCount));
2281 if( *OutDirectoryCB != NULL)
2284 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2285 AFS_TRACE_LEVEL_VERBOSE,
2286 "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
2287 &(*OutDirectoryCB)->NameInformation.FileName,
2290 (*OutDirectoryCB)->DirOpenReferenceCount));
2294 if( pDirEntry != NULL)
2297 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
2299 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2300 AFS_TRACE_LEVEL_VERBOSE,
2301 "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
2302 &pDirEntry->NameInformation.FileName,
2307 ASSERT( lCount >= 0);
2310 if( pParentDirEntry != NULL)
2313 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
2315 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2316 AFS_TRACE_LEVEL_VERBOSE,
2317 "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
2318 &pParentDirEntry->NameInformation.FileName,
2323 ASSERT( lCount >= 0);
2326 if( bReleaseCurrentVolume)
2329 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
2331 lCount = AFSVolumeDecrement( pCurrentVolume,
2332 VolumeReferenceReason);
2334 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2335 AFS_TRACE_LEVEL_VERBOSE,
2336 "AFSLocateNameEntry Decrement7 count on volume %p Reason %u Cnt %d\n",
2338 VolumeReferenceReason,
2341 bReleaseCurrentVolume = FALSE;
2344 if( bSubstituteName &&
2345 uniSearchName.Buffer != NULL)
2348 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
2356 AFSCreateDirEntry( IN GUID *AuthGroup,
2357 IN AFSObjectInfoCB *ParentObjectInfo,
2358 IN AFSDirectoryCB *ParentDirCB,
2359 IN PUNICODE_STRING FileName,
2360 IN PUNICODE_STRING ComponentName,
2361 IN ULONG Attributes,
2362 IN OUT AFSDirectoryCB **DirEntry)
2365 UNREFERENCED_PARAMETER(FileName);
2366 NTSTATUS ntStatus = STATUS_SUCCESS;
2367 AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
2368 LARGE_INTEGER liFileSize = {0,0};
2374 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2375 AFS_TRACE_LEVEL_VERBOSE_2,
2376 "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
2377 &ParentDirCB->NameInformation.FileName,
2378 ParentObjectInfo->FileId.Cell,
2379 ParentObjectInfo->FileId.Volume,
2380 ParentObjectInfo->FileId.Vnode,
2381 ParentObjectInfo->FileId.Unique,
2386 // OK, before inserting the node into the parent tree, issue
2387 // the request to the service for node creation
2388 // We will need to drop the lock on the parent node since the create
2389 // could cause a callback into the file system to invalidate it's cache
2392 ntStatus = AFSNotifyFileCreate( AuthGroup,
2400 // If the returned status is STATUS_REPARSE then the entry exists
2401 // and we raced, get out.
2403 if( ntStatus == STATUS_REPARSE)
2406 *DirEntry = pDirNode;
2408 try_return( ntStatus = STATUS_SUCCESS);
2411 if( !NT_SUCCESS( ntStatus))
2414 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2415 AFS_TRACE_LEVEL_ERROR,
2416 "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
2417 &ParentDirCB->NameInformation.FileName,
2418 ParentObjectInfo->FileId.Cell,
2419 ParentObjectInfo->FileId.Volume,
2420 ParentObjectInfo->FileId.Vnode,
2421 ParentObjectInfo->FileId.Unique,
2426 try_return( ntStatus);
2430 // If AFSNotifyFileCreate returns pDirNode != NULL, then its
2431 // DirOpenReferenceCount is held.
2434 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2438 // Before attempting to insert the new entry, check if we need to validate the parent
2441 if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2444 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2445 AFS_TRACE_LEVEL_VERBOSE,
2446 "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2447 &ParentDirCB->NameInformation.FileName,
2448 ParentObjectInfo->FileId.Cell,
2449 ParentObjectInfo->FileId.Volume,
2450 ParentObjectInfo->FileId.Vnode,
2451 ParentObjectInfo->FileId.Unique));
2453 ntStatus = AFSVerifyEntry( AuthGroup,
2456 if( !NT_SUCCESS( ntStatus))
2459 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2460 AFS_TRACE_LEVEL_ERROR,
2461 "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2462 &ParentDirCB->NameInformation.FileName,
2463 ParentObjectInfo->FileId.Cell,
2464 ParentObjectInfo->FileId.Volume,
2465 ParentObjectInfo->FileId.Vnode,
2466 ParentObjectInfo->FileId.Unique,
2469 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2471 try_return( ntStatus);
2476 // Check for the entry in the event we raced with some other thread
2479 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2480 (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2483 if( pExistingDirNode != NULL)
2485 if (AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2486 &pExistingDirNode->ObjectInformation->FileId))
2489 if ( pExistingDirNode != pDirNode)
2492 lCount = InterlockedDecrement( &pDirNode->DirOpenReferenceCount);
2494 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2495 AFS_TRACE_LEVEL_VERBOSE,
2496 "AFSCreateDirEntry Decrement count on %wZ DE %p Cnt %d\n",
2497 &pDirNode->NameInformation.FileName,
2501 AFSDeleteDirEntry( ParentObjectInfo,
2504 lCount = InterlockedIncrement( &pExistingDirNode->DirOpenReferenceCount);
2506 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2507 AFS_TRACE_LEVEL_VERBOSE,
2508 "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2509 &pExistingDirNode->NameInformation.FileName,
2513 *DirEntry = pExistingDirNode;
2516 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2518 try_return( ntStatus = STATUS_SUCCESS);
2524 // Need to tear down this entry and rebuild it below
2527 if( pExistingDirNode->DirOpenReferenceCount <= 0 &&
2528 pExistingDirNode->NameArrayReferenceCount <= 0)
2531 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2532 AFS_TRACE_LEVEL_VERBOSE,
2533 "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2535 &pExistingDirNode->NameInformation.FileName,
2536 pExistingDirNode->ObjectInformation->FileId.Cell,
2537 pExistingDirNode->ObjectInformation->FileId.Volume,
2538 pExistingDirNode->ObjectInformation->FileId.Vnode,
2539 pExistingDirNode->ObjectInformation->FileId.Unique,
2540 pDirNode->ObjectInformation->FileId.Cell,
2541 pDirNode->ObjectInformation->FileId.Volume,
2542 pDirNode->ObjectInformation->FileId.Vnode,
2543 pDirNode->ObjectInformation->FileId.Unique));
2545 AFSDeleteDirEntry( ParentObjectInfo,
2551 SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2553 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2554 AFS_TRACE_LEVEL_VERBOSE,
2555 "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2557 &pExistingDirNode->NameInformation.FileName,
2558 pExistingDirNode->ObjectInformation->FileId.Cell,
2559 pExistingDirNode->ObjectInformation->FileId.Volume,
2560 pExistingDirNode->ObjectInformation->FileId.Vnode,
2561 pExistingDirNode->ObjectInformation->FileId.Unique,
2562 pDirNode->ObjectInformation->FileId.Cell,
2563 pDirNode->ObjectInformation->FileId.Volume,
2564 pDirNode->ObjectInformation->FileId.Vnode,
2565 pDirNode->ObjectInformation->FileId.Unique));
2567 AFSRemoveNameEntry( ParentObjectInfo,
2573 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2574 AFS_TRACE_LEVEL_VERBOSE_2,
2575 "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2576 &ParentDirCB->NameInformation.FileName,
2577 ParentObjectInfo->FileId.Cell,
2578 ParentObjectInfo->FileId.Volume,
2579 ParentObjectInfo->FileId.Vnode,
2580 ParentObjectInfo->FileId.Unique,
2584 // Insert the directory node
2587 AFSInsertDirectoryNode( ParentObjectInfo,
2592 // Pass back the dir entry
2595 *DirEntry = pDirNode;
2597 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2608 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2609 IN AFSDirectoryCB *DirEntry,
2610 IN BOOLEAN InsertInEnumList)
2618 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2621 // Insert the node into the directory node tree
2624 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2625 AFS_TRACE_LEVEL_VERBOSE,
2626 "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2628 &DirEntry->NameInformation.FileName));
2630 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2632 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2635 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2637 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2638 AFS_TRACE_LEVEL_VERBOSE,
2639 "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2641 &DirEntry->NameInformation.FileName));
2646 AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2649 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2650 AFS_TRACE_LEVEL_VERBOSE,
2651 "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2653 &DirEntry->NameInformation.FileName));
2656 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2659 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2661 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2663 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2664 AFS_TRACE_LEVEL_VERBOSE,
2665 "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2667 &DirEntry->NameInformation.FileName));
2672 AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2675 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2676 AFS_TRACE_LEVEL_VERBOSE,
2677 "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2679 &DirEntry->NameInformation.FileName));
2683 // Into the shortname tree
2686 if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2689 if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2692 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2694 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2695 AFS_TRACE_LEVEL_VERBOSE,
2696 "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2698 &DirEntry->NameInformation.FileName));
2700 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2705 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2708 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2709 AFS_TRACE_LEVEL_VERBOSE,
2710 "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2712 &DirEntry->NameInformation.FileName));
2716 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2718 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2719 AFS_TRACE_LEVEL_VERBOSE,
2720 "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2722 &DirEntry->NameInformation.FileName));
2727 if( InsertInEnumList)
2731 // And insert the node into the directory list
2734 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2735 AFS_TRACE_LEVEL_VERBOSE,
2736 "AFSInsertDirectoryNode Inserting entry %p %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2738 &DirEntry->NameInformation.FileName,
2739 DirEntry->ObjectInformation->FileId.Cell,
2740 DirEntry->ObjectInformation->FileId.Volume,
2741 DirEntry->ObjectInformation->FileId.Vnode,
2742 DirEntry->ObjectInformation->FileId.Unique));
2744 if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2747 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2752 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2754 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2757 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2759 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2761 lCount = InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2763 AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2764 AFS_TRACE_LEVEL_VERBOSE,
2765 "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2766 &DirEntry->NameInformation.FileName,
2768 ParentObjectInfo->FileId.Cell,
2769 ParentObjectInfo->FileId.Volume,
2770 ParentObjectInfo->FileId.Vnode,
2771 ParentObjectInfo->FileId.Unique));
2779 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2780 IN AFSDirectoryCB **ppDirEntry)
2784 AFSDirectoryCB *pDirEntry;
2789 pDirEntry = (AFSDirectoryCB *) InterlockedCompareExchangePointer( (PVOID *)ppDirEntry,
2793 if ( pDirEntry == NULL)
2796 try_return( NOTHING);
2799 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2800 AFS_TRACE_LEVEL_VERBOSE,
2801 "AFSDeleteDirEntry Deleting dir entry in parent %p Entry %p object %p %wZ RefCount %d\n",
2804 pDirEntry->ObjectInformation,
2805 &pDirEntry->NameInformation.FileName,
2806 pDirEntry->DirOpenReferenceCount));
2808 ASSERT( pDirEntry->DirOpenReferenceCount == 0);
2810 AFSRemoveDirNodeFromParent( ParentObjectInfo,
2815 // Free up the name buffer if it was reallocated
2818 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2821 AFSExFreePoolWithTag( pDirEntry->NameInformation.FileName.Buffer, 0);
2824 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2827 AFSExFreePoolWithTag( pDirEntry->NameInformation.TargetName.Buffer, 0);
2830 if ( pDirEntry->ObjectInformation != NULL)
2833 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
2834 pDirEntry->ObjectInformation->Links == 0)
2837 SetFlag( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2841 // Dereference the object for this dir entry
2844 AFSAcquireShared( pDirEntry->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock,
2847 lCount = AFSObjectInfoDecrement( pDirEntry->ObjectInformation,
2848 AFS_OBJECT_REFERENCE_DIRENTRY);
2850 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2851 AFS_TRACE_LEVEL_VERBOSE,
2852 "AFSDeleteDirEntry Decrement count on object %p Cnt %d\n",
2853 pDirEntry->ObjectInformation,
2856 AFSReleaseResource( pDirEntry->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock);
2859 ExDeleteResourceLite( &pDirEntry->NonPaged->Lock);
2861 AFSExFreePoolWithTag( pDirEntry->NonPaged, AFS_DIR_ENTRY_NP_TAG);
2864 // Free up the dir entry
2867 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
2868 AFS_TRACE_LEVEL_VERBOSE,
2869 "AFSDeleteDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
2872 AFSExFreePoolWithTag( pDirEntry, AFS_DIR_ENTRY_TAG);
2881 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2882 IN AFSDirectoryCB *DirEntry,
2883 IN BOOLEAN RemoveFromEnumList)
2886 NTSTATUS ntStatus = STATUS_SUCCESS;
2893 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2895 if ( DirEntry->ObjectInformation != NULL)
2898 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2899 AFS_TRACE_LEVEL_VERBOSE,
2900 "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %p\n",
2902 &DirEntry->NameInformation.FileName,
2903 DirEntry->ObjectInformation->FileId.Cell,
2904 DirEntry->ObjectInformation->FileId.Volume,
2905 DirEntry->ObjectInformation->FileId.Vnode,
2906 DirEntry->ObjectInformation->FileId.Unique,
2912 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2913 AFS_TRACE_LEVEL_VERBOSE,
2914 "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ from Parent %p\n",
2916 &DirEntry->NameInformation.FileName,
2920 if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2923 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2924 AFS_TRACE_LEVEL_VERBOSE,
2925 "AFSRemoveDirNodeFromParent Removing DirEntry %p name %wZ\n",
2927 &DirEntry->NameInformation.FileName));
2929 AFSRemoveNameEntry( ParentObjectInfo,
2935 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2936 AFS_TRACE_LEVEL_VERBOSE,
2937 "AFSRemoveDirNodeFromParent DE %p for %wZ NOT removing entry due to flag set\n",
2939 &DirEntry->NameInformation.FileName));
2943 if( RemoveFromEnumList &&
2944 BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST))
2948 // And remove the entry from the enumeration list
2951 if( DirEntry->ListEntry.fLink == NULL)
2954 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = (AFSDirectoryCB *)DirEntry->ListEntry.bLink;
2959 ((AFSDirectoryCB *)DirEntry->ListEntry.fLink)->ListEntry.bLink = DirEntry->ListEntry.bLink;
2962 if( DirEntry->ListEntry.bLink == NULL)
2965 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = (AFSDirectoryCB *)DirEntry->ListEntry.fLink;
2970 ((AFSDirectoryCB *)DirEntry->ListEntry.bLink)->ListEntry.fLink = DirEntry->ListEntry.fLink;
2973 ASSERT( ParentObjectInfo->Specific.Directory.DirectoryNodeCount > 0);
2975 lCount = InterlockedDecrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2977 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2979 AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2980 AFS_TRACE_LEVEL_VERBOSE,
2981 "AFSRemoveDirNodeFromParent Removing entry %wZ Dec Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2982 &DirEntry->NameInformation.FileName,
2984 ParentObjectInfo->FileId.Cell,
2985 ParentObjectInfo->FileId.Volume,
2986 ParentObjectInfo->FileId.Vnode,
2987 ParentObjectInfo->FileId.Unique));
2989 DirEntry->ListEntry.fLink = NULL;
2990 DirEntry->ListEntry.bLink = NULL;
2998 AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
2999 IN OUT PUNICODE_STRING TargetFileName)
3002 NTSTATUS ntStatus = STATUS_SUCCESS;
3003 UNICODE_STRING uniFileName;
3009 // We will process backwards from the end of the name looking
3010 // for the first \ we encounter
3013 uniFileName.Length = FileName->Length;
3014 uniFileName.MaximumLength = FileName->MaximumLength;
3016 uniFileName.Buffer = FileName->Buffer;
3021 if( uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
3025 // Subtract one more character off of the filename if it is not the root
3028 if( uniFileName.Length > sizeof( WCHAR))
3031 uniFileName.Length -= sizeof( WCHAR);
3035 // Now build up the target name
3038 TargetFileName->Length = FileName->Length - uniFileName.Length;
3041 // If we are not on the root then fixup the name
3044 if( uniFileName.Length > sizeof( WCHAR))
3047 TargetFileName->Length -= sizeof( WCHAR);
3049 TargetFileName->Buffer = &uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) + 1];
3054 TargetFileName->Buffer = &uniFileName.Buffer[ uniFileName.Length/sizeof( WCHAR)];
3058 // Fixup the passed back filename length
3061 FileName->Length = uniFileName.Length;
3063 TargetFileName->MaximumLength = TargetFileName->Length;
3068 uniFileName.Length -= sizeof( WCHAR);
3076 AFSParseName( IN PIRP Irp,
3078 OUT PUNICODE_STRING FileName,
3079 OUT PUNICODE_STRING ParsedFileName,
3080 OUT PUNICODE_STRING RootFileName,
3081 OUT ULONG *ParseFlags,
3082 OUT AFSVolumeCB **VolumeCB,
3083 OUT AFSDirectoryCB **ParentDirectoryCB,
3084 OUT AFSNameArrayHdr **NameArray)
3087 NTSTATUS ntStatus = STATUS_SUCCESS;
3088 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
3089 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3090 UNICODE_STRING uniFullName, uniComponentName, uniRemainingPath;
3092 AFSDirectoryCB *pDirEntry = NULL;
3093 USHORT usIndex = 0, usDriveIndex = 0;
3094 AFSCcb *pRelatedCcb = NULL;
3095 AFSNameArrayHdr *pNameArray = NULL, *pRelatedNameArray = NULL;
3096 USHORT usComponentIndex = 0;
3097 USHORT usComponentLength = 0;
3098 AFSVolumeCB *pVolumeCB = NULL;
3099 AFSFcb *pRelatedFcb = NULL;
3100 BOOLEAN bReleaseTreeLock = FALSE;
3101 BOOLEAN bIsAllShare = FALSE;
3108 // Indicate we are opening a root ...
3111 *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
3113 *ParentDirectoryCB = NULL;
3115 if( pIrpSp->FileObject->RelatedFileObject != NULL)
3118 pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
3120 pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
3122 pRelatedNameArray = pRelatedCcb->NameArray;
3124 uniFullName = pIrpSp->FileObject->FileName;
3126 ASSERT( pRelatedFcb != NULL);
3129 // No wild cards in the name
3132 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3133 AFS_TRACE_LEVEL_VERBOSE_2,
3134 "AFSParseName (%p) Relative open for %wZ FID %08lX-%08lX-%08lX-%08lX component %wZ\n",
3136 &pRelatedCcb->DirectoryCB->NameInformation.FileName,
3137 pRelatedFcb->ObjectInformation->FileId.Cell,
3138 pRelatedFcb->ObjectInformation->FileId.Volume,
3139 pRelatedFcb->ObjectInformation->FileId.Vnode,
3140 pRelatedFcb->ObjectInformation->FileId.Unique,
3143 if( FsRtlDoesNameContainWildCards( &uniFullName))
3146 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3147 AFS_TRACE_LEVEL_ERROR,
3148 "AFSParseName (%p) Component %wZ contains wild cards\n",
3152 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3155 pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
3157 pDirEntry = pRelatedCcb->DirectoryCB;
3159 *FileName = pIrpSp->FileObject->FileName;
3162 // Grab the root node while checking state
3165 AFSAcquireShared( pVolumeCB->VolumeLock,
3168 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3169 BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3173 // The volume has been taken off line so fail the access
3176 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3177 AFS_TRACE_LEVEL_ERROR,
3178 "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3180 pVolumeCB->ObjectInformation.FileId.Cell,
3181 pVolumeCB->ObjectInformation.FileId.Volume));
3183 AFSReleaseResource( pVolumeCB->VolumeLock);
3185 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3188 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3191 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3192 AFS_TRACE_LEVEL_VERBOSE,
3193 "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
3195 pVolumeCB->ObjectInformation.FileId.Cell,
3196 pVolumeCB->ObjectInformation.FileId.Volume));
3198 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3201 if( !NT_SUCCESS( ntStatus))
3204 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3205 AFS_TRACE_LEVEL_ERROR,
3206 "AFSParseName (%p) Failed verification of root Status %08lX\n",
3210 AFSReleaseResource( pVolumeCB->VolumeLock);
3212 try_return( ntStatus);
3216 AFSReleaseResource( pVolumeCB->VolumeLock);
3218 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
3221 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3222 AFS_TRACE_LEVEL_VERBOSE,
3223 "AFSParseName (%p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3225 &pDirEntry->NameInformation.FileName,
3226 pDirEntry->ObjectInformation->FileId.Cell,
3227 pDirEntry->ObjectInformation->FileId.Volume,
3228 pDirEntry->ObjectInformation->FileId.Vnode,
3229 pDirEntry->ObjectInformation->FileId.Unique));
3232 // Directory TreeLock should be exclusively held
3235 AFSAcquireExcl( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
3238 ntStatus = AFSVerifyEntry( AuthGroup,
3241 AFSReleaseResource( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
3243 if( !NT_SUCCESS( ntStatus))
3246 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3247 AFS_TRACE_LEVEL_VERBOSE,
3248 "AFSParseName (%p) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3250 &pDirEntry->NameInformation.FileName,
3251 pDirEntry->ObjectInformation->FileId.Cell,
3252 pDirEntry->ObjectInformation->FileId.Volume,
3253 pDirEntry->ObjectInformation->FileId.Vnode,
3254 pDirEntry->ObjectInformation->FileId.Unique,
3257 try_return( ntStatus);
3262 // Create our full path name buffer
3265 uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length +
3267 pIrpSp->FileObject->FileName.Length +
3270 uniFullName.Length = 0;
3272 uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
3273 uniFullName.MaximumLength,
3274 AFS_NAME_BUFFER_THREE_TAG);
3276 if( uniFullName.Buffer == NULL)
3279 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3280 AFS_TRACE_LEVEL_ERROR,
3281 "AFSParseName (%p) Failed to allocate full name buffer\n",
3284 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3287 RtlZeroMemory( uniFullName.Buffer,
3288 uniFullName.MaximumLength);
3290 RtlCopyMemory( uniFullName.Buffer,
3291 pRelatedCcb->FullFileName.Buffer,
3292 pRelatedCcb->FullFileName.Length);
3294 uniFullName.Length = pRelatedCcb->FullFileName.Length;
3296 usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
3298 usComponentLength = pIrpSp->FileObject->FileName.Length;
3300 if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
3301 pIrpSp->FileObject->FileName.Length > 0 &&
3302 pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
3303 pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
3306 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
3308 uniFullName.Length += sizeof( WCHAR);
3310 usComponentLength += sizeof( WCHAR);
3313 if( pIrpSp->FileObject->FileName.Length > 0)
3316 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
3317 pIrpSp->FileObject->FileName.Buffer,
3318 pIrpSp->FileObject->FileName.Length);
3320 uniFullName.Length += pIrpSp->FileObject->FileName.Length;
3323 *RootFileName = uniFullName;
3326 // We populate up to the current parent
3329 if( pRelatedNameArray == NULL)
3333 // Init and populate our name array
3336 pNameArray = AFSInitNameArray( NULL,
3339 if( pNameArray == NULL)
3342 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3343 AFS_TRACE_LEVEL_VERBOSE,
3344 "AFSParseName (%p) Failed to initialize name array\n",
3347 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3349 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3352 ntStatus = AFSPopulateNameArray( pNameArray,
3354 pRelatedCcb->DirectoryCB);
3360 // Init and populate our name array
3363 pNameArray = AFSInitNameArray( NULL,
3364 pRelatedNameArray->MaxElementCount);
3366 if( pNameArray == NULL)
3369 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3370 AFS_TRACE_LEVEL_VERBOSE,
3371 "AFSParseName (%p) Failed to initialize name array\n",
3374 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3376 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3379 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
3381 pRelatedCcb->DirectoryCB);
3384 if( !NT_SUCCESS( ntStatus))
3387 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3388 AFS_TRACE_LEVEL_VERBOSE,
3389 "AFSParseName (%p) Failed to populate name array\n",
3392 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3394 try_return( ntStatus);
3397 ParsedFileName->Length = usComponentLength;
3398 ParsedFileName->MaximumLength = uniFullName.MaximumLength;
3400 ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
3403 // Indicate to caller that RootFileName must be freed
3406 SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
3408 *NameArray = pNameArray;
3411 // Increment our volume reference count
3414 lCount = AFSVolumeIncrement( pVolumeCB,
3415 AFS_VOLUME_REFERENCE_PARSE_NAME);
3417 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3418 AFS_TRACE_LEVEL_VERBOSE,
3419 "AFSParseName Increment count on volume %p Cnt %d\n",
3423 *VolumeCB = pVolumeCB;
3425 *ParentDirectoryCB = pDirEntry;
3427 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3428 AFS_TRACE_LEVEL_VERBOSE_2,
3429 "AFSParseName (%p) Returning full name %wZ\n",
3433 try_return( ntStatus);
3437 // No wild cards in the name
3440 uniFullName = pIrpSp->FileObject->FileName;
3442 if( FsRtlDoesNameContainWildCards( &uniFullName) ||
3443 uniFullName.Length < AFSServerName.Length)
3446 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3447 AFS_TRACE_LEVEL_ERROR,
3448 "AFSParseName (%p) Name %wZ contains wild cards or too short\n",
3452 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3456 // The name is a fully qualified name. Parse out the server/share names and
3457 // point to the root qualified name
3458 // First thing is to locate the server name
3461 FsRtlDissectName( uniFullName,
3465 uniFullName = uniRemainingPath;
3468 // This component is the server name we are serving
3471 if( RtlCompareUnicodeString( &uniComponentName,
3477 // Drive letter based name?
3480 uniFullName = pIrpSp->FileObject->FileName;
3482 while( usIndex < uniFullName.Length/sizeof( WCHAR))
3485 if( uniFullName.Buffer[ usIndex] == L':')
3488 uniFullName.Buffer = &uniFullName.Buffer[ usIndex + 2];
3490 uniFullName.Length -= (usIndex + 2) * sizeof( WCHAR);
3492 usDriveIndex = usIndex - 1;
3501 // Do we have the right server name now?
3504 FsRtlDissectName( uniFullName,
3508 uniFullName = uniRemainingPath;
3511 // This component is the server name we are serving
3514 if( RtlCompareUnicodeString( &uniComponentName,
3519 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3520 AFS_TRACE_LEVEL_ERROR,
3521 "AFSParseName (%p) Name %wZ does not have server name\n",
3523 &pIrpSp->FileObject->FileName));
3525 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3529 // Validate this drive letter is actively mapped
3532 if( usDriveIndex > 0 &&
3533 !AFSIsDriveMapped( pIrpSp->FileObject->FileName.Buffer[ usDriveIndex]))
3536 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3537 AFS_TRACE_LEVEL_ERROR,
3538 "AFSParseName (%p) Name %wZ contains invalid drive mapping\n",
3540 &pIrpSp->FileObject->FileName));
3542 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3546 if( FsRtlDoesNameContainWildCards( &uniFullName))
3549 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3550 AFS_TRACE_LEVEL_ERROR,
3551 "AFSParseName (%p) Component %wZ contains wild cards\n",
3555 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3558 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3559 AFS_TRACE_LEVEL_VERBOSE_2,
3560 "AFSParseName (%p) Processing full name %wZ\n",
3564 if( uniFullName.Length > 0 &&
3565 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] == L'\\')
3568 uniFullName.Length -= sizeof( WCHAR);
3572 // Be sure we are online and ready to go
3575 AFSAcquireShared( AFSGlobalRoot->VolumeLock,
3578 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3579 BooleanFlagOn( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3583 // The volume has been taken off line so fail the access
3586 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3587 AFS_TRACE_LEVEL_ERROR,
3588 "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3590 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3591 AFSGlobalRoot->ObjectInformation.FileId.Volume));
3593 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3595 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3598 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3601 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3602 AFS_TRACE_LEVEL_VERBOSE,
3603 "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
3605 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3606 AFSGlobalRoot->ObjectInformation.FileId.Volume));
3608 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3611 if( !NT_SUCCESS( ntStatus))
3614 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3615 AFS_TRACE_LEVEL_ERROR,
3616 "AFSParseName (%p) Failed verification of root Status %08lX\n",
3620 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3622 try_return( ntStatus);
3626 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3628 if( !BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3631 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3632 AFS_TRACE_LEVEL_VERBOSE,
3633 "AFSParseName (%p) Enumerating global root of volume %08lX:%08lX\n",
3635 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3636 AFSGlobalRoot->ObjectInformation.FileId.Volume));
3638 ntStatus = AFSEnumerateGlobalRoot( AuthGroup);
3640 if( !NT_SUCCESS( ntStatus))
3643 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3644 AFS_TRACE_LEVEL_ERROR,
3645 "AFSParseName (%p) Failed enumeraiton of root Status %08lX\n",
3649 try_return( ntStatus);
3654 // Check for the \\Server access and return it as though it were \\Server\Globalroot
3657 if( uniRemainingPath.Buffer == NULL ||
3658 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3659 uniRemainingPath.Buffer[ 0] == L'\\'))
3662 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3663 AFS_TRACE_LEVEL_VERBOSE_2,
3664 "AFSParseName (%p) Returning global root access\n",
3667 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3669 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3670 AFS_TRACE_LEVEL_VERBOSE,
3671 "AFSParseName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3672 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3673 AFSGlobalRoot->DirectoryCB,
3679 FileName->Length = 0;
3680 FileName->MaximumLength = 0;
3681 FileName->Buffer = NULL;
3683 try_return( ntStatus = STATUS_SUCCESS);
3686 *RootFileName = uniFullName;
3689 // Include the starting \ in the root name
3692 if( RootFileName->Buffer[ 0] != L'\\')
3694 RootFileName->Buffer--;
3695 RootFileName->Length += sizeof( WCHAR);
3696 RootFileName->MaximumLength += sizeof( WCHAR);
3700 // Get the 'share' name
3703 FsRtlDissectName( uniFullName,
3707 if( FsRtlDoesNameContainWildCards( &uniFullName))
3710 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3711 AFS_TRACE_LEVEL_ERROR,
3712 "AFSParseName (%p) Component %wZ contains wild cards\n",
3714 &uniComponentName));
3716 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3720 // If this is the ALL access then perform some additional processing
3723 if( uniComponentName.Length == 0 ||
3724 RtlCompareUnicodeString( &uniComponentName,
3732 // If there is nothing else then get out
3735 if( uniRemainingPath.Buffer == NULL ||
3736 uniRemainingPath.Length == 0 ||
3737 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3738 uniRemainingPath.Buffer[ 0] == L'\\'))
3741 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3742 AFS_TRACE_LEVEL_VERBOSE_2,
3743 "AFSParseName (%p) Returning global root access\n",
3746 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3748 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3749 AFS_TRACE_LEVEL_VERBOSE,
3750 "AFSParseName Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
3751 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3752 AFSGlobalRoot->DirectoryCB,
3758 FileName->Length = 0;
3759 FileName->MaximumLength = 0;
3760 FileName->Buffer = NULL;
3762 try_return( ntStatus = STATUS_SUCCESS);
3766 // Process the name again to strip off the ALL portion
3769 uniFullName = uniRemainingPath;
3771 FsRtlDissectName( uniFullName,
3776 // Check for the PIOCtl name
3779 if( RtlCompareUnicodeString( &uniComponentName,
3784 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3785 AFS_TRACE_LEVEL_VERBOSE_2,
3786 "AFSParseName (%p) Returning root PIOCtl access\n",
3789 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3791 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3792 AFS_TRACE_LEVEL_VERBOSE,
3793 "AFSParseName Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
3794 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3795 AFSGlobalRoot->DirectoryCB,
3799 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3803 *FileName = AFSPIOCtlName;
3805 try_return( ntStatus = STATUS_SUCCESS);
3808 else if( (pDirEntry = AFSGetSpecialShareNameEntry( &uniComponentName,
3809 &uniRemainingPath)) != NULL)
3812 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3813 AFS_TRACE_LEVEL_VERBOSE_2,
3814 "AFSParseName (%p) Returning root share name %wZ access\n",
3816 &uniComponentName));
3819 // Add in the full share name to pass back
3822 if( uniRemainingPath.Buffer != NULL)
3826 // This routine strips off the leading slash so add it back in
3829 uniRemainingPath.Buffer--;
3830 uniRemainingPath.Length += sizeof( WCHAR);
3831 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3834 // And the cell name
3837 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3838 uniRemainingPath.Length += uniComponentName.Length;
3839 uniRemainingPath.MaximumLength += uniComponentName.Length;
3841 uniComponentName = uniRemainingPath;
3846 *FileName = uniComponentName;
3848 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3850 *ParentDirectoryCB = pDirEntry;
3852 try_return( ntStatus = STATUS_SUCCESS);
3856 // Determine the 'share' we are accessing
3859 ulCRC = AFSGenerateCRC( &uniComponentName,
3862 AFSAcquireShared( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3865 bReleaseTreeLock = TRUE;
3867 AFSLocateCaseSensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
3871 if( pDirEntry == NULL)
3874 ulCRC = AFSGenerateCRC( &uniComponentName,
3877 AFSLocateCaseInsensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
3881 if( pDirEntry == NULL)
3885 // OK, if this component is a valid short name then try
3886 // a lookup in the short name tree
3889 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3890 RtlIsNameLegalDOS8Dot3( &uniComponentName,
3895 AFSLocateShortNameDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.ShortNameTree,
3900 if( pDirEntry == NULL)
3904 // Check with the service whether it is a valid cell name
3907 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3909 bReleaseTreeLock = FALSE;
3911 ntStatus = AFSCheckCellName( AuthGroup,
3915 if( !NT_SUCCESS( ntStatus))
3919 uniRemainingPath.Length == 0 &&
3920 ntStatus == STATUS_OBJECT_PATH_NOT_FOUND)
3923 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3924 AFS_TRACE_LEVEL_VERBOSE,
3925 "AFSParseName (%p) AFSCheckCellName %wZ returned path not found; ntStatus %08X\n",
3928 STATUS_OBJECT_NAME_NOT_FOUND));
3930 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
3933 try_return( ntStatus);
3939 if( bReleaseTreeLock)
3941 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3946 // Be sure we are starting from the correct volume
3949 if( pDirEntry->ObjectInformation->VolumeCB != AFSGlobalRoot)
3953 // We dropped the global root in the CheckCellName routine which is the
3954 // only way we can be here
3957 pVolumeCB = pDirEntry->ObjectInformation->VolumeCB;
3960 // Init our name array
3963 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
3966 if( pNameArray == NULL)
3969 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3970 AFS_TRACE_LEVEL_VERBOSE,
3971 "AFSParseName (%p) Failed to initialize name array\n",
3974 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3977 ntStatus = AFSInsertNextElement( pNameArray,
3978 pVolumeCB->DirectoryCB);
3983 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3984 AFS_TRACE_LEVEL_VERBOSE,
3985 "AFSParseName (%p) Failed to insert name array element\n",
3988 try_return( ntStatus);
3992 // In this case don't add back in the 'share' name since that is where we are
3993 // starting. Just put the leading slash back in
3996 if( uniRemainingPath.Buffer != NULL)
3999 uniRemainingPath.Buffer--;
4000 uniRemainingPath.Length += sizeof( WCHAR);
4001 uniRemainingPath.MaximumLength += sizeof( WCHAR);
4003 if( uniRemainingPath.Length > sizeof( WCHAR))
4006 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
4010 // Pass back the parent being the root of the volume
4013 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
4019 // Pass back a root slash
4022 uniRemainingPath = uniComponentName;
4024 uniRemainingPath.Buffer--;
4025 uniRemainingPath.Length = sizeof( WCHAR);
4026 uniRemainingPath.MaximumLength = sizeof( WCHAR);
4029 // This is a root open so pass back no parent
4036 pVolumeCB = AFSGlobalRoot;
4039 // Init our name array
4042 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
4044 if( pNameArray == NULL)
4047 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4048 AFS_TRACE_LEVEL_VERBOSE,
4049 "AFSParseName (%p) Failed to initialize name array\n",
4052 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4056 // Add back in the 'share' portion of the name since we will parse it out on return
4059 if( uniRemainingPath.Buffer != NULL)
4063 // This routine strips off the leading slash so add it back in
4066 uniRemainingPath.Buffer--;
4067 uniRemainingPath.Length += sizeof( WCHAR);
4068 uniRemainingPath.MaximumLength += sizeof( WCHAR);
4070 if( uniRemainingPath.Length > sizeof( WCHAR))
4073 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
4077 // And the cell name
4080 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
4081 uniRemainingPath.Length += uniComponentName.Length;
4082 uniRemainingPath.MaximumLength += uniComponentName.Length;
4087 uniRemainingPath = uniComponentName;
4091 // And the leading slash again ...
4094 uniRemainingPath.Buffer--;
4095 uniRemainingPath.Length += sizeof( WCHAR);
4096 uniRemainingPath.MaximumLength += sizeof( WCHAR);
4099 // Pass back the parent being the volume root
4102 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
4106 // Return the remaining portion as the file name
4109 *FileName = uniRemainingPath;
4111 *ParsedFileName = uniRemainingPath;
4113 *NameArray = pNameArray;
4115 *VolumeCB = pVolumeCB;
4118 // Increment our reference on the volume
4121 lCount = AFSVolumeIncrement( pVolumeCB,
4122 AFS_VOLUME_REFERENCE_PARSE_NAME);
4124 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4125 AFS_TRACE_LEVEL_VERBOSE,
4126 "AFSParseName Increment2 count on global volume %p Cnt %d\n",
4132 if( NT_SUCCESS( ntStatus))
4135 if( *ParentDirectoryCB != NULL)
4138 lCount = InterlockedIncrement( &(*ParentDirectoryCB)->DirOpenReferenceCount);
4140 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4141 AFS_TRACE_LEVEL_VERBOSE,
4142 "AFSParseName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4143 &(*ParentDirectoryCB)->NameInformation.FileName,
4144 (*ParentDirectoryCB),
4150 if( *VolumeCB != NULL)
4152 ASSERT( (*VolumeCB)->VolumeReferenceCount > 0);
4155 if( ntStatus != STATUS_SUCCESS)
4158 if( pNameArray != NULL)
4161 AFSFreeNameArray( pNameArray);
4170 AFSCheckCellName( IN GUID *AuthGroup,
4171 IN UNICODE_STRING *CellName,
4172 OUT AFSDirectoryCB **ShareDirEntry)
4175 NTSTATUS ntStatus = STATUS_SUCCESS;
4176 UNICODE_STRING uniName;
4177 AFSDirEnumEntry *pDirEnumEntry = NULL;
4178 AFSDirHdr *pDirHdr = &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr;
4179 AFSDirectoryCB *pDirNode = NULL;
4180 UNICODE_STRING uniDirName, uniTargetName;
4181 AFSVolumeCB *pVolumeCB = NULL;
4188 // Look for some default names we will not handle
4191 RtlInitUnicodeString( &uniName,
4194 if( RtlCompareUnicodeString( &uniName,
4199 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4202 RtlInitUnicodeString( &uniName,
4205 if( RtlCompareUnicodeString( &uniName,
4210 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4213 RtlInitUnicodeString( &uniName,
4216 if( RtlCompareUnicodeString( &uniName,
4221 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4224 RtlInitUnicodeString( &uniName,
4227 if( RtlCompareUnicodeString( &uniName,
4232 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4236 // OK, ask the CM about this component name
4239 ntStatus = AFSEvaluateTargetByName( AuthGroup,
4240 &AFSGlobalRoot->ObjectInformation,
4245 if( !NT_SUCCESS( ntStatus))
4248 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4249 AFS_TRACE_LEVEL_WARNING,
4250 "AFSCheckCellName entry %wZ does not exist parent FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4252 AFSGlobalRoot->ObjectInformation.FileId.Cell,
4253 AFSGlobalRoot->ObjectInformation.FileId.Volume,
4254 AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4255 AFSGlobalRoot->ObjectInformation.FileId.Unique,
4258 try_return( ntStatus);
4262 // OK, we have a dir enum entry back so add it to the root node
4265 uniDirName = *CellName;
4267 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
4268 uniTargetName.MaximumLength = uniTargetName.Length;
4269 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
4272 // Is this entry a root volume entry?
4275 if( pDirEnumEntry->FileId.Cell != AFSGlobalRoot->ObjectInformation.FileId.Cell ||
4276 pDirEnumEntry->FileId.Volume != AFSGlobalRoot->ObjectInformation.FileId.Volume)
4280 // Build the root volume entry
4283 ntStatus = AFSBuildRootVolume( AuthGroup,
4284 &pDirEnumEntry->FileId,
4288 // On success returns with a volume reference count held
4291 if( !NT_SUCCESS( ntStatus))
4293 try_return( ntStatus);
4296 *ShareDirEntry = pVolumeCB->DirectoryCB;
4298 lCount = InterlockedIncrement( &pVolumeCB->DirectoryCB->DirOpenReferenceCount);
4300 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4301 AFS_TRACE_LEVEL_VERBOSE,
4302 "AFSCheckCellName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4303 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4304 pVolumeCB->DirectoryCB,
4308 lCount = AFSVolumeDecrement( pVolumeCB,
4309 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4311 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4312 AFS_TRACE_LEVEL_VERBOSE,
4313 "AFSCheckCellName Decrement count on volume %p Cnt %d\n",
4320 lCount = InterlockedIncrement( &pDirHdr->ContentIndex);
4322 pDirNode = AFSInitDirEntry( &AFSGlobalRoot->ObjectInformation,
4328 if( pDirNode == NULL)
4331 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4335 // Init the short name if we have one
4338 if( pDirEnumEntry->ShortNameLength > 0)
4341 pDirNode->NameInformation.ShortNameLength = pDirEnumEntry->ShortNameLength;
4343 RtlCopyMemory( pDirNode->NameInformation.ShortName,
4344 pDirEnumEntry->ShortName,
4345 pDirNode->NameInformation.ShortNameLength);
4348 AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4352 // Insert the node into the name tree
4355 ASSERT( ExIsResourceAcquiredExclusiveLite( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock));
4357 if( pDirHdr->CaseSensitiveTreeHead == NULL)
4360 pDirHdr->CaseSensitiveTreeHead = pDirNode;
4365 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( pDirHdr->CaseSensitiveTreeHead,
4369 AFSDeleteDirEntry( &AFSGlobalRoot->ObjectInformation,
4372 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4374 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4378 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
4380 if( pDirHdr->CaseInsensitiveTreeHead == NULL)
4383 pDirHdr->CaseInsensitiveTreeHead = pDirNode;
4385 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
4390 AFSInsertCaseInsensitiveDirEntry( pDirHdr->CaseInsensitiveTreeHead,
4394 if( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead == NULL)
4397 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead = pDirNode;
4402 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
4404 pDirNode->ListEntry.bLink = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail;
4407 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail = pDirNode;
4409 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
4411 lCount = InterlockedIncrement( &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeCount);
4413 AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
4414 AFS_TRACE_LEVEL_VERBOSE,
4415 "AFSCheckCellName Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
4416 &pDirNode->NameInformation.FileName,
4418 AFSGlobalRoot->ObjectInformation.FileId.Cell,
4419 AFSGlobalRoot->ObjectInformation.FileId.Volume,
4420 AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4421 AFSGlobalRoot->ObjectInformation.FileId.Unique));
4423 lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
4425 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4426 AFS_TRACE_LEVEL_VERBOSE,
4427 "AFSCheckCellName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
4428 &pDirNode->NameInformation.FileName,
4433 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4436 // Pass back the dir node
4439 *ShareDirEntry = pDirNode;
4444 if( pDirEnumEntry != NULL)
4447 AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_31_TAG);
4455 AFSBuildMountPointTarget( IN GUID *AuthGroup,
4456 IN AFSDirectoryCB *DirectoryCB,
4457 OUT AFSVolumeCB **TargetVolumeCB)
4460 NTSTATUS ntStatus = STATUS_SUCCESS;
4461 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4462 AFSDirEnumEntry *pDirEntry = NULL;
4463 ULONGLONG ullIndex = 0;
4464 AFSVolumeCB *pVolumeCB = NULL;
4465 AFSFileID stTargetFileID;
4467 BOOLEAN bReleaseVolumeLock = FALSE;
4473 // Loop on each entry, building the chain until we encounter the final target
4476 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4477 AFS_TRACE_LEVEL_VERBOSE_2,
4478 "AFSBuildMountPointTarget Building target directory for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4479 &DirectoryCB->NameInformation.FileName,
4480 DirectoryCB->ObjectInformation->FileId.Cell,
4481 DirectoryCB->ObjectInformation->FileId.Volume,
4482 DirectoryCB->ObjectInformation->FileId.Vnode,
4483 DirectoryCB->ObjectInformation->FileId.Unique));
4486 // Do we need to evaluate the node?
4489 //if( DirectoryCB->ObjectInformation->TargetFileId.Vnode == 0 &&
4490 // DirectoryCB->ObjectInformation->TargetFileId.Unique == 0)
4494 // Go evaluate the current target to get the target fid
4497 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4498 AFS_TRACE_LEVEL_VERBOSE_2,
4499 "AFSBuildMountPointTarget Evaluating target %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4500 &DirectoryCB->NameInformation.FileName,
4501 DirectoryCB->ObjectInformation->FileId.Cell,
4502 DirectoryCB->ObjectInformation->FileId.Volume,
4503 DirectoryCB->ObjectInformation->FileId.Vnode,
4504 DirectoryCB->ObjectInformation->FileId.Unique));
4506 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
4511 if( !NT_SUCCESS( ntStatus))
4514 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4515 AFS_TRACE_LEVEL_ERROR,
4516 "AFSBuildMountPointTarget Failed to evaluate target %wZ Status %08lX\n",
4517 &DirectoryCB->NameInformation.FileName,
4520 try_return( ntStatus);
4523 if( pDirEntry->TargetFileId.Vnode == 0 &&
4524 pDirEntry->TargetFileId.Unique == 0)
4527 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4528 AFS_TRACE_LEVEL_ERROR,
4529 "AFSBuildMountPointTarget Target %wZ FID %08lX-%08lX-%08lX-%08lX service returned zero FID\n",
4530 &DirectoryCB->NameInformation.FileName,
4531 DirectoryCB->ObjectInformation->FileId.Cell,
4532 DirectoryCB->ObjectInformation->FileId.Volume,
4533 DirectoryCB->ObjectInformation->FileId.Vnode,
4534 DirectoryCB->ObjectInformation->FileId.Unique));
4536 try_return( ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED);
4539 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
4542 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
4543 &DirectoryCB->Flags,
4544 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4545 (USHORT)pDirEntry->TargetNameLength);
4547 if( !NT_SUCCESS( ntStatus))
4550 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4552 try_return( ntStatus);
4555 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4557 DirectoryCB->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
4560 stTargetFileID = DirectoryCB->ObjectInformation->TargetFileId;
4563 // Try to locate this FID. First the volume then the
4567 ullIndex = AFSCreateHighIndex( &stTargetFileID);
4569 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4570 AFS_TRACE_LEVEL_VERBOSE,
4571 "AFSBuildMountPointTarget Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4572 &pDevExt->Specific.RDR.VolumeTreeLock,
4573 PsGetCurrentThread()));
4575 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4578 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4579 AFS_TRACE_LEVEL_VERBOSE_2,
4580 "AFSBuildMountPointTarget Locating volume for target %I64X\n",
4583 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4585 (AFSBTreeEntry **)&pVolumeCB);
4588 // We can be processing a request for a target that is on a volume
4589 // we have never seen before.
4592 if( pVolumeCB == NULL)
4596 // Locking is held correctly in init routine
4599 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4602 // Go init the root of the volume
4605 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4606 AFS_TRACE_LEVEL_VERBOSE_2,
4607 "AFSBuildMountPointTarget Initializing root for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4608 &DirectoryCB->NameInformation.FileName,
4609 DirectoryCB->ObjectInformation->FileId.Cell,
4610 DirectoryCB->ObjectInformation->FileId.Volume,
4611 DirectoryCB->ObjectInformation->FileId.Vnode,
4612 DirectoryCB->ObjectInformation->FileId.Unique));
4614 ntStatus = AFSInitVolume( AuthGroup,
4616 AFS_VOLUME_REFERENCE_MOUNTPT,
4619 if( !NT_SUCCESS( ntStatus))
4622 try_return( ntStatus);
4626 // pVolumeCB->VolumeLock held exclusive and
4627 // pVolumeCB->VolumeReferenceCount has been incremented
4628 // pVolumeCB->RootFcb == NULL
4631 bReleaseVolumeLock = TRUE;
4637 // AFSInitVolume returns with a VolumeReferenceCount
4638 // obtain one to match
4641 lCount = AFSVolumeIncrement( pVolumeCB,
4642 AFS_VOLUME_REFERENCE_MOUNTPT);
4644 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4645 AFS_TRACE_LEVEL_VERBOSE,
4646 "AFSBuildMountPointTarget Increment count on volume %p Cnt %d\n",
4650 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4653 if( pVolumeCB->RootFcb == NULL)
4656 if ( bReleaseVolumeLock == FALSE)
4659 AFSAcquireExcl( pVolumeCB->VolumeLock,
4662 bReleaseVolumeLock = TRUE;
4666 // Initialize the root fcb for this volume
4669 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4672 if( !NT_SUCCESS( ntStatus))
4675 lCount = AFSVolumeDecrement( pVolumeCB,
4676 AFS_VOLUME_REFERENCE_MOUNTPT);
4678 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4679 AFS_TRACE_LEVEL_VERBOSE,
4680 "AFSBuildMountPoint Decrement count on volume %p Cnt %d\n",
4684 AFSReleaseResource( pVolumeCB->VolumeLock);
4686 try_return( ntStatus);
4690 // Drop the lock acquired above
4693 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4696 if ( bReleaseVolumeLock == TRUE)
4699 AFSReleaseResource( pVolumeCB->VolumeLock);
4702 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4703 AFS_TRACE_LEVEL_VERBOSE_2,
4704 "AFSBuildMountPointTarget Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4705 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4706 pVolumeCB->ObjectInformation.FileId.Cell,
4707 pVolumeCB->ObjectInformation.FileId.Volume,
4708 pVolumeCB->ObjectInformation.FileId.Vnode,
4709 pVolumeCB->ObjectInformation.FileId.Unique));
4711 *TargetVolumeCB = pVolumeCB;
4718 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
4726 AFSBuildRootVolume( IN GUID *AuthGroup,
4727 IN AFSFileID *FileId,
4728 OUT AFSVolumeCB **TargetVolumeCB)
4731 NTSTATUS ntStatus = STATUS_SUCCESS;
4732 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4733 ULONGLONG ullIndex = 0;
4734 AFSVolumeCB *pVolumeCB = NULL;
4736 BOOLEAN bReleaseVolumeLock = FALSE;
4741 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4742 AFS_TRACE_LEVEL_VERBOSE_2,
4743 "AFSBuildRootVolume Building target volume for FID %08lX-%08lX-%08lX-%08lX\n",
4749 ullIndex = AFSCreateHighIndex( FileId);
4751 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4752 AFS_TRACE_LEVEL_VERBOSE,
4753 "AFSBuildRootVolume Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4754 &pDevExt->Specific.RDR.VolumeTreeLock,
4755 PsGetCurrentThread()));
4757 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4760 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4761 AFS_TRACE_LEVEL_VERBOSE_2,
4762 "AFSBuildRootVolume Locating volume for target %I64X\n",
4765 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4767 (AFSBTreeEntry **)&pVolumeCB);
4770 // We can be processing a request for a target that is on a volume
4771 // we have never seen before.
4774 if( pVolumeCB == NULL)
4778 // Locking is held correctly in init routine
4781 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4784 // Go init the root of the volume
4787 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4788 AFS_TRACE_LEVEL_VERBOSE_2,
4789 "AFSBuildRootVolume Initializing root for FID %08lX-%08lX-%08lX-%08lX\n",
4795 ntStatus = AFSInitVolume( AuthGroup,
4797 AFS_VOLUME_REFERENCE_BUILD_ROOT,
4800 if( !NT_SUCCESS( ntStatus))
4803 try_return( ntStatus);
4807 // pVolumeCB->VolumeLock is held exclusive
4808 // pVolumeCB->VolumeReferenceCount has been incremented
4809 // pVolumeCB->RootFcb == NULL
4812 bReleaseVolumeLock = TRUE;
4818 // AFSInitVolume returns with a VolumeReferenceCount
4819 // obtain one to match
4822 lCount = AFSVolumeIncrement( pVolumeCB,
4823 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4825 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4826 AFS_TRACE_LEVEL_VERBOSE,
4827 "AFSBuildRootVolume Increment count on volume %p Cnt %d\n",
4831 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4835 if( pVolumeCB->RootFcb == NULL)
4838 if ( bReleaseVolumeLock == FALSE)
4841 AFSAcquireExcl( pVolumeCB->VolumeLock,
4844 bReleaseVolumeLock = TRUE;
4848 // Initialize the root fcb for this volume
4851 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4854 if( !NT_SUCCESS( ntStatus))
4857 lCount = AFSVolumeDecrement( pVolumeCB,
4858 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4860 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4861 AFS_TRACE_LEVEL_VERBOSE,
4862 "AFSBuildRootVolume Decrement count on volume %p Cnt %d\n",
4866 AFSReleaseResource( pVolumeCB->VolumeLock);
4868 try_return( ntStatus);
4872 // Drop the lock acquired above
4875 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4878 if ( bReleaseVolumeLock == TRUE)
4881 AFSReleaseResource( pVolumeCB->VolumeLock);
4884 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4885 AFS_TRACE_LEVEL_VERBOSE_2,
4886 "AFSBuildRootVolume Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4887 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4888 pVolumeCB->ObjectInformation.FileId.Cell,
4889 pVolumeCB->ObjectInformation.FileId.Volume,
4890 pVolumeCB->ObjectInformation.FileId.Vnode,
4891 pVolumeCB->ObjectInformation.FileId.Unique));
4893 *TargetVolumeCB = pVolumeCB;
4904 AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
4905 IN PFILE_OBJECT FileObject,
4906 IN UNICODE_STRING *RemainingPath,
4910 NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
4911 UNICODE_STRING uniReparseName;
4912 UNICODE_STRING uniMUPDeviceName;
4913 UNICODE_STRING uniIOMgrDeviceName;
4914 AFSDirEnumEntry *pDirEntry = NULL;
4920 // Build up the name to reparse
4923 RtlInitUnicodeString( &uniMUPDeviceName,
4926 RtlInitUnicodeString( &uniIOMgrDeviceName,
4929 uniReparseName.Length = 0;
4930 uniReparseName.Buffer = NULL;
4933 // Be sure we have a target name
4936 if( DirEntry->NameInformation.TargetName.Length == 0)
4939 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
4944 if( !NT_SUCCESS( ntStatus) ||
4945 pDirEntry->TargetNameLength == 0)
4948 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4949 AFS_TRACE_LEVEL_ERROR,
4950 "AFSProcessDFSLink EvaluateTargetByID failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4951 &DirEntry->NameInformation.FileName,
4952 DirEntry->ObjectInformation->FileId.Cell,
4953 DirEntry->ObjectInformation->FileId.Volume,
4954 DirEntry->ObjectInformation->FileId.Vnode,
4955 DirEntry->ObjectInformation->FileId.Unique,
4958 if( NT_SUCCESS( ntStatus))
4961 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
4964 try_return( ntStatus);
4968 // Update the target name
4971 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
4974 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
4976 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4977 (USHORT)pDirEntry->TargetNameLength);
4979 if( !NT_SUCCESS( ntStatus))
4982 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4983 AFS_TRACE_LEVEL_ERROR,
4984 "AFSProcessDFSLink UpdateTargetName failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4985 &DirEntry->NameInformation.FileName,
4986 DirEntry->ObjectInformation->FileId.Cell,
4987 DirEntry->ObjectInformation->FileId.Volume,
4988 DirEntry->ObjectInformation->FileId.Vnode,
4989 DirEntry->ObjectInformation->FileId.Unique,
4992 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4994 try_return( ntStatus);
4997 AFSConvertToShared( &DirEntry->NonPaged->Lock);
5001 AFSAcquireShared( &DirEntry->NonPaged->Lock,
5005 uniReparseName.MaximumLength = uniMUPDeviceName.Length +
5007 DirEntry->NameInformation.TargetName.Length +
5010 if( RemainingPath != NULL &&
5011 RemainingPath->Length > 0)
5014 uniReparseName.MaximumLength += RemainingPath->Length;
5018 // Allocate the reparse buffer
5021 uniReparseName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5022 uniReparseName.MaximumLength,
5023 AFS_REPARSE_NAME_TAG);
5025 if( uniReparseName.Buffer == NULL)
5028 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5029 AFS_TRACE_LEVEL_ERROR,
5030 "AFSProcessDFSLink uniReparseName.Buffer == NULL Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
5031 &DirEntry->NameInformation.FileName,
5032 DirEntry->ObjectInformation->FileId.Cell,
5033 DirEntry->ObjectInformation->FileId.Volume,
5034 DirEntry->ObjectInformation->FileId.Vnode,
5035 DirEntry->ObjectInformation->FileId.Unique,
5036 STATUS_INSUFFICIENT_RESOURCES));
5038 AFSReleaseResource( &DirEntry->NonPaged->Lock);
5040 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5044 // Start building the name
5047 if ( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\' &&
5048 DirEntry->NameInformation.TargetName.Buffer[ 1] == L':')
5051 RtlCopyMemory( uniReparseName.Buffer,
5052 uniIOMgrDeviceName.Buffer,
5053 uniIOMgrDeviceName.Length);
5055 uniReparseName.Length = uniIOMgrDeviceName.Length;
5060 RtlCopyMemory( uniReparseName.Buffer,
5061 uniMUPDeviceName.Buffer,
5062 uniMUPDeviceName.Length);
5064 uniReparseName.Length = uniMUPDeviceName.Length;
5066 if( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\')
5069 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
5071 uniReparseName.Length += sizeof( WCHAR);
5075 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
5076 DirEntry->NameInformation.TargetName.Buffer,
5077 DirEntry->NameInformation.TargetName.Length);
5079 uniReparseName.Length += DirEntry->NameInformation.TargetName.Length;
5081 AFSReleaseResource( &DirEntry->NonPaged->Lock);
5083 if( RemainingPath != NULL &&
5084 RemainingPath->Length > 0)
5087 if( uniReparseName.Buffer[ (uniReparseName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
5088 RemainingPath->Buffer[ 0] != L'\\')
5091 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
5093 uniReparseName.Length += sizeof( WCHAR);
5096 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
5097 RemainingPath->Buffer,
5098 RemainingPath->Length);
5100 uniReparseName.Length += RemainingPath->Length;
5104 // Update the name in the file object
5107 if( FileObject->FileName.Buffer != NULL)
5110 AFSExFreePoolWithTag( FileObject->FileName.Buffer, 0);
5113 FileObject->FileName = uniReparseName;
5115 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5116 AFS_TRACE_LEVEL_VERBOSE,
5117 "AFSProcessDFSLink Reparsing access to Fcb %wZ FID %08lX-%08lX-%08lX-%08lX to %wZ\n",
5118 &DirEntry->NameInformation.FileName,
5119 DirEntry->ObjectInformation->FileId.Cell,
5120 DirEntry->ObjectInformation->FileId.Volume,
5121 DirEntry->ObjectInformation->FileId.Vnode,
5122 DirEntry->ObjectInformation->FileId.Unique,
5126 // Return status reparse ...
5129 ntStatus = STATUS_REPARSE;
5136 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);