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,
69 OUT PUNICODE_STRING TargetName)
72 NTSTATUS ntStatus = STATUS_SUCCESS;
73 UNICODE_STRING uniPathName, uniComponentName, uniRemainingPath, uniSearchName, uniFullPathName;
75 AFSDirectoryCB *pDirEntry = NULL, *pParentDirEntry = NULL;
76 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
77 UNICODE_STRING uniSysName;
78 ULONG ulSubstituteIndex = 0;
79 BOOLEAN bSubstituteName = FALSE;
80 AFSNameArrayHdr *pNameArray = NameArray;
81 BOOLEAN bAllocatedSymLinkBuffer = FALSE;
82 UNICODE_STRING uniRelativeName, uniNoOpName;
83 AFSObjectInfoCB *pCurrentObject = NULL;
84 AFSObjectInfoCB *pParentObjectInfo = NULL;
85 AFSVolumeCB *pCurrentVolume = NULL;
86 AFSVolumeCB *pTargetVolume = NULL;
87 BOOLEAN bReleaseCurrentVolume = FALSE;
88 LONG VolumeReferenceReason;
89 BOOLEAN bSubstitutedName = FALSE;
95 ASSERT( *OutVolumeCB != VolumeCB);
97 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
98 AFS_TRACE_LEVEL_VERBOSE_2,
99 "AFSLocateNameEntry (FO: %p) Processing full name %wZ\n",
103 RtlInitUnicodeString( &uniSysName,
106 RtlInitUnicodeString( &uniRelativeName,
109 RtlInitUnicodeString( &uniNoOpName,
113 // Cleanup some parameters
116 if( ComponentName != NULL)
119 ComponentName->Length = 0;
120 ComponentName->MaximumLength = 0;
121 ComponentName->Buffer = NULL;
125 // We will parse through the filename, locating the directory nodes until we encounter a cache miss
126 // Starting at the root node
129 pParentDirEntry = NULL;
131 pDirEntry = ParentDirectoryCB;
134 // Increment our reference on this dir entry
137 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
139 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
140 AFS_TRACE_LEVEL_VERBOSE,
141 "AFSLocateNameEntry Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
142 &pDirEntry->NameInformation.FileName,
147 pCurrentVolume = VolumeCB;
149 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
151 lCount = AFSVolumeIncrement( pCurrentVolume,
152 VolumeReferenceReason);
154 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
155 AFS_TRACE_LEVEL_VERBOSE,
156 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
158 VolumeReferenceReason,
161 bReleaseCurrentVolume = TRUE;
163 uniPathName = *ParsedPathName;
165 uniFullPathName = *RootPathName;
167 uniComponentName.Length = uniComponentName.MaximumLength = 0;
168 uniComponentName.Buffer = NULL;
170 uniRemainingPath.Length = uniRemainingPath.MaximumLength = 0;
171 uniRemainingPath.Buffer = NULL;
173 uniSearchName.Length = uniSearchName.MaximumLength = 0;
174 uniSearchName.Buffer = NULL;
179 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
181 ASSERT( pDirEntry->DirOpenReferenceCount > 0);
184 // Check our total link count for this name array
187 if( pNameArray->LinkCount >= (LONG)pDevExt->Specific.RDR.MaxLinkCount)
190 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
193 pCurrentObject = pDirEntry->ObjectInformation;
195 KeQueryTickCount( &pCurrentObject->LastAccessCount);
198 // Check that the directory entry is not deleted or pending delete
201 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
204 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
205 AFS_TRACE_LEVEL_ERROR,
206 "AFSLocateNameEntry (FO: %p) Deleted parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
208 &pDirEntry->NameInformation.FileName,
209 pCurrentObject->FileId.Cell,
210 pCurrentObject->FileId.Volume,
211 pCurrentObject->FileId.Vnode,
212 pCurrentObject->FileId.Unique,
213 STATUS_FILE_DELETED));
215 try_return( ntStatus = STATUS_FILE_DELETED);
218 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
221 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
222 AFS_TRACE_LEVEL_ERROR,
223 "AFSLocateNameEntry (FO: %p) Delete pending on %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
225 &pDirEntry->NameInformation.FileName,
226 pCurrentObject->FileId.Cell,
227 pCurrentObject->FileId.Volume,
228 pCurrentObject->FileId.Vnode,
229 pCurrentObject->FileId.Unique,
230 STATUS_DELETE_PENDING));
232 try_return( ntStatus = STATUS_DELETE_PENDING);
236 // Check if the directory requires verification
239 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
240 ( pCurrentObject->FileType != AFS_FILE_TYPE_DIRECTORY ||
241 !AFSIsEnumerationInProcess( pCurrentObject)))
244 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
245 AFS_TRACE_LEVEL_VERBOSE,
246 "AFSLocateNameEntry (FO: %p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
248 &pDirEntry->NameInformation.FileName,
249 pCurrentObject->FileId.Cell,
250 pCurrentObject->FileId.Volume,
251 pCurrentObject->FileId.Vnode,
252 pCurrentObject->FileId.Unique));
255 // Directory TreeLock should be exclusively held
258 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
261 ntStatus = AFSVerifyEntry( AuthGroup,
265 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
267 if( !NT_SUCCESS( ntStatus))
270 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
271 AFS_TRACE_LEVEL_ERROR,
272 "AFSLocateNameEntry (FO: %p) Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
274 &pDirEntry->NameInformation.FileName,
275 pCurrentObject->FileId.Cell,
276 pCurrentObject->FileId.Volume,
277 pCurrentObject->FileId.Vnode,
278 pCurrentObject->FileId.Unique,
281 try_return( ntStatus);
286 // Ensure the parent node has been evaluated, if not then go do it now
289 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) ||
290 pCurrentObject->FileType == AFS_FILE_TYPE_UNKNOWN)
293 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
294 AFS_TRACE_LEVEL_VERBOSE,
295 "AFSLocateNameEntry (FO: %p) Evaluating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
297 &pDirEntry->NameInformation.FileName,
298 pCurrentObject->FileId.Cell,
299 pCurrentObject->FileId.Volume,
300 pCurrentObject->FileId.Vnode,
301 pCurrentObject->FileId.Unique));
303 ntStatus = AFSEvaluateNode( AuthGroup,
306 if( !NT_SUCCESS( ntStatus))
309 if ( ntStatus == STATUS_NOT_A_DIRECTORY)
312 if ( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
315 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
316 AFS_TRACE_LEVEL_ERROR,
317 "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT NULL Status %08lX\n",
319 &pDirEntry->NameInformation.FileName,
320 pCurrentObject->FileId.Cell,
321 pCurrentObject->FileId.Volume,
322 pCurrentObject->FileId.Vnode,
323 pCurrentObject->FileId.Unique,
329 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
330 AFS_TRACE_LEVEL_ERROR,
331 "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT %08lX-%08lX-%08lX-%08lX Status %08lX\n",
333 &pDirEntry->NameInformation.FileName,
334 pCurrentObject->FileId.Cell,
335 pCurrentObject->FileId.Volume,
336 pCurrentObject->FileId.Vnode,
337 pCurrentObject->FileId.Unique,
338 pCurrentObject->ParentFileId.Cell,
339 pCurrentObject->ParentFileId.Volume,
340 pCurrentObject->ParentFileId.Vnode,
341 pCurrentObject->ParentFileId.Unique,
347 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
348 AFS_TRACE_LEVEL_ERROR,
349 "AFSLocateNameEntry (FO: %p) Failed to evaluate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
351 &pDirEntry->NameInformation.FileName,
352 pCurrentObject->FileId.Cell,
353 pCurrentObject->FileId.Volume,
354 pCurrentObject->FileId.Vnode,
355 pCurrentObject->FileId.Unique,
359 try_return( ntStatus);
362 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
366 // If this is a mount point or symlink then go get the real directory node
369 switch( pCurrentObject->FileType)
372 case AFS_FILE_TYPE_SYMLINK:
375 UNICODE_STRING uniTempName;
376 WCHAR *pTmpBuffer = NULL;
380 // Check if the flag is set to NOT evaluate a symlink
381 // and we are done with the parsing
384 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL) &&
385 uniRemainingPath.Length == 0)
389 // Pass back the directory entries
392 *OutParentDirectoryCB = pParentDirEntry;
394 pParentDirEntry = NULL;
396 *OutDirectoryCB = pDirEntry;
400 *OutVolumeCB = pCurrentVolume;
402 *OutVolumeReferenceReason = VolumeReferenceReason;
404 bReleaseCurrentVolume = FALSE;
406 *RootPathName = uniFullPathName;
408 try_return( ntStatus);
411 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
414 AFSAcquireExcl( &pDirEntry->NonPaged->Lock,
417 if( pDirEntry->NameInformation.TargetName.Length == 0)
421 // We'll reset the DV to ensure we validate the metadata content
424 pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
426 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
428 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
429 AFS_TRACE_LEVEL_VERBOSE,
430 "AFSLocateNameEntry (FO: %p) Verifying symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
432 &pDirEntry->NameInformation.FileName,
433 pCurrentObject->FileId.Cell,
434 pCurrentObject->FileId.Volume,
435 pCurrentObject->FileId.Vnode,
436 pCurrentObject->FileId.Unique));
439 // Directory TreeLock should be exclusively held
442 ntStatus = AFSVerifyEntry( AuthGroup,
446 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
448 if( !NT_SUCCESS( ntStatus))
451 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
452 AFS_TRACE_LEVEL_ERROR,
453 "AFSLocateNameEntry (FO: %p) Failed to verify symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
455 &pDirEntry->NameInformation.FileName,
456 pCurrentObject->FileId.Cell,
457 pCurrentObject->FileId.Volume,
458 pCurrentObject->FileId.Vnode,
459 pCurrentObject->FileId.Unique,
462 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
464 try_return( ntStatus);
468 // If the type changed then reprocess this entry
471 if( pCurrentObject->FileType != AFS_FILE_TYPE_SYMLINK)
474 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
482 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
486 // If we were given a zero length target name then deny access to the entry
489 if( pDirEntry->NameInformation.TargetName.Length == 0)
492 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
494 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
495 AFS_TRACE_LEVEL_ERROR,
496 "AFSLocateNameEntry (FO: %p) Failed to retrieve target name for symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
498 &pDirEntry->NameInformation.FileName,
499 pCurrentObject->FileId.Cell,
500 pCurrentObject->FileId.Volume,
501 pCurrentObject->FileId.Vnode,
502 pCurrentObject->FileId.Unique,
505 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
507 try_return( ntStatus);
510 if( AFSIsRelativeName( &pDirEntry->NameInformation.TargetName))
513 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
514 AFS_TRACE_LEVEL_VERBOSE,
515 "AFSLocateNameEntry (FO: %p) Processing relative symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
517 &pDirEntry->NameInformation.TargetName,
518 &pDirEntry->NameInformation.FileName,
519 pCurrentObject->FileId.Cell,
520 pCurrentObject->FileId.Volume,
521 pCurrentObject->FileId.Vnode,
522 pCurrentObject->FileId.Unique));
525 // We'll substitute this name into the current process name
526 // starting at where we sit in the path
529 uniTempName.Length = 0;
530 uniTempName.MaximumLength = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer) +
531 pDirEntry->NameInformation.TargetName.Length +
533 uniRemainingPath.Length;
535 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
536 uniTempName.MaximumLength,
537 AFS_NAME_BUFFER_ONE_TAG);
539 if( uniTempName.Buffer == NULL)
542 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
544 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
548 // We have so first copy in the portion up to the component
552 RtlCopyMemory( uniTempName.Buffer,
553 uniFullPathName.Buffer,
554 (ULONG)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer));
556 uniTempName.Length = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer);
558 if( bAllocatedSymLinkBuffer ||
562 pTmpBuffer = uniFullPathName.Buffer;
565 bAllocatedSymLinkBuffer = TRUE;
568 // Have we parsed this name yet? Better have at least once ...
571 if( uniComponentName.Length == 0)
577 // Copy in the target name ...
580 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
581 pDirEntry->NameInformation.TargetName.Buffer,
582 pDirEntry->NameInformation.TargetName.Length);
584 uniPathName.Buffer = &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)];
586 uniPathName.Length += pDirEntry->NameInformation.TargetName.Length;
587 uniPathName.MaximumLength = uniTempName.MaximumLength;
589 uniTempName.Length += pDirEntry->NameInformation.TargetName.Length;
592 // And now any remaining portion of the name
595 if( uniRemainingPath.Length > 0)
598 if( uniRemainingPath.Buffer[ 0] != L'\\')
601 uniRemainingPath.Buffer--;
602 uniRemainingPath.Length += sizeof( WCHAR);
604 uniPathName.Length += sizeof( WCHAR);
607 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
608 uniRemainingPath.Buffer,
609 uniRemainingPath.Length);
611 uniTempName.Length += uniRemainingPath.Length;
614 uniFullPathName = uniTempName;
616 if( pTmpBuffer != NULL)
619 AFSExFreePoolWithTag( pTmpBuffer, 0);
622 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
625 // Dereference the current entry ..
628 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
630 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
631 AFS_TRACE_LEVEL_VERBOSE,
632 "AFSLocateNameEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
633 &pDirEntry->NameInformation.FileName,
638 ASSERT( lCount >= 0);
641 // OK, need to back up one entry for the correct parent since the current
642 // entry we are on is the symlink itself
645 pDirEntry = AFSBackupEntry( pNameArray);
647 pCurrentObject = pDirEntry->ObjectInformation;
650 // Increment our reference on this dir entry
653 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
655 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
656 AFS_TRACE_LEVEL_VERBOSE,
657 "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
658 &pDirEntry->NameInformation.FileName,
663 if ( pParentDirEntry)
666 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
668 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
669 AFS_TRACE_LEVEL_VERBOSE,
670 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
671 &pParentDirEntry->NameInformation.FileName,
676 pParentDirEntry = NULL;
679 if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
682 pParentDirEntry = AFSGetParentEntry( pNameArray);
684 ASSERT( pParentDirEntry != pDirEntry);
686 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
688 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
689 AFS_TRACE_LEVEL_VERBOSE,
690 "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
691 &pParentDirEntry->NameInformation.FileName,
697 if ( pDirEntry->ObjectInformation->VolumeCB != pCurrentVolume)
700 lCount = AFSVolumeDecrement( pCurrentVolume,
701 VolumeReferenceReason);
703 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
704 AFS_TRACE_LEVEL_VERBOSE,
705 "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
707 VolumeReferenceReason,
710 pCurrentVolume = pDirEntry->ObjectInformation->VolumeCB;
712 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
714 lCount = AFSVolumeIncrement( pCurrentVolume,
715 VolumeReferenceReason);
717 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
718 AFS_TRACE_LEVEL_VERBOSE,
719 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
721 VolumeReferenceReason,
728 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
729 AFS_TRACE_LEVEL_VERBOSE,
730 "AFSLocateNameEntry (FO: %p) Processing absolute symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
732 &pDirEntry->NameInformation.TargetName,
733 &pDirEntry->NameInformation.FileName,
734 pCurrentObject->FileId.Cell,
735 pCurrentObject->FileId.Volume,
736 pCurrentObject->FileId.Vnode,
737 pCurrentObject->FileId.Unique));
739 if ( !AFSIsAbsoluteAFSName( &pDirEntry->NameInformation.TargetName))
742 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
743 AFS_TRACE_LEVEL_ERROR,
744 "AFSLocateNameEntry Name %wZ contains invalid server name\n",
745 &pDirEntry->NameInformation.TargetName));
748 // The correct response would be STATUS_OBJECT_PATH_INVALID
749 // but that prevents cmd.exe from performing a recursive
750 // directory enumeration when opening a directory entry
751 // that represents a symlink to an invalid path is discovered.
754 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
756 try_return( ntStatus = STATUS_OBJECT_PATH_NOT_FOUND);
760 // We'll substitute this name into the current process name
761 // starting at where we sit in the path
764 uniTempName.Length = 0;
765 uniTempName.MaximumLength = pDirEntry->NameInformation.TargetName.Length +
767 uniRemainingPath.Length;
769 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
770 uniTempName.MaximumLength,
771 AFS_NAME_BUFFER_TWO_TAG);
773 if( uniTempName.Buffer == NULL)
776 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
778 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
781 if( bAllocatedSymLinkBuffer ||
785 pTmpBuffer = uniFullPathName.Buffer;
788 bAllocatedSymLinkBuffer = TRUE;
791 // Have we parsed this name yet? Better have at least once ...
794 if( uniComponentName.Length == 0)
800 // Copy in the target name ...
803 RtlCopyMemory( uniTempName.Buffer,
804 &pDirEntry->NameInformation.TargetName.Buffer[ AFSMountRootName.Length/sizeof( WCHAR)],
805 pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length);
807 uniTempName.Length = pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length;
810 // And now any remaining portion of the name
813 if( uniRemainingPath.Length > 0)
816 if( uniRemainingPath.Buffer[ 0] != L'\\')
819 uniRemainingPath.Buffer--;
820 uniRemainingPath.Length += sizeof( WCHAR);
823 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
824 uniRemainingPath.Buffer,
825 uniRemainingPath.Length);
827 uniTempName.Length += uniRemainingPath.Length;
830 uniFullPathName = uniTempName;
832 uniPathName = uniTempName;
834 if( pTmpBuffer != NULL)
837 AFSExFreePoolWithTag( pTmpBuffer, 0);
840 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
843 // If our current volume is not the global root then make it so ...
846 if( pCurrentVolume != AFSGlobalRoot)
849 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
850 AFS_TRACE_LEVEL_VERBOSE,
851 "AFSLocateNameEntry (FO: %p) Current volume not global, resetting for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
853 &pDirEntry->NameInformation.FileName,
854 pCurrentObject->FileId.Cell,
855 pCurrentObject->FileId.Volume,
856 pCurrentObject->FileId.Vnode,
857 pCurrentObject->FileId.Unique));
859 lCount = AFSVolumeDecrement( pCurrentVolume,
860 VolumeReferenceReason);
862 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
863 AFS_TRACE_LEVEL_VERBOSE,
864 "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
866 VolumeReferenceReason,
869 pCurrentVolume = AFSGlobalRoot;
871 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
873 lCount = AFSVolumeIncrement( pCurrentVolume,
874 VolumeReferenceReason);
876 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
877 AFS_TRACE_LEVEL_VERBOSE,
878 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
880 VolumeReferenceReason,
885 // Dereference our current dir entry
888 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
890 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
891 AFS_TRACE_LEVEL_VERBOSE,
892 "AFSLocateNameEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
893 &pDirEntry->NameInformation.FileName,
898 ASSERT( lCount >= 0);
900 pDirEntry = pCurrentVolume->DirectoryCB;
902 pCurrentObject = pDirEntry->ObjectInformation;
905 // Reference the new dir entry
908 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
910 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
911 AFS_TRACE_LEVEL_VERBOSE,
912 "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
913 &pDirEntry->NameInformation.FileName,
919 // Reset the name array
920 // Persist the link count in the name array
923 lLinkCount = pNameArray->LinkCount;
925 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
926 AFS_TRACE_LEVEL_VERBOSE,
927 "AFSLocateNameEntry (FO: %p) Resetting name array for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
929 &pDirEntry->NameInformation.FileName,
930 pCurrentObject->FileId.Cell,
931 pCurrentObject->FileId.Volume,
932 pCurrentObject->FileId.Vnode,
933 pCurrentObject->FileId.Unique));
935 AFSResetNameArray( pNameArray,
938 pNameArray->LinkCount = lLinkCount;
940 if ( pParentDirEntry)
943 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
945 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
946 AFS_TRACE_LEVEL_VERBOSE,
947 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
948 &pParentDirEntry->NameInformation.FileName,
953 pParentDirEntry = NULL;
958 // Increment our link count
961 lCount = InterlockedIncrement( &pNameArray->LinkCount);
966 case AFS_FILE_TYPE_MOUNTPOINT:
970 // Check if the flag is set to NOT evaluate a mount point
971 // and we are done with the parsing
974 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL) &&
975 uniRemainingPath.Length == 0)
979 // Pass back the directory entries
982 *OutParentDirectoryCB = pParentDirEntry;
984 pParentDirEntry = NULL;
986 *OutDirectoryCB = pDirEntry;
990 *OutVolumeCB = pCurrentVolume;
992 *OutVolumeReferenceReason = VolumeReferenceReason;
994 bReleaseCurrentVolume = FALSE;
996 *RootPathName = uniFullPathName;
998 try_return( ntStatus);
1001 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1002 AFS_TRACE_LEVEL_VERBOSE,
1003 "AFSLocateNameEntry (FO: %p) Building MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1005 &pDirEntry->NameInformation.FileName,
1006 pCurrentObject->FileId.Cell,
1007 pCurrentObject->FileId.Volume,
1008 pCurrentObject->FileId.Vnode,
1009 pCurrentObject->FileId.Unique));
1012 // Go retrieve the target entry for this node
1013 // Release the current volume cb entry since we would
1014 // have lock inversion in the following call
1015 // Also decrement the ref count on the volume
1018 ntStatus = AFSBuildMountPointTarget( AuthGroup,
1022 if( !NT_SUCCESS( ntStatus))
1025 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1026 AFS_TRACE_LEVEL_ERROR,
1027 "AFSLocateNameEntry (FO: %p) Failed to build MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1029 &pDirEntry->NameInformation.FileName,
1030 pCurrentObject->FileId.Cell,
1031 pCurrentObject->FileId.Volume,
1032 pCurrentObject->FileId.Vnode,
1033 pCurrentObject->FileId.Unique,
1036 try_return( ntStatus);
1039 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
1041 lCount = AFSVolumeDecrement( pCurrentVolume,
1042 VolumeReferenceReason);
1044 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1045 AFS_TRACE_LEVEL_VERBOSE,
1046 "AFSLocateNameEntry Decrement2 count on volume %p Reason %u Cnt %d\n",
1048 VolumeReferenceReason,
1051 pCurrentVolume = pTargetVolume;
1053 pTargetVolume = NULL;
1055 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
1057 VolumeReferenceReason = AFS_VOLUME_REFERENCE_MOUNTPT;
1060 // We want to restart processing here on the new parent ...
1061 // Deref and ref count the entries
1064 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1066 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1067 AFS_TRACE_LEVEL_VERBOSE,
1068 "AFSLocateNameEntry Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
1069 &pDirEntry->NameInformation.FileName,
1074 ASSERT( lCount >= 0);
1076 pDirEntry = pCurrentVolume->DirectoryCB;
1078 pCurrentObject = pDirEntry->ObjectInformation;
1080 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1082 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1083 AFS_TRACE_LEVEL_VERBOSE,
1084 "AFSLocateNameEntry Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
1085 &pDirEntry->NameInformation.FileName,
1091 // The name array stores both the mount point and the target.
1092 // Insert the target.
1095 AFSInsertNextElement( pNameArray,
1098 if ( pParentDirEntry)
1101 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1103 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1104 AFS_TRACE_LEVEL_VERBOSE,
1105 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1106 &pParentDirEntry->NameInformation.FileName,
1111 pParentDirEntry = NULL;
1115 // Increment our link count
1118 lCount = InterlockedIncrement( &pNameArray->LinkCount);
1123 case AFS_FILE_TYPE_DFSLINK:
1126 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL) &&
1127 uniRemainingPath.Length == 0)
1131 // Pass back the directory entries
1134 *OutParentDirectoryCB = pParentDirEntry;
1136 pParentDirEntry = NULL;
1138 *OutDirectoryCB = pDirEntry;
1142 *OutVolumeCB = pCurrentVolume;
1144 *OutVolumeReferenceReason = VolumeReferenceReason;
1146 bReleaseCurrentVolume = FALSE;
1148 *RootPathName = uniFullPathName;
1150 try_return( ntStatus);
1154 // This is a DFS link so we need to update the file name and return STATUS_REPARSE to the
1155 // system for it to reevaluate it
1158 if( FileObject != NULL ||
1162 ntStatus = AFSProcessDFSLink( pDirEntry,
1172 // This is where we have been re-entered from an NP evaluation call via the BuildBranch()
1176 ntStatus = STATUS_INVALID_PARAMETER;
1179 if( ntStatus != STATUS_SUCCESS &&
1180 ntStatus != STATUS_REPARSE)
1183 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1184 AFS_TRACE_LEVEL_ERROR,
1185 "AFSLocateNameEntry (FO: %p) Failed to process DFSLink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1187 &pDirEntry->NameInformation.FileName,
1188 pCurrentObject->FileId.Cell,
1189 pCurrentObject->FileId.Volume,
1190 pCurrentObject->FileId.Vnode,
1191 pCurrentObject->FileId.Unique,
1195 try_return( ntStatus);
1198 case AFS_FILE_TYPE_UNKNOWN:
1199 case AFS_FILE_TYPE_INVALID:
1203 // Something was not processed ...
1206 try_return( ntStatus = STATUS_ACCESS_DENIED);
1209 } /* end of switch */
1212 // If the parent is not initialized then do it now
1215 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1216 !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED) &&
1217 uniPathName.Length > 0)
1220 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1221 AFS_TRACE_LEVEL_VERBOSE,
1222 "AFSLocateNameEntry (FO: %p) Enumerating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1224 &pDirEntry->NameInformation.FileName,
1225 pCurrentObject->FileId.Cell,
1226 pCurrentObject->FileId.Volume,
1227 pCurrentObject->FileId.Vnode,
1228 pCurrentObject->FileId.Unique));
1230 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1233 if( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1236 ntStatus = AFSEnumerateDirectory( AuthGroup,
1240 if( !NT_SUCCESS( ntStatus))
1243 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1245 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1246 AFS_TRACE_LEVEL_ERROR,
1247 "AFSLocateNameEntry (FO: %p) Failed to enumerate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1249 &pDirEntry->NameInformation.FileName,
1250 pCurrentObject->FileId.Cell,
1251 pCurrentObject->FileId.Volume,
1252 pCurrentObject->FileId.Vnode,
1253 pCurrentObject->FileId.Unique,
1256 try_return( ntStatus);
1260 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1262 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1265 if( uniPathName.Length > 0)
1268 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1269 AFS_TRACE_LEVEL_ERROR,
1270 "AFSLocateNameEntry (FO: %p) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1272 &pDirEntry->NameInformation.FileName,
1273 pCurrentObject->FileId.Cell,
1274 pCurrentObject->FileId.Volume,
1275 pCurrentObject->FileId.Vnode,
1276 pCurrentObject->FileId.Unique));
1278 // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1279 // one of the components of the path is not a directory. However, returning
1280 // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1281 // Instead IIS insists on treating the target file as if it is a directory containing
1282 // a potential web.config file. NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1283 // AFS will follow suit.
1285 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1290 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1291 AFS_TRACE_LEVEL_VERBOSE,
1292 "AFSLocateNameEntry (FO: %p) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1294 &pDirEntry->NameInformation.FileName,
1295 pCurrentObject->FileId.Cell,
1296 pCurrentObject->FileId.Volume,
1297 pCurrentObject->FileId.Vnode,
1298 pCurrentObject->FileId.Unique));
1301 // Pass back the directory entries
1304 *OutParentDirectoryCB = pParentDirEntry;
1306 pParentDirEntry = NULL;
1308 *OutDirectoryCB = pDirEntry;
1312 *OutVolumeCB = pCurrentVolume;
1314 *OutVolumeReferenceReason = VolumeReferenceReason;
1316 bReleaseCurrentVolume = FALSE;
1318 *RootPathName = uniFullPathName;
1321 try_return( ntStatus);
1325 // If we are at the end of the processing, set our returned information and get out
1328 if( uniPathName.Length == 0)
1331 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1332 AFS_TRACE_LEVEL_VERBOSE,
1333 "AFSLocateNameEntry (FO: %p) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1335 &pDirEntry->NameInformation.FileName,
1336 pCurrentObject->FileId.Cell,
1337 pCurrentObject->FileId.Volume,
1338 pCurrentObject->FileId.Vnode,
1339 pCurrentObject->FileId.Unique));
1342 // Pass back the directory entries
1345 *OutParentDirectoryCB = pParentDirEntry;
1347 pParentDirEntry = NULL;
1349 *OutDirectoryCB = pDirEntry;
1353 *OutVolumeCB = pCurrentVolume;
1355 *OutVolumeReferenceReason = VolumeReferenceReason;
1357 bReleaseCurrentVolume = FALSE;
1359 *RootPathName = uniFullPathName;
1361 try_return( ntStatus);
1365 // We may have returned to the top of the while( TRUE)
1367 if( bSubstituteName &&
1368 uniSearchName.Buffer != NULL)
1371 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1373 bSubstituteName = FALSE;
1375 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1376 uniSearchName.Buffer = NULL;
1379 ulSubstituteIndex = 1;
1381 ntStatus = STATUS_SUCCESS;
1384 // Get the next component name
1387 FsRtlDissectName( uniPathName,
1392 // Check for the . and .. in the path
1395 if( RtlCompareUnicodeString( &uniComponentName,
1400 uniPathName = uniRemainingPath;
1405 if( RtlCompareUnicodeString( &uniComponentName,
1410 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1411 AFS_TRACE_LEVEL_VERBOSE,
1412 "AFSLocateNameEntry (FO: %p) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1414 &pDirEntry->NameInformation.FileName,
1415 pCurrentObject->FileId.Cell,
1416 pCurrentObject->FileId.Volume,
1417 pCurrentObject->FileId.Vnode,
1418 pCurrentObject->FileId.Unique));
1421 // Need to back up one entry in the name array
1423 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1425 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1426 AFS_TRACE_LEVEL_VERBOSE,
1427 "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1428 &pDirEntry->NameInformation.FileName,
1433 ASSERT( lCount >= 0);
1435 pDirEntry = AFSBackupEntry( NameArray);
1437 if( pDirEntry == NULL)
1440 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1441 AFS_TRACE_LEVEL_ERROR,
1442 "AFSLocateNameEntry AFSBackupEntry failed\n"));
1444 try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1447 pCurrentObject = pDirEntry->ObjectInformation;
1449 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1451 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1452 AFS_TRACE_LEVEL_VERBOSE,
1453 "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1454 &pDirEntry->NameInformation.FileName,
1459 if ( pParentDirEntry)
1462 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1464 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1465 AFS_TRACE_LEVEL_VERBOSE,
1466 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1467 &pParentDirEntry->NameInformation.FileName,
1472 pParentDirEntry = NULL;
1475 if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1478 pParentDirEntry = AFSGetParentEntry( pNameArray);
1480 ASSERT( pParentDirEntry != pDirEntry);
1482 if ( pParentDirEntry)
1485 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
1487 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1488 AFS_TRACE_LEVEL_VERBOSE,
1489 "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
1490 &pParentDirEntry->NameInformation.FileName,
1497 if ( pDirEntry->ObjectInformation->VolumeCB != pCurrentVolume)
1500 lCount = AFSVolumeDecrement( pCurrentVolume,
1501 VolumeReferenceReason);
1503 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1504 AFS_TRACE_LEVEL_VERBOSE,
1505 "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
1507 VolumeReferenceReason,
1510 pCurrentVolume = pDirEntry->ObjectInformation->VolumeCB;
1512 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
1514 lCount = AFSVolumeIncrement( pCurrentVolume,
1515 VolumeReferenceReason);
1517 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1518 AFS_TRACE_LEVEL_VERBOSE,
1519 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
1521 VolumeReferenceReason,
1525 uniPathName = uniRemainingPath;
1531 // Update our pointers
1534 if ( pParentDirEntry)
1537 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1539 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1540 AFS_TRACE_LEVEL_VERBOSE,
1541 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1542 &pParentDirEntry->NameInformation.FileName,
1548 pParentDirEntry = pDirEntry;
1552 pCurrentObject = NULL;
1554 uniSearchName = uniComponentName;
1556 while( pDirEntry == NULL)
1560 // If the SearchName contains @SYS then we perform the substitution.
1561 // If there is no substitution we give up.
1564 if( !bSubstituteName &&
1565 FsRtlIsNameInExpression( &uniSysName,
1571 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1572 AFS_TRACE_LEVEL_VERBOSE_2,
1573 "AFSLocateNameEntry (FO: %p) Processing @SYS substitution for %wZ Index %08lX\n",
1576 ulSubstituteIndex));
1578 ntStatus = AFSSubstituteSysName( &uniComponentName,
1582 if ( NT_SUCCESS( ntStatus))
1585 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1586 AFS_TRACE_LEVEL_VERBOSE_2,
1587 "AFSLocateNameEntry (FO: %p) Located substitution %wZ for %wZ Index %08lX\n",
1591 ulSubstituteIndex));
1594 // Go reparse the name again
1597 bSubstituteName = TRUE;
1599 ulSubstituteIndex++; // For the next entry, if needed
1601 continue; // while( pDirEntry == NULL)
1606 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1607 AFS_TRACE_LEVEL_ERROR,
1608 "AFSLocateNameEntry (FO: %p) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1614 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1618 // Pass back the directory entries
1621 *OutParentDirectoryCB = pParentDirEntry;
1623 pParentDirEntry = NULL;
1625 *OutDirectoryCB = NULL;
1627 *OutVolumeCB = pCurrentVolume;
1629 *OutVolumeReferenceReason = VolumeReferenceReason;
1631 bReleaseCurrentVolume = FALSE;
1633 if( ComponentName != NULL)
1636 *ComponentName = uniComponentName;
1639 *RootPathName = uniFullPathName;
1643 // We can't possibly have a pDirEntry since the lookup failed
1645 try_return( ntStatus);
1650 // Generate the CRC on the node and perform a case sensitive lookup
1653 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1654 AFS_TRACE_LEVEL_VERBOSE_2,
1655 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case sensitive\n",
1659 ulCRC = AFSGenerateCRC( &uniSearchName,
1662 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1665 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1669 if( pDirEntry == NULL)
1673 // Missed so perform a case insensitive lookup
1676 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1677 AFS_TRACE_LEVEL_VERBOSE_2,
1678 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case insensitive\n",
1682 ulCRC = AFSGenerateCRC( &uniSearchName,
1685 AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1689 if( pDirEntry == NULL)
1693 // OK, if this component is a valid short name then try
1694 // a lookup in the short name tree
1697 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1698 RtlIsNameLegalDOS8Dot3( &uniSearchName,
1703 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1704 AFS_TRACE_LEVEL_VERBOSE_2,
1705 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ short name\n",
1709 AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1714 if ( pDirEntry == NULL &&
1715 pParentDirEntry->ObjectInformation->VolumeCB == AFSGlobalRoot)
1719 // Check with the service to see if this is a valid cell name
1720 // that can be automatically resolved. Drop the shared TreeLock
1721 // since AFSCheckCellName must acquire it exclusively.
1724 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1726 ntStatus = AFSCheckCellName( AuthGroup,
1730 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1734 if( pDirEntry == NULL)
1738 // If we substituted a name then reset our search name and try again
1741 if( bSubstituteName)
1744 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1746 uniSearchName = uniComponentName;
1748 bSubstituteName = FALSE;
1750 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1752 continue; // while( pDirEntry == NULL)
1756 // Node name not found so get out
1759 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1761 if( uniRemainingPath.Length > 0)
1764 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1766 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1767 AFS_TRACE_LEVEL_VERBOSE,
1768 "AFSLocateNameEntry (FO: %p) Returning path not found for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
1771 pParentDirEntry->ObjectInformation->FileId.Cell,
1772 pParentDirEntry->ObjectInformation->FileId.Volume,
1773 pParentDirEntry->ObjectInformation->FileId.Vnode,
1774 pParentDirEntry->ObjectInformation->FileId.Unique));
1779 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1781 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1782 AFS_TRACE_LEVEL_VERBOSE,
1783 "AFSLocateNameEntry (FO: %p) Returning name not found for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
1786 pParentDirEntry->ObjectInformation->FileId.Cell,
1787 pParentDirEntry->ObjectInformation->FileId.Volume,
1788 pParentDirEntry->ObjectInformation->FileId.Vnode,
1789 pParentDirEntry->ObjectInformation->FileId.Unique));
1792 // Pass back the directory entries
1795 *OutParentDirectoryCB = pParentDirEntry;
1797 pParentDirEntry = NULL;
1799 *OutDirectoryCB = NULL;
1801 *OutVolumeCB = pCurrentVolume;
1803 *OutVolumeReferenceReason = VolumeReferenceReason;
1805 bReleaseCurrentVolume = FALSE;
1807 if( ComponentName != NULL)
1810 *ComponentName = uniComponentName;
1813 *RootPathName = uniFullPathName;
1816 try_return( ntStatus);
1823 // Here we have a match on the case insensitive lookup for the name. If there
1824 // Is more than one link entry for this node then fail the lookup request
1827 pCurrentObject = pDirEntry->ObjectInformation;
1829 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1830 pDirEntry->CaseInsensitiveList.fLink != NULL)
1834 // Increment our dir entry ref count since we will decrement it on exit
1837 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1839 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1840 AFS_TRACE_LEVEL_VERBOSE,
1841 "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1842 &pDirEntry->NameInformation.FileName,
1847 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1849 try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1854 if( pDirEntry != NULL)
1858 // If the verify flag is set on the parent and the current entry is deleted
1859 // revalidate the parent and search again.
1862 pCurrentObject = pDirEntry->ObjectInformation;
1864 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1865 BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1868 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1870 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1871 AFS_TRACE_LEVEL_VERBOSE,
1872 "AFSLocateNameEntry (FO: %p) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1874 &pParentDirEntry->NameInformation.FileName,
1875 pParentDirEntry->ObjectInformation->FileId.Cell,
1876 pParentDirEntry->ObjectInformation->FileId.Volume,
1877 pParentDirEntry->ObjectInformation->FileId.Vnode,
1878 pParentDirEntry->ObjectInformation->FileId.Unique));
1881 // Directory TreeLock should be exclusively held
1884 AFSAcquireExcl( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1887 ntStatus = AFSVerifyEntry( AuthGroup,
1891 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1893 if( !NT_SUCCESS( ntStatus))
1896 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1897 AFS_TRACE_LEVEL_ERROR,
1898 "AFSLocateNameEntry (FO: %p) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1900 &pParentDirEntry->NameInformation.FileName,
1901 pParentDirEntry->ObjectInformation->FileId.Cell,
1902 pParentDirEntry->ObjectInformation->FileId.Volume,
1903 pParentDirEntry->ObjectInformation->FileId.Vnode,
1904 pParentDirEntry->ObjectInformation->FileId.Unique,
1907 try_return( ntStatus);
1910 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1911 AFS_TRACE_LEVEL_VERBOSE,
1912 "AFSLocateNameEntry (FO: %p) Reprocessing component %wZ in parent %wZ\n",
1915 &pParentDirEntry->NameInformation.FileName));
1920 pCurrentObject = NULL;
1926 // Increment our dir entry ref count
1929 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1931 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1932 AFS_TRACE_LEVEL_VERBOSE,
1933 "AFSLocateNameEntry Increment6 count on %wZ DE %p Ccb %p Cnt %d\n",
1934 &pDirEntry->NameInformation.FileName,
1940 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1942 } // End while( pDirEntry == NULL)
1945 // If we have a dirEntry for this component, perform some basic validation on it
1948 if( pDirEntry != NULL)
1951 pCurrentObject = pDirEntry->ObjectInformation;
1953 if (BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1956 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1957 AFS_TRACE_LEVEL_ERROR,
1958 "AFSLocateNameEntry (FO: %p) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1960 &pDirEntry->NameInformation.FileName,
1961 pCurrentObject->FileId.Cell,
1962 pCurrentObject->FileId.Volume,
1963 pCurrentObject->FileId.Vnode,
1964 pCurrentObject->FileId.Unique));
1967 // This entry was deleted through the invalidation call back so perform cleanup
1971 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1974 pParentObjectInfo = AFSFindObjectInfo( pCurrentObject->VolumeCB,
1975 &pCurrentObject->ParentFileId,
1979 ASSERT( pParentObjectInfo != NULL);
1981 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1984 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1987 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1989 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1990 AFS_TRACE_LEVEL_VERBOSE,
1991 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1992 &pDirEntry->NameInformation.FileName,
1997 ASSERT( lCount >= 0);
2000 pDirEntry->NameArrayReferenceCount <= 0)
2003 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2004 AFS_TRACE_LEVEL_VERBOSE,
2005 "AFSLocateNameEntry Deleting dir entry %p (%p) for %wZ\n",
2008 &pDirEntry->NameInformation.FileName));
2011 // Remove and delete the directory entry from the parent list
2014 AFSDeleteDirEntry( pParentObjectInfo,
2017 AFSAcquireShared( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
2020 if( pCurrentObject->ObjectReferenceCount <= 0)
2023 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
2026 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2027 AFS_TRACE_LEVEL_VERBOSE,
2028 "AFSLocateNameEntry Removing object %p from volume tree\n",
2031 AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
2032 &pCurrentObject->TreeEntry);
2034 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
2038 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
2043 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2044 AFS_TRACE_LEVEL_VERBOSE,
2045 "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
2047 &pDirEntry->NameInformation.FileName));
2049 SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
2051 AFSRemoveNameEntry( pParentObjectInfo,
2055 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2057 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
2060 // We deleted the dir entry so check if there is any remaining portion
2061 // of the name to process.
2064 if( uniRemainingPath.Length > 0)
2067 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
2069 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2070 AFS_TRACE_LEVEL_VERBOSE,
2071 "AFSLocateNameEntry (FO: %p) Returning path not found(2) for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
2074 pParentObjectInfo->FileId.Cell,
2075 pParentObjectInfo->FileId.Volume,
2076 pParentObjectInfo->FileId.Vnode,
2077 pParentObjectInfo->FileId.Unique));
2079 AFSReleaseObjectInfo( &pParentObjectInfo);
2084 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
2086 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2087 AFS_TRACE_LEVEL_VERBOSE,
2088 "AFSLocateNameEntry (FO: %p) Returning name not found(2) for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
2091 pParentObjectInfo->FileId.Cell,
2092 pParentObjectInfo->FileId.Volume,
2093 pParentObjectInfo->FileId.Vnode,
2094 pParentObjectInfo->FileId.Unique));
2096 AFSReleaseObjectInfo( &pParentObjectInfo);
2099 // Pass back the directory entries
2102 *OutParentDirectoryCB = pParentDirEntry;
2104 pParentDirEntry = NULL;
2106 *OutDirectoryCB = NULL;
2108 *OutVolumeCB = pCurrentVolume;
2110 *OutVolumeReferenceReason = VolumeReferenceReason;
2112 bReleaseCurrentVolume = FALSE;
2114 if( ComponentName != NULL)
2117 *ComponentName = uniComponentName;
2120 *RootPathName = uniFullPathName;
2125 if( ntStatus != STATUS_SUCCESS)
2128 try_return( ntStatus);
2132 // If we ended up substituting a name in the component then update
2133 // the full path and update the pointers
2136 if( bSubstituteName)
2139 BOOLEAN bRelativeOpen = FALSE;
2141 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2142 AFS_TRACE_LEVEL_VERBOSE_2,
2143 "AFSLocateNameEntry (FO: %p) Substituting %wZ into %wZ Index %08lX\n",
2147 ulSubstituteIndex));
2149 if( FileObject != NULL &&
2150 FileObject->RelatedFileObject != NULL)
2153 bRelativeOpen = TRUE;
2157 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
2158 // and free the prior Buffer contents but only if the fourth
2159 // parameter is TRUE.
2162 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
2167 bAllocatedSymLinkBuffer ||
2170 if( !NT_SUCCESS( ntStatus))
2173 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2174 AFS_TRACE_LEVEL_ERROR,
2175 "AFSLocateNameEntry (FO: %p) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
2182 try_return( ntStatus);
2186 // We have substituted a name into the buffer so if we do this again for this
2187 // path, we need to free up the buffer we allocated.
2190 bSubstitutedName = TRUE;
2194 // Update the search parameters
2197 uniPathName = uniRemainingPath;
2200 // Check if the is a SymLink entry but has no Target FileID or Name. In this
2201 // case it might be a DFS Link so let's go and evaluate it to be sure
2204 if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
2205 ( pCurrentObject->TargetFileId.Vnode == 0 ||
2206 pDirEntry->NameInformation.TargetName.Length == 0))
2209 ntStatus = AFSValidateSymLink( AuthGroup,
2212 if( !NT_SUCCESS( ntStatus))
2215 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2216 AFS_TRACE_LEVEL_ERROR,
2217 "AFSLocateNameEntry (FO: %p) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2219 &pDirEntry->NameInformation.FileName,
2220 pCurrentObject->FileId.Cell,
2221 pCurrentObject->FileId.Volume,
2222 pCurrentObject->FileId.Vnode,
2223 pCurrentObject->FileId.Unique,
2226 try_return( ntStatus);
2231 // Update the name array
2234 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2235 AFS_TRACE_LEVEL_VERBOSE,
2236 "AFSLocateNameEntry (FO: %p) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2238 &pDirEntry->NameInformation.FileName,
2239 pCurrentObject->FileId.Cell,
2240 pCurrentObject->FileId.Volume,
2241 pCurrentObject->FileId.Vnode,
2242 pCurrentObject->FileId.Unique));
2244 ntStatus = AFSInsertNextElement( pNameArray,
2247 if( !NT_SUCCESS( ntStatus))
2250 try_return( ntStatus);
2256 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2257 AFS_TRACE_LEVEL_VERBOSE,
2258 "AFSLocateNameEntry (FO: %p) Completed processing %wZ Status %08lX\n",
2263 if( ( !NT_SUCCESS( ntStatus) &&
2264 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
2265 ntStatus == STATUS_REPARSE)
2267 if( RootPathName->Buffer != uniFullPathName.Buffer)
2270 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
2276 if( *OutParentDirectoryCB != NULL)
2279 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2280 AFS_TRACE_LEVEL_VERBOSE,
2281 "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
2282 &(*OutParentDirectoryCB)->NameInformation.FileName,
2283 *OutParentDirectoryCB,
2285 (*OutParentDirectoryCB)->DirOpenReferenceCount));
2288 if( *OutDirectoryCB != NULL)
2291 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2292 AFS_TRACE_LEVEL_VERBOSE,
2293 "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
2294 &(*OutDirectoryCB)->NameInformation.FileName,
2297 (*OutDirectoryCB)->DirOpenReferenceCount));
2301 if( pDirEntry != NULL)
2304 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
2306 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2307 AFS_TRACE_LEVEL_VERBOSE,
2308 "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
2309 &pDirEntry->NameInformation.FileName,
2314 ASSERT( lCount >= 0);
2317 if( pParentDirEntry != NULL)
2320 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
2322 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2323 AFS_TRACE_LEVEL_VERBOSE,
2324 "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
2325 &pParentDirEntry->NameInformation.FileName,
2330 ASSERT( lCount >= 0);
2333 if( bReleaseCurrentVolume)
2336 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
2338 lCount = AFSVolumeDecrement( pCurrentVolume,
2339 VolumeReferenceReason);
2341 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2342 AFS_TRACE_LEVEL_VERBOSE,
2343 "AFSLocateNameEntry Decrement7 count on volume %p Reason %u Cnt %d\n",
2345 VolumeReferenceReason,
2348 bReleaseCurrentVolume = FALSE;
2351 if( bSubstituteName &&
2352 uniSearchName.Buffer != NULL)
2355 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
2363 AFSCreateDirEntry( IN GUID *AuthGroup,
2364 IN AFSObjectInfoCB *ParentObjectInfo,
2365 IN AFSDirectoryCB *ParentDirCB,
2366 IN PUNICODE_STRING FileName,
2367 IN PUNICODE_STRING ComponentName,
2368 IN ULONG Attributes,
2369 IN OUT AFSDirectoryCB **DirEntry)
2372 UNREFERENCED_PARAMETER(FileName);
2373 NTSTATUS ntStatus = STATUS_SUCCESS;
2374 AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
2375 LARGE_INTEGER liFileSize = {0,0};
2381 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2382 AFS_TRACE_LEVEL_VERBOSE_2,
2383 "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
2384 &ParentDirCB->NameInformation.FileName,
2385 ParentObjectInfo->FileId.Cell,
2386 ParentObjectInfo->FileId.Volume,
2387 ParentObjectInfo->FileId.Vnode,
2388 ParentObjectInfo->FileId.Unique,
2393 // OK, before inserting the node into the parent tree, issue
2394 // the request to the service for node creation
2395 // We will need to drop the lock on the parent node since the create
2396 // could cause a callback into the file system to invalidate it's cache
2399 ntStatus = AFSNotifyFileCreate( AuthGroup,
2407 // If the returned status is STATUS_REPARSE then the entry exists
2408 // and we raced, get out.
2410 if( ntStatus == STATUS_REPARSE)
2413 *DirEntry = pDirNode;
2415 try_return( ntStatus = STATUS_SUCCESS);
2418 if( !NT_SUCCESS( ntStatus))
2421 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2422 AFS_TRACE_LEVEL_ERROR,
2423 "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
2424 &ParentDirCB->NameInformation.FileName,
2425 ParentObjectInfo->FileId.Cell,
2426 ParentObjectInfo->FileId.Volume,
2427 ParentObjectInfo->FileId.Vnode,
2428 ParentObjectInfo->FileId.Unique,
2433 try_return( ntStatus);
2437 // If AFSNotifyFileCreate returns pDirNode != NULL, then its
2438 // DirOpenReferenceCount is held.
2441 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2445 // Before attempting to insert the new entry, check if we need to validate the parent
2448 if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2451 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2452 AFS_TRACE_LEVEL_VERBOSE,
2453 "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2454 &ParentDirCB->NameInformation.FileName,
2455 ParentObjectInfo->FileId.Cell,
2456 ParentObjectInfo->FileId.Volume,
2457 ParentObjectInfo->FileId.Vnode,
2458 ParentObjectInfo->FileId.Unique));
2460 ntStatus = AFSVerifyEntry( AuthGroup,
2464 if( !NT_SUCCESS( ntStatus))
2467 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2468 AFS_TRACE_LEVEL_ERROR,
2469 "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2470 &ParentDirCB->NameInformation.FileName,
2471 ParentObjectInfo->FileId.Cell,
2472 ParentObjectInfo->FileId.Volume,
2473 ParentObjectInfo->FileId.Vnode,
2474 ParentObjectInfo->FileId.Unique,
2477 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2479 try_return( ntStatus);
2484 // Check for the entry in the event we raced with some other thread
2487 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2488 (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2491 if( pExistingDirNode != NULL)
2493 if (AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2494 &pExistingDirNode->ObjectInformation->FileId))
2497 if ( pExistingDirNode != pDirNode)
2500 lCount = InterlockedDecrement( &pDirNode->DirOpenReferenceCount);
2502 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2503 AFS_TRACE_LEVEL_VERBOSE,
2504 "AFSCreateDirEntry Decrement count on %wZ DE %p Cnt %d\n",
2505 &pDirNode->NameInformation.FileName,
2509 AFSDeleteDirEntry( ParentObjectInfo,
2512 lCount = InterlockedIncrement( &pExistingDirNode->DirOpenReferenceCount);
2514 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2515 AFS_TRACE_LEVEL_VERBOSE,
2516 "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2517 &pExistingDirNode->NameInformation.FileName,
2521 *DirEntry = pExistingDirNode;
2524 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2526 try_return( ntStatus = STATUS_SUCCESS);
2532 // Need to tear down this entry and rebuild it below
2535 if( pExistingDirNode->DirOpenReferenceCount <= 0 &&
2536 pExistingDirNode->NameArrayReferenceCount <= 0)
2539 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2540 AFS_TRACE_LEVEL_VERBOSE,
2541 "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2543 &pExistingDirNode->NameInformation.FileName,
2544 pExistingDirNode->ObjectInformation->FileId.Cell,
2545 pExistingDirNode->ObjectInformation->FileId.Volume,
2546 pExistingDirNode->ObjectInformation->FileId.Vnode,
2547 pExistingDirNode->ObjectInformation->FileId.Unique,
2548 pDirNode->ObjectInformation->FileId.Cell,
2549 pDirNode->ObjectInformation->FileId.Volume,
2550 pDirNode->ObjectInformation->FileId.Vnode,
2551 pDirNode->ObjectInformation->FileId.Unique));
2553 AFSDeleteDirEntry( ParentObjectInfo,
2559 SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2561 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2562 AFS_TRACE_LEVEL_VERBOSE,
2563 "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2565 &pExistingDirNode->NameInformation.FileName,
2566 pExistingDirNode->ObjectInformation->FileId.Cell,
2567 pExistingDirNode->ObjectInformation->FileId.Volume,
2568 pExistingDirNode->ObjectInformation->FileId.Vnode,
2569 pExistingDirNode->ObjectInformation->FileId.Unique,
2570 pDirNode->ObjectInformation->FileId.Cell,
2571 pDirNode->ObjectInformation->FileId.Volume,
2572 pDirNode->ObjectInformation->FileId.Vnode,
2573 pDirNode->ObjectInformation->FileId.Unique));
2575 AFSRemoveNameEntry( ParentObjectInfo,
2581 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2582 AFS_TRACE_LEVEL_VERBOSE_2,
2583 "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2584 &ParentDirCB->NameInformation.FileName,
2585 ParentObjectInfo->FileId.Cell,
2586 ParentObjectInfo->FileId.Volume,
2587 ParentObjectInfo->FileId.Vnode,
2588 ParentObjectInfo->FileId.Unique,
2592 // Insert the directory node
2595 AFSInsertDirectoryNode( ParentObjectInfo,
2600 // Pass back the dir entry
2603 *DirEntry = pDirNode;
2605 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2616 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2617 IN AFSDirectoryCB *DirEntry,
2618 IN BOOLEAN InsertInEnumList)
2626 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2629 // Insert the node into the directory node tree
2632 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2633 AFS_TRACE_LEVEL_VERBOSE,
2634 "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2636 &DirEntry->NameInformation.FileName));
2638 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2640 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2643 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2645 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2646 AFS_TRACE_LEVEL_VERBOSE,
2647 "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2649 &DirEntry->NameInformation.FileName));
2654 AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2657 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2658 AFS_TRACE_LEVEL_VERBOSE,
2659 "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2661 &DirEntry->NameInformation.FileName));
2664 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2667 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2669 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2671 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2672 AFS_TRACE_LEVEL_VERBOSE,
2673 "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2675 &DirEntry->NameInformation.FileName));
2680 AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2683 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2684 AFS_TRACE_LEVEL_VERBOSE,
2685 "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2687 &DirEntry->NameInformation.FileName));
2691 // Into the shortname tree
2694 if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2697 if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2700 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2702 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2703 AFS_TRACE_LEVEL_VERBOSE,
2704 "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2706 &DirEntry->NameInformation.FileName));
2708 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2713 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2716 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2717 AFS_TRACE_LEVEL_VERBOSE,
2718 "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2720 &DirEntry->NameInformation.FileName));
2724 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2726 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2727 AFS_TRACE_LEVEL_VERBOSE,
2728 "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2730 &DirEntry->NameInformation.FileName));
2735 if( InsertInEnumList)
2739 // And insert the node into the directory list
2742 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2743 AFS_TRACE_LEVEL_VERBOSE,
2744 "AFSInsertDirectoryNode Inserting entry %p %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2746 &DirEntry->NameInformation.FileName,
2747 DirEntry->ObjectInformation->FileId.Cell,
2748 DirEntry->ObjectInformation->FileId.Volume,
2749 DirEntry->ObjectInformation->FileId.Vnode,
2750 DirEntry->ObjectInformation->FileId.Unique));
2752 if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2755 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2760 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2762 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2765 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2767 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2769 lCount = InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2771 AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2772 AFS_TRACE_LEVEL_VERBOSE,
2773 "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2774 &DirEntry->NameInformation.FileName,
2776 ParentObjectInfo->FileId.Cell,
2777 ParentObjectInfo->FileId.Volume,
2778 ParentObjectInfo->FileId.Vnode,
2779 ParentObjectInfo->FileId.Unique));
2787 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2788 IN AFSDirectoryCB **ppDirEntry)
2792 AFSDirectoryCB *pDirEntry;
2797 pDirEntry = (AFSDirectoryCB *) InterlockedCompareExchangePointer( (PVOID *)ppDirEntry,
2801 if ( pDirEntry == NULL)
2804 try_return( NOTHING);
2807 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2808 AFS_TRACE_LEVEL_VERBOSE,
2809 "AFSDeleteDirEntry Deleting dir entry in parent %p Entry %p object %p %wZ RefCount %d\n",
2812 pDirEntry->ObjectInformation,
2813 &pDirEntry->NameInformation.FileName,
2814 pDirEntry->DirOpenReferenceCount));
2816 ASSERT( pDirEntry->DirOpenReferenceCount == 0);
2818 AFSRemoveDirNodeFromParent( ParentObjectInfo,
2823 // Free up the name buffer if it was reallocated
2826 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2829 AFSExFreePoolWithTag( pDirEntry->NameInformation.FileName.Buffer, 0);
2832 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2835 AFSExFreePoolWithTag( pDirEntry->NameInformation.TargetName.Buffer, 0);
2838 if ( pDirEntry->ObjectInformation != NULL)
2841 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
2842 pDirEntry->ObjectInformation->Links == 0)
2845 SetFlag( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2849 // Dereference the object for this dir entry
2852 AFSAcquireShared( pDirEntry->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock,
2855 lCount = AFSObjectInfoDecrement( pDirEntry->ObjectInformation,
2856 AFS_OBJECT_REFERENCE_DIRENTRY);
2858 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2859 AFS_TRACE_LEVEL_VERBOSE,
2860 "AFSDeleteDirEntry Decrement count on object %p Cnt %d\n",
2861 pDirEntry->ObjectInformation,
2864 AFSReleaseResource( pDirEntry->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock);
2867 ExDeleteResourceLite( &pDirEntry->NonPaged->Lock);
2869 AFSExFreePoolWithTag( pDirEntry->NonPaged, AFS_DIR_ENTRY_NP_TAG);
2872 // Free up the dir entry
2875 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
2876 AFS_TRACE_LEVEL_VERBOSE,
2877 "AFSDeleteDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
2880 AFSExFreePoolWithTag( pDirEntry, AFS_DIR_ENTRY_TAG);
2889 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2890 IN AFSDirectoryCB *DirEntry,
2891 IN BOOLEAN RemoveFromEnumList)
2894 NTSTATUS ntStatus = STATUS_SUCCESS;
2901 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2903 if ( DirEntry->ObjectInformation != NULL)
2906 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2907 AFS_TRACE_LEVEL_VERBOSE,
2908 "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %p\n",
2910 &DirEntry->NameInformation.FileName,
2911 DirEntry->ObjectInformation->FileId.Cell,
2912 DirEntry->ObjectInformation->FileId.Volume,
2913 DirEntry->ObjectInformation->FileId.Vnode,
2914 DirEntry->ObjectInformation->FileId.Unique,
2920 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2921 AFS_TRACE_LEVEL_VERBOSE,
2922 "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ from Parent %p\n",
2924 &DirEntry->NameInformation.FileName,
2928 if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2931 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2932 AFS_TRACE_LEVEL_VERBOSE,
2933 "AFSRemoveDirNodeFromParent Removing DirEntry %p name %wZ\n",
2935 &DirEntry->NameInformation.FileName));
2937 AFSRemoveNameEntry( ParentObjectInfo,
2943 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2944 AFS_TRACE_LEVEL_VERBOSE,
2945 "AFSRemoveDirNodeFromParent DE %p for %wZ NOT removing entry due to flag set\n",
2947 &DirEntry->NameInformation.FileName));
2951 if( RemoveFromEnumList &&
2952 BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST))
2956 // And remove the entry from the enumeration list
2959 if( DirEntry->ListEntry.fLink == NULL)
2962 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = (AFSDirectoryCB *)DirEntry->ListEntry.bLink;
2967 ((AFSDirectoryCB *)DirEntry->ListEntry.fLink)->ListEntry.bLink = DirEntry->ListEntry.bLink;
2970 if( DirEntry->ListEntry.bLink == NULL)
2973 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = (AFSDirectoryCB *)DirEntry->ListEntry.fLink;
2978 ((AFSDirectoryCB *)DirEntry->ListEntry.bLink)->ListEntry.fLink = DirEntry->ListEntry.fLink;
2981 ASSERT( ParentObjectInfo->Specific.Directory.DirectoryNodeCount > 0);
2983 lCount = InterlockedDecrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2985 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2987 AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2988 AFS_TRACE_LEVEL_VERBOSE,
2989 "AFSRemoveDirNodeFromParent Removing entry %wZ Dec Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2990 &DirEntry->NameInformation.FileName,
2992 ParentObjectInfo->FileId.Cell,
2993 ParentObjectInfo->FileId.Volume,
2994 ParentObjectInfo->FileId.Vnode,
2995 ParentObjectInfo->FileId.Unique));
2997 DirEntry->ListEntry.fLink = NULL;
2998 DirEntry->ListEntry.bLink = NULL;
3006 AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
3007 IN OUT PUNICODE_STRING TargetFileName)
3010 NTSTATUS ntStatus = STATUS_SUCCESS;
3011 UNICODE_STRING uniFileName;
3017 // We will process backwards from the end of the name looking
3018 // for the first \ we encounter
3021 uniFileName.Length = FileName->Length;
3022 uniFileName.MaximumLength = FileName->MaximumLength;
3024 uniFileName.Buffer = FileName->Buffer;
3029 if( uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
3033 // Subtract one more character off of the filename if it is not the root
3036 if( uniFileName.Length > sizeof( WCHAR))
3039 uniFileName.Length -= sizeof( WCHAR);
3043 // Now build up the target name
3046 TargetFileName->Length = FileName->Length - uniFileName.Length;
3049 // If we are not on the root then fixup the name
3052 if( uniFileName.Length > sizeof( WCHAR))
3055 TargetFileName->Length -= sizeof( WCHAR);
3057 TargetFileName->Buffer = &uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) + 1];
3062 TargetFileName->Buffer = &uniFileName.Buffer[ uniFileName.Length/sizeof( WCHAR)];
3066 // Fixup the passed back filename length
3069 FileName->Length = uniFileName.Length;
3071 TargetFileName->MaximumLength = TargetFileName->Length;
3076 uniFileName.Length -= sizeof( WCHAR);
3084 AFSParseRelatedName( IN PIRP Irp,
3086 OUT PUNICODE_STRING FileName,
3087 OUT PUNICODE_STRING ParsedFileName,
3088 OUT PUNICODE_STRING RootFileName,
3089 OUT ULONG *ParseFlags,
3090 OUT AFSVolumeCB **VolumeCB,
3091 OUT AFSDirectoryCB **ParentDirectoryCB,
3092 OUT AFSNameArrayHdr **NameArray)
3094 NTSTATUS ntStatus = STATUS_SUCCESS;
3095 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
3096 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3097 AFSCcb *pRelatedCcb = NULL;
3098 AFSFcb *pRelatedFcb = NULL;
3099 AFSNameArrayHdr *pRelatedNameArray = NULL;
3100 UNICODE_STRING uniFullName;
3101 AFSDirectoryCB *pDirEntry = NULL;
3102 AFSNameArrayHdr *pNameArray = NULL;
3103 USHORT usComponentIndex = 0;
3104 USHORT usComponentLength = 0;
3105 AFSVolumeCB *pVolumeCB = NULL;
3111 pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
3113 pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
3115 pRelatedNameArray = pRelatedCcb->NameArray;
3117 uniFullName = pIrpSp->FileObject->FileName;
3119 ASSERT( pRelatedFcb != NULL);
3122 // On error, FileName indicates the path on which the failure occurred.
3125 *FileName = pRelatedCcb->FullFileName;
3128 // No wild cards in the name
3131 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3132 AFS_TRACE_LEVEL_VERBOSE_2,
3133 "AFSParseRelatedName (%p) %wZ FID %08lX-%08lX-%08lX-%08lX %wZ\n",
3135 &pRelatedCcb->DirectoryCB->NameInformation.FileName,
3136 pRelatedFcb->ObjectInformation->FileId.Cell,
3137 pRelatedFcb->ObjectInformation->FileId.Volume,
3138 pRelatedFcb->ObjectInformation->FileId.Vnode,
3139 pRelatedFcb->ObjectInformation->FileId.Unique,
3140 &pRelatedCcb->FullFileName));
3142 if( FsRtlDoesNameContainWildCards( &pRelatedCcb->FullFileName))
3145 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3146 AFS_TRACE_LEVEL_ERROR,
3147 "AFSParseNameRelated (%p) Component %wZ contains wild cards\n",
3149 &pRelatedCcb->FullFileName));
3151 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3154 pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
3156 pDirEntry = pRelatedCcb->DirectoryCB;
3159 // Grab the root node while checking state
3162 AFSAcquireShared( pVolumeCB->VolumeLock,
3165 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3166 BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3170 // The volume has been taken off line so fail the access
3173 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3174 AFS_TRACE_LEVEL_ERROR,
3175 "AFSParseNameRelated (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3177 pVolumeCB->ObjectInformation.FileId.Cell,
3178 pVolumeCB->ObjectInformation.FileId.Volume));
3180 AFSReleaseResource( pVolumeCB->VolumeLock);
3182 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3185 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3188 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3189 AFS_TRACE_LEVEL_VERBOSE,
3190 "AFSParseNameRelated (%p) Verifying root of volume %08lX:%08lX\n",
3192 pVolumeCB->ObjectInformation.FileId.Cell,
3193 pVolumeCB->ObjectInformation.FileId.Volume));
3195 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3198 if( !NT_SUCCESS( ntStatus))
3201 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3202 AFS_TRACE_LEVEL_ERROR,
3203 "AFSParseNameRelated (%p) Failed verification of root Status %08lX\n",
3207 AFSReleaseResource( pVolumeCB->VolumeLock);
3209 try_return( ntStatus);
3213 AFSReleaseResource( pVolumeCB->VolumeLock);
3215 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
3218 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3219 AFS_TRACE_LEVEL_VERBOSE,
3220 "AFSParseNameRelated (%p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3222 &pDirEntry->NameInformation.FileName,
3223 pDirEntry->ObjectInformation->FileId.Cell,
3224 pDirEntry->ObjectInformation->FileId.Volume,
3225 pDirEntry->ObjectInformation->FileId.Vnode,
3226 pDirEntry->ObjectInformation->FileId.Unique));
3229 // Directory TreeLock should be exclusively held
3232 AFSAcquireExcl( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
3235 ntStatus = AFSVerifyEntry( AuthGroup,
3239 AFSReleaseResource( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
3241 if( !NT_SUCCESS( ntStatus))
3244 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3245 AFS_TRACE_LEVEL_VERBOSE,
3246 "AFSParseNameRelated (%p) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3248 &pDirEntry->NameInformation.FileName,
3249 pDirEntry->ObjectInformation->FileId.Cell,
3250 pDirEntry->ObjectInformation->FileId.Volume,
3251 pDirEntry->ObjectInformation->FileId.Vnode,
3252 pDirEntry->ObjectInformation->FileId.Unique,
3255 try_return( ntStatus);
3260 // Create our full path name buffer
3263 uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length
3264 + sizeof( WCHAR) + pIrpSp->FileObject->FileName.Length
3267 uniFullName.Length = 0;
3269 uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
3270 uniFullName.MaximumLength,
3271 AFS_NAME_BUFFER_THREE_TAG);
3273 if( uniFullName.Buffer == NULL)
3276 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3277 AFS_TRACE_LEVEL_ERROR,
3278 "AFSParseNameRelated (%p) Failed to allocate full name buffer\n",
3281 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3284 SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
3286 RtlZeroMemory( uniFullName.Buffer,
3287 uniFullName.MaximumLength);
3289 RtlCopyMemory( uniFullName.Buffer,
3290 pRelatedCcb->FullFileName.Buffer,
3291 pRelatedCcb->FullFileName.Length);
3293 uniFullName.Length = pRelatedCcb->FullFileName.Length;
3295 usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
3297 usComponentLength = pIrpSp->FileObject->FileName.Length;
3299 if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
3300 pIrpSp->FileObject->FileName.Length > 0 &&
3301 pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
3302 pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
3305 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
3307 uniFullName.Length += sizeof( WCHAR);
3309 usComponentLength += sizeof( WCHAR);
3312 if( pIrpSp->FileObject->FileName.Length > 0)
3315 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
3316 pIrpSp->FileObject->FileName.Buffer,
3317 pIrpSp->FileObject->FileName.Length);
3319 uniFullName.Length += pIrpSp->FileObject->FileName.Length;
3322 *RootFileName = uniFullName;
3325 // We populate up to the current parent
3328 if( pRelatedNameArray == NULL)
3332 // Init and populate our name array
3335 pNameArray = AFSInitNameArray( NULL,
3338 if( pNameArray == NULL)
3341 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3342 AFS_TRACE_LEVEL_VERBOSE,
3343 "AFSParseNameRelated (%p) Failed to initialize name array\n",
3346 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3348 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
3350 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3353 ntStatus = AFSPopulateNameArray( pNameArray,
3355 pRelatedCcb->DirectoryCB);
3361 // Init and populate our name array
3364 pNameArray = AFSInitNameArray( NULL,
3365 pRelatedNameArray->MaxElementCount);
3367 if( pNameArray == NULL)
3370 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3371 AFS_TRACE_LEVEL_VERBOSE,
3372 "AFSParseNameRelated (%p) Failed to initialize name array\n",
3375 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3377 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
3379 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3382 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
3384 pRelatedCcb->DirectoryCB);
3387 if( !NT_SUCCESS( ntStatus))
3390 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3391 AFS_TRACE_LEVEL_VERBOSE,
3392 "AFSParseNameRelated (%p) Failed to populate name array\n",
3395 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3397 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
3399 try_return( ntStatus);
3402 ParsedFileName->Length = usComponentLength;
3404 ParsedFileName->MaximumLength = uniFullName.MaximumLength;
3406 ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
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 "AFSParseNameRelated 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 "AFSParseNameRelated (%p) Returning full name %wZ\n",
3433 try_return( ntStatus);
3437 if( NT_SUCCESS( ntStatus))
3440 if( *ParentDirectoryCB != NULL)
3443 lCount = InterlockedIncrement( &(*ParentDirectoryCB)->DirOpenReferenceCount);
3445 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3446 AFS_TRACE_LEVEL_VERBOSE,
3447 "AFSParseRelatedName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
3448 &(*ParentDirectoryCB)->NameInformation.FileName,
3449 (*ParentDirectoryCB),
3455 if( *VolumeCB != NULL)
3457 ASSERT( (*VolumeCB)->VolumeReferenceCount > 0);
3460 if( ntStatus != STATUS_SUCCESS)
3463 if( pNameArray != NULL)
3466 AFSFreeNameArray( pNameArray);
3475 AFSParseName( IN PIRP Irp,
3477 OUT PUNICODE_STRING FileName,
3478 OUT PUNICODE_STRING ParsedFileName,
3479 OUT PUNICODE_STRING RootFileName,
3480 OUT ULONG *ParseFlags,
3481 OUT AFSVolumeCB **VolumeCB,
3482 OUT AFSDirectoryCB **ParentDirectoryCB,
3483 OUT AFSNameArrayHdr **NameArray)
3486 NTSTATUS ntStatus = STATUS_SUCCESS;
3487 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
3488 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3489 UNICODE_STRING uniFullName, uniComponentName, uniRemainingPath;
3491 AFSDirectoryCB *pDirEntry = NULL;
3492 USHORT usIndex = 0, usDriveIndex = 0;
3493 AFSNameArrayHdr *pNameArray = NULL;
3494 USHORT usComponentIndex = 0;
3495 USHORT usComponentLength = 0;
3496 AFSVolumeCB *pVolumeCB = NULL;
3497 BOOLEAN bReleaseTreeLock = FALSE;
3498 BOOLEAN bIsAllShare = FALSE;
3504 if( pIrpSp->FileObject->RelatedFileObject != NULL)
3507 return AFSParseRelatedName( Irp, AuthGroup, FileName,
3508 ParsedFileName, RootFileName,
3509 ParseFlags, VolumeCB,
3510 ParentDirectoryCB, NameArray);
3514 // Indicate we are opening a root ...
3517 *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
3519 *ParentDirectoryCB = NULL;
3522 // On error, FileName indicates the path on which the failure occurred
3525 *FileName = pIrpSp->FileObject->FileName;
3528 // No wild cards in the name
3531 uniFullName = pIrpSp->FileObject->FileName;
3533 if( FsRtlDoesNameContainWildCards( &uniFullName) ||
3534 uniFullName.Length < AFSServerName.Length)
3537 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3538 AFS_TRACE_LEVEL_ERROR,
3539 "AFSParseName (%p) Name %wZ contains wild cards or too short\n",
3543 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3547 // The name is a fully qualified name. Parse out the server/share names and
3548 // point to the root qualified name
3549 // First thing is to locate the server name
3552 FsRtlDissectName( uniFullName,
3556 uniFullName = uniRemainingPath;
3559 // This component is the server name we are serving
3562 if( RtlCompareUnicodeString( &uniComponentName,
3568 // Drive letter based name?
3571 uniFullName = pIrpSp->FileObject->FileName;
3573 while( usIndex < uniFullName.Length/sizeof( WCHAR))
3576 if( uniFullName.Buffer[ usIndex] == L':')
3579 uniFullName.Buffer = &uniFullName.Buffer[ usIndex + 2];
3581 uniFullName.Length -= (usIndex + 2) * sizeof( WCHAR);
3583 usDriveIndex = usIndex - 1;
3592 // Do we have the right server name now?
3595 FsRtlDissectName( uniFullName,
3599 uniFullName = uniRemainingPath;
3602 // This component is the server name we are serving
3605 if( RtlCompareUnicodeString( &uniComponentName,
3610 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3611 AFS_TRACE_LEVEL_ERROR,
3612 "AFSParseName (%p) Name %wZ does not have server name\n",
3614 &pIrpSp->FileObject->FileName));
3616 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3620 // Validate this drive letter is actively mapped
3623 if( usDriveIndex > 0 &&
3624 !AFSIsDriveMapped( pIrpSp->FileObject->FileName.Buffer[ usDriveIndex]))
3627 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3628 AFS_TRACE_LEVEL_ERROR,
3629 "AFSParseName (%p) Name %wZ contains invalid drive mapping\n",
3631 &pIrpSp->FileObject->FileName));
3633 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3637 if( FsRtlDoesNameContainWildCards( &uniFullName))
3640 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3641 AFS_TRACE_LEVEL_ERROR,
3642 "AFSParseName (%p) Component %wZ contains wild cards\n",
3646 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3649 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3650 AFS_TRACE_LEVEL_VERBOSE_2,
3651 "AFSParseName (%p) Processing full name %wZ\n",
3655 if( uniFullName.Length > 0 &&
3656 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] == L'\\')
3659 uniFullName.Length -= sizeof( WCHAR);
3663 // Be sure we are online and ready to go
3666 AFSAcquireShared( AFSGlobalRoot->VolumeLock,
3669 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3670 BooleanFlagOn( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3674 // The volume has been taken off line so fail the access
3677 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3678 AFS_TRACE_LEVEL_ERROR,
3679 "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3681 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3682 AFSGlobalRoot->ObjectInformation.FileId.Volume));
3684 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3686 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3689 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3692 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3693 AFS_TRACE_LEVEL_VERBOSE,
3694 "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
3696 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3697 AFSGlobalRoot->ObjectInformation.FileId.Volume));
3699 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3702 if( !NT_SUCCESS( ntStatus))
3705 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3706 AFS_TRACE_LEVEL_ERROR,
3707 "AFSParseName (%p) Failed verification of root Status %08lX\n",
3711 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3713 try_return( ntStatus);
3717 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3719 if( !BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3722 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3723 AFS_TRACE_LEVEL_VERBOSE,
3724 "AFSParseName (%p) Enumerating global root of volume %08lX:%08lX\n",
3726 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3727 AFSGlobalRoot->ObjectInformation.FileId.Volume));
3729 ntStatus = AFSEnumerateGlobalRoot( AuthGroup);
3731 if( !NT_SUCCESS( ntStatus))
3734 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3735 AFS_TRACE_LEVEL_ERROR,
3736 "AFSParseName (%p) Failed enumeraiton of root Status %08lX\n",
3740 try_return( ntStatus);
3745 // Check for the \\Server access and return it as though it were \\Server\Globalroot
3748 if( uniRemainingPath.Buffer == NULL ||
3749 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3750 uniRemainingPath.Buffer[ 0] == L'\\'))
3753 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3754 AFS_TRACE_LEVEL_VERBOSE_2,
3755 "AFSParseName (%p) Returning global root access\n",
3758 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3760 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3761 AFS_TRACE_LEVEL_VERBOSE,
3762 "AFSParseName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3763 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3764 AFSGlobalRoot->DirectoryCB,
3770 FileName->Length = 0;
3771 FileName->MaximumLength = 0;
3772 FileName->Buffer = NULL;
3774 try_return( ntStatus = STATUS_SUCCESS);
3777 *RootFileName = uniFullName;
3780 // Include the starting \ in the root name
3783 if( RootFileName->Buffer[ 0] != L'\\')
3785 RootFileName->Buffer--;
3786 RootFileName->Length += sizeof( WCHAR);
3787 RootFileName->MaximumLength += sizeof( WCHAR);
3791 // Get the 'share' name
3794 FsRtlDissectName( uniFullName,
3798 if( FsRtlDoesNameContainWildCards( &uniFullName))
3801 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3802 AFS_TRACE_LEVEL_ERROR,
3803 "AFSParseName (%p) Component %wZ contains wild cards\n",
3805 &uniComponentName));
3807 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3811 // If this is the ALL access then perform some additional processing
3814 if( uniComponentName.Length == 0 ||
3815 RtlCompareUnicodeString( &uniComponentName,
3823 // If there is nothing else then get out
3826 if( uniRemainingPath.Buffer == NULL ||
3827 uniRemainingPath.Length == 0 ||
3828 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3829 uniRemainingPath.Buffer[ 0] == L'\\'))
3832 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3833 AFS_TRACE_LEVEL_VERBOSE_2,
3834 "AFSParseName (%p) Returning global root access\n",
3837 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3839 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3840 AFS_TRACE_LEVEL_VERBOSE,
3841 "AFSParseName Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
3842 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3843 AFSGlobalRoot->DirectoryCB,
3849 FileName->Length = 0;
3850 FileName->MaximumLength = 0;
3851 FileName->Buffer = NULL;
3853 try_return( ntStatus = STATUS_SUCCESS);
3857 // Process the name again to strip off the ALL portion
3860 uniFullName = uniRemainingPath;
3862 FsRtlDissectName( uniFullName,
3867 // Check for the PIOCtl name
3870 if( RtlCompareUnicodeString( &uniComponentName,
3875 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3876 AFS_TRACE_LEVEL_VERBOSE_2,
3877 "AFSParseName (%p) Returning root PIOCtl access\n",
3880 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3882 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3883 AFS_TRACE_LEVEL_VERBOSE,
3884 "AFSParseName Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
3885 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3886 AFSGlobalRoot->DirectoryCB,
3890 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3894 *FileName = AFSPIOCtlName;
3896 try_return( ntStatus = STATUS_SUCCESS);
3899 else if( (pDirEntry = AFSGetSpecialShareNameEntry( &uniComponentName,
3900 &uniRemainingPath)) != NULL)
3903 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3904 AFS_TRACE_LEVEL_VERBOSE_2,
3905 "AFSParseName (%p) Returning root share name %wZ access\n",
3907 &uniComponentName));
3910 // Add in the full share name to pass back
3913 if( uniRemainingPath.Buffer != NULL)
3917 // This routine strips off the leading slash so add it back in
3920 uniRemainingPath.Buffer--;
3921 uniRemainingPath.Length += sizeof( WCHAR);
3922 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3925 // And the cell name
3928 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3929 uniRemainingPath.Length += uniComponentName.Length;
3930 uniRemainingPath.MaximumLength += uniComponentName.Length;
3932 uniComponentName = uniRemainingPath;
3937 *FileName = uniComponentName;
3939 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3941 *ParentDirectoryCB = pDirEntry;
3943 try_return( ntStatus = STATUS_SUCCESS);
3947 // Determine the 'share' we are accessing
3950 ulCRC = AFSGenerateCRC( &uniComponentName,
3953 AFSAcquireShared( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3956 bReleaseTreeLock = TRUE;
3958 AFSLocateCaseSensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
3962 if( pDirEntry == NULL)
3965 ulCRC = AFSGenerateCRC( &uniComponentName,
3968 AFSLocateCaseInsensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
3972 if( pDirEntry == NULL)
3976 // OK, if this component is a valid short name then try
3977 // a lookup in the short name tree
3980 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3981 RtlIsNameLegalDOS8Dot3( &uniComponentName,
3986 AFSLocateShortNameDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.ShortNameTree,
3991 if( pDirEntry == NULL)
3995 // Check with the service whether it is a valid cell name
3998 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4000 bReleaseTreeLock = FALSE;
4002 ntStatus = AFSCheckCellName( AuthGroup,
4006 if( !NT_SUCCESS( ntStatus))
4010 uniRemainingPath.Length == 0 &&
4011 ntStatus == STATUS_OBJECT_PATH_NOT_FOUND)
4014 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4015 AFS_TRACE_LEVEL_VERBOSE,
4016 "AFSParseName (%p) AFSCheckCellName %wZ returned path not found; ntStatus %08X\n",
4019 STATUS_OBJECT_NAME_NOT_FOUND));
4021 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
4024 try_return( ntStatus);
4030 if( bReleaseTreeLock)
4032 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4037 // Be sure we are starting from the correct volume
4040 if( pDirEntry->ObjectInformation->VolumeCB != AFSGlobalRoot)
4044 // We dropped the global root in the CheckCellName routine which is the
4045 // only way we can be here
4048 pVolumeCB = pDirEntry->ObjectInformation->VolumeCB;
4051 // Init our name array
4054 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
4057 if( pNameArray == NULL)
4060 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4061 AFS_TRACE_LEVEL_VERBOSE,
4062 "AFSParseName (%p) Failed to initialize name array\n",
4065 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4068 ntStatus = AFSInsertNextElement( pNameArray,
4069 pVolumeCB->DirectoryCB);
4074 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4075 AFS_TRACE_LEVEL_VERBOSE,
4076 "AFSParseName (%p) Failed to insert name array element\n",
4079 try_return( ntStatus);
4083 // In this case don't add back in the 'share' name since that is where we are
4084 // starting. Just put the leading slash back in
4087 if( uniRemainingPath.Buffer != NULL)
4090 uniRemainingPath.Buffer--;
4091 uniRemainingPath.Length += sizeof( WCHAR);
4092 uniRemainingPath.MaximumLength += sizeof( WCHAR);
4094 if( uniRemainingPath.Length > sizeof( WCHAR))
4097 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
4101 // Pass back the parent being the root of the volume
4104 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
4110 // Pass back a root slash
4113 uniRemainingPath = uniComponentName;
4115 uniRemainingPath.Buffer--;
4116 uniRemainingPath.Length = sizeof( WCHAR);
4117 uniRemainingPath.MaximumLength = sizeof( WCHAR);
4120 // This is a root open so pass back no parent
4127 pVolumeCB = AFSGlobalRoot;
4130 // Init our name array
4133 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
4135 if( pNameArray == NULL)
4138 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4139 AFS_TRACE_LEVEL_VERBOSE,
4140 "AFSParseName (%p) Failed to initialize name array\n",
4143 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4147 // Add back in the 'share' portion of the name since we will parse it out on return
4150 if( uniRemainingPath.Buffer != NULL)
4154 // This routine strips off the leading slash so add it back in
4157 uniRemainingPath.Buffer--;
4158 uniRemainingPath.Length += sizeof( WCHAR);
4159 uniRemainingPath.MaximumLength += sizeof( WCHAR);
4161 if( uniRemainingPath.Length > sizeof( WCHAR))
4164 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
4168 // And the cell name
4171 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
4172 uniRemainingPath.Length += uniComponentName.Length;
4173 uniRemainingPath.MaximumLength += uniComponentName.Length;
4178 uniRemainingPath = uniComponentName;
4182 // And the leading slash again ...
4185 uniRemainingPath.Buffer--;
4186 uniRemainingPath.Length += sizeof( WCHAR);
4187 uniRemainingPath.MaximumLength += sizeof( WCHAR);
4190 // Pass back the parent being the volume root
4193 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
4197 // Return the remaining portion as the file name
4200 *FileName = uniRemainingPath;
4202 *ParsedFileName = uniRemainingPath;
4204 *NameArray = pNameArray;
4206 *VolumeCB = pVolumeCB;
4209 // Increment our reference on the volume
4212 lCount = AFSVolumeIncrement( pVolumeCB,
4213 AFS_VOLUME_REFERENCE_PARSE_NAME);
4215 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4216 AFS_TRACE_LEVEL_VERBOSE,
4217 "AFSParseName Increment2 count on global volume %p Cnt %d\n",
4223 if( NT_SUCCESS( ntStatus))
4226 if( *ParentDirectoryCB != NULL)
4229 lCount = InterlockedIncrement( &(*ParentDirectoryCB)->DirOpenReferenceCount);
4231 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4232 AFS_TRACE_LEVEL_VERBOSE,
4233 "AFSParseName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4234 &(*ParentDirectoryCB)->NameInformation.FileName,
4235 (*ParentDirectoryCB),
4241 if( *VolumeCB != NULL)
4243 ASSERT( (*VolumeCB)->VolumeReferenceCount > 0);
4246 if( ntStatus != STATUS_SUCCESS)
4249 if( pNameArray != NULL)
4252 AFSFreeNameArray( pNameArray);
4261 AFSCheckCellName( IN GUID *AuthGroup,
4262 IN UNICODE_STRING *CellName,
4263 OUT AFSDirectoryCB **ShareDirEntry)
4266 NTSTATUS ntStatus = STATUS_SUCCESS;
4267 UNICODE_STRING uniName;
4268 AFSDirEnumEntry *pDirEnumEntry = NULL;
4269 AFSDirHdr *pDirHdr = &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr;
4270 AFSDirectoryCB *pDirNode = NULL;
4271 UNICODE_STRING uniDirName, uniTargetName;
4272 AFSVolumeCB *pVolumeCB = NULL;
4279 // Look for some default names we will not handle
4282 RtlInitUnicodeString( &uniName,
4285 if( RtlCompareUnicodeString( &uniName,
4290 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4293 RtlInitUnicodeString( &uniName,
4296 if( RtlCompareUnicodeString( &uniName,
4301 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4304 RtlInitUnicodeString( &uniName,
4307 if( RtlCompareUnicodeString( &uniName,
4312 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4315 RtlInitUnicodeString( &uniName,
4318 if( RtlCompareUnicodeString( &uniName,
4323 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4327 // OK, ask the CM about this component name
4330 ntStatus = AFSEvaluateTargetByName( AuthGroup,
4331 &AFSGlobalRoot->ObjectInformation,
4336 if( !NT_SUCCESS( ntStatus))
4339 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4340 AFS_TRACE_LEVEL_WARNING,
4341 "AFSCheckCellName entry %wZ does not exist parent FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4343 AFSGlobalRoot->ObjectInformation.FileId.Cell,
4344 AFSGlobalRoot->ObjectInformation.FileId.Volume,
4345 AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4346 AFSGlobalRoot->ObjectInformation.FileId.Unique,
4349 try_return( ntStatus);
4353 // OK, we have a dir enum entry back so add it to the root node
4356 uniDirName = *CellName;
4358 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
4359 uniTargetName.MaximumLength = uniTargetName.Length;
4360 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
4363 // Is this entry a root volume entry?
4366 if( pDirEnumEntry->FileId.Cell != AFSGlobalRoot->ObjectInformation.FileId.Cell ||
4367 pDirEnumEntry->FileId.Volume != AFSGlobalRoot->ObjectInformation.FileId.Volume)
4371 // Build the root volume entry
4374 ntStatus = AFSBuildRootVolume( AuthGroup,
4375 &pDirEnumEntry->FileId,
4379 // On success returns with a volume reference count held
4382 if( !NT_SUCCESS( ntStatus))
4384 try_return( ntStatus);
4387 *ShareDirEntry = pVolumeCB->DirectoryCB;
4389 lCount = InterlockedIncrement( &pVolumeCB->DirectoryCB->DirOpenReferenceCount);
4391 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4392 AFS_TRACE_LEVEL_VERBOSE,
4393 "AFSCheckCellName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4394 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4395 pVolumeCB->DirectoryCB,
4399 lCount = AFSVolumeDecrement( pVolumeCB,
4400 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4402 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4403 AFS_TRACE_LEVEL_VERBOSE,
4404 "AFSCheckCellName Decrement count on volume %p Cnt %d\n",
4411 lCount = InterlockedIncrement( &pDirHdr->ContentIndex);
4413 pDirNode = AFSInitDirEntry( &AFSGlobalRoot->ObjectInformation,
4419 if( pDirNode == NULL)
4422 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4426 // Init the short name if we have one
4429 if( pDirEnumEntry->ShortNameLength > 0)
4432 pDirNode->NameInformation.ShortNameLength = pDirEnumEntry->ShortNameLength;
4434 RtlCopyMemory( pDirNode->NameInformation.ShortName,
4435 pDirEnumEntry->ShortName,
4436 pDirNode->NameInformation.ShortNameLength);
4439 AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4443 // Insert the node into the name tree
4446 ASSERT( ExIsResourceAcquiredExclusiveLite( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock));
4448 if( pDirHdr->CaseSensitiveTreeHead == NULL)
4451 pDirHdr->CaseSensitiveTreeHead = pDirNode;
4456 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( pDirHdr->CaseSensitiveTreeHead,
4460 AFSDeleteDirEntry( &AFSGlobalRoot->ObjectInformation,
4463 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4465 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4469 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
4471 if( pDirHdr->CaseInsensitiveTreeHead == NULL)
4474 pDirHdr->CaseInsensitiveTreeHead = pDirNode;
4476 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
4481 AFSInsertCaseInsensitiveDirEntry( pDirHdr->CaseInsensitiveTreeHead,
4485 if( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead == NULL)
4488 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead = pDirNode;
4493 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
4495 pDirNode->ListEntry.bLink = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail;
4498 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail = pDirNode;
4500 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
4502 lCount = InterlockedIncrement( &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeCount);
4504 AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
4505 AFS_TRACE_LEVEL_VERBOSE,
4506 "AFSCheckCellName Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
4507 &pDirNode->NameInformation.FileName,
4509 AFSGlobalRoot->ObjectInformation.FileId.Cell,
4510 AFSGlobalRoot->ObjectInformation.FileId.Volume,
4511 AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4512 AFSGlobalRoot->ObjectInformation.FileId.Unique));
4514 lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
4516 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4517 AFS_TRACE_LEVEL_VERBOSE,
4518 "AFSCheckCellName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
4519 &pDirNode->NameInformation.FileName,
4524 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4527 // Pass back the dir node
4530 *ShareDirEntry = pDirNode;
4535 if( pDirEnumEntry != NULL)
4538 AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_31_TAG);
4546 AFSBuildMountPointTarget( IN GUID *AuthGroup,
4547 IN AFSDirectoryCB *DirectoryCB,
4548 OUT AFSVolumeCB **TargetVolumeCB)
4551 NTSTATUS ntStatus = STATUS_SUCCESS;
4552 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4553 AFSDirEnumEntry *pDirEntry = NULL;
4554 ULONGLONG ullIndex = 0;
4555 AFSVolumeCB *pVolumeCB = NULL;
4556 AFSFileID stTargetFileID;
4558 BOOLEAN bReleaseVolumeLock = FALSE;
4564 // Loop on each entry, building the chain until we encounter the final target
4567 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4568 AFS_TRACE_LEVEL_VERBOSE_2,
4569 "AFSBuildMountPointTarget Building target directory for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4570 &DirectoryCB->NameInformation.FileName,
4571 DirectoryCB->ObjectInformation->FileId.Cell,
4572 DirectoryCB->ObjectInformation->FileId.Volume,
4573 DirectoryCB->ObjectInformation->FileId.Vnode,
4574 DirectoryCB->ObjectInformation->FileId.Unique));
4577 // Do we need to evaluate the node?
4580 //if( DirectoryCB->ObjectInformation->TargetFileId.Vnode == 0 &&
4581 // DirectoryCB->ObjectInformation->TargetFileId.Unique == 0)
4585 // Go evaluate the current target to get the target fid
4588 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4589 AFS_TRACE_LEVEL_VERBOSE_2,
4590 "AFSBuildMountPointTarget Evaluating target %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4591 &DirectoryCB->NameInformation.FileName,
4592 DirectoryCB->ObjectInformation->FileId.Cell,
4593 DirectoryCB->ObjectInformation->FileId.Volume,
4594 DirectoryCB->ObjectInformation->FileId.Vnode,
4595 DirectoryCB->ObjectInformation->FileId.Unique));
4597 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
4602 if( !NT_SUCCESS( ntStatus))
4605 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4606 AFS_TRACE_LEVEL_ERROR,
4607 "AFSBuildMountPointTarget Failed to evaluate target %wZ Status %08lX\n",
4608 &DirectoryCB->NameInformation.FileName,
4611 try_return( ntStatus);
4614 if( pDirEntry->TargetFileId.Vnode == 0 &&
4615 pDirEntry->TargetFileId.Unique == 0)
4618 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4619 AFS_TRACE_LEVEL_ERROR,
4620 "AFSBuildMountPointTarget Target %wZ FID %08lX-%08lX-%08lX-%08lX service returned zero FID\n",
4621 &DirectoryCB->NameInformation.FileName,
4622 DirectoryCB->ObjectInformation->FileId.Cell,
4623 DirectoryCB->ObjectInformation->FileId.Volume,
4624 DirectoryCB->ObjectInformation->FileId.Vnode,
4625 DirectoryCB->ObjectInformation->FileId.Unique));
4627 try_return( ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED);
4630 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
4633 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
4634 &DirectoryCB->Flags,
4635 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4636 (USHORT)pDirEntry->TargetNameLength);
4638 if( !NT_SUCCESS( ntStatus))
4641 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4643 try_return( ntStatus);
4646 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4648 DirectoryCB->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
4651 stTargetFileID = DirectoryCB->ObjectInformation->TargetFileId;
4654 // Try to locate this FID. First the volume then the
4658 ullIndex = AFSCreateHighIndex( &stTargetFileID);
4660 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4661 AFS_TRACE_LEVEL_VERBOSE,
4662 "AFSBuildMountPointTarget Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4663 &pDevExt->Specific.RDR.VolumeTreeLock,
4664 PsGetCurrentThread()));
4666 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4669 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4670 AFS_TRACE_LEVEL_VERBOSE_2,
4671 "AFSBuildMountPointTarget Locating volume for target %I64X\n",
4674 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4676 (AFSBTreeEntry **)&pVolumeCB);
4679 // We can be processing a request for a target that is on a volume
4680 // we have never seen before.
4683 if( pVolumeCB == NULL)
4687 // Locking is held correctly in init routine
4690 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4693 // Go init the root of the volume
4696 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4697 AFS_TRACE_LEVEL_VERBOSE_2,
4698 "AFSBuildMountPointTarget Initializing root for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4699 &DirectoryCB->NameInformation.FileName,
4700 DirectoryCB->ObjectInformation->FileId.Cell,
4701 DirectoryCB->ObjectInformation->FileId.Volume,
4702 DirectoryCB->ObjectInformation->FileId.Vnode,
4703 DirectoryCB->ObjectInformation->FileId.Unique));
4705 ntStatus = AFSInitVolume( AuthGroup,
4707 AFS_VOLUME_REFERENCE_MOUNTPT,
4710 if( !NT_SUCCESS( ntStatus))
4713 try_return( ntStatus);
4717 // pVolumeCB->VolumeLock held exclusive and
4718 // pVolumeCB->VolumeReferenceCount has been incremented
4719 // pVolumeCB->RootFcb == NULL
4722 bReleaseVolumeLock = TRUE;
4728 // AFSInitVolume returns with a VolumeReferenceCount
4729 // obtain one to match
4732 lCount = AFSVolumeIncrement( pVolumeCB,
4733 AFS_VOLUME_REFERENCE_MOUNTPT);
4735 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4736 AFS_TRACE_LEVEL_VERBOSE,
4737 "AFSBuildMountPointTarget Increment count on volume %p Cnt %d\n",
4741 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4744 if( pVolumeCB->RootFcb == NULL)
4747 if ( bReleaseVolumeLock == FALSE)
4750 AFSAcquireExcl( pVolumeCB->VolumeLock,
4753 bReleaseVolumeLock = TRUE;
4757 // Initialize the root fcb for this volume
4760 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4763 if( !NT_SUCCESS( ntStatus))
4766 lCount = AFSVolumeDecrement( pVolumeCB,
4767 AFS_VOLUME_REFERENCE_MOUNTPT);
4769 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4770 AFS_TRACE_LEVEL_VERBOSE,
4771 "AFSBuildMountPoint Decrement count on volume %p Cnt %d\n",
4775 AFSReleaseResource( pVolumeCB->VolumeLock);
4777 try_return( ntStatus);
4781 // Drop the lock acquired above
4784 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4787 if ( bReleaseVolumeLock == TRUE)
4790 AFSReleaseResource( pVolumeCB->VolumeLock);
4793 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4794 AFS_TRACE_LEVEL_VERBOSE_2,
4795 "AFSBuildMountPointTarget Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4796 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4797 pVolumeCB->ObjectInformation.FileId.Cell,
4798 pVolumeCB->ObjectInformation.FileId.Volume,
4799 pVolumeCB->ObjectInformation.FileId.Vnode,
4800 pVolumeCB->ObjectInformation.FileId.Unique));
4802 *TargetVolumeCB = pVolumeCB;
4809 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
4817 AFSBuildRootVolume( IN GUID *AuthGroup,
4818 IN AFSFileID *FileId,
4819 OUT AFSVolumeCB **TargetVolumeCB)
4822 NTSTATUS ntStatus = STATUS_SUCCESS;
4823 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4824 ULONGLONG ullIndex = 0;
4825 AFSVolumeCB *pVolumeCB = NULL;
4827 BOOLEAN bReleaseVolumeLock = FALSE;
4832 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4833 AFS_TRACE_LEVEL_VERBOSE_2,
4834 "AFSBuildRootVolume Building target volume for FID %08lX-%08lX-%08lX-%08lX\n",
4840 ullIndex = AFSCreateHighIndex( FileId);
4842 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4843 AFS_TRACE_LEVEL_VERBOSE,
4844 "AFSBuildRootVolume Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4845 &pDevExt->Specific.RDR.VolumeTreeLock,
4846 PsGetCurrentThread()));
4848 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4851 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4852 AFS_TRACE_LEVEL_VERBOSE_2,
4853 "AFSBuildRootVolume Locating volume for target %I64X\n",
4856 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4858 (AFSBTreeEntry **)&pVolumeCB);
4861 // We can be processing a request for a target that is on a volume
4862 // we have never seen before.
4865 if( pVolumeCB == NULL)
4869 // Locking is held correctly in init routine
4872 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4875 // Go init the root of the volume
4878 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4879 AFS_TRACE_LEVEL_VERBOSE_2,
4880 "AFSBuildRootVolume Initializing root for FID %08lX-%08lX-%08lX-%08lX\n",
4886 ntStatus = AFSInitVolume( AuthGroup,
4888 AFS_VOLUME_REFERENCE_BUILD_ROOT,
4891 if( !NT_SUCCESS( ntStatus))
4894 try_return( ntStatus);
4898 // pVolumeCB->VolumeLock is held exclusive
4899 // pVolumeCB->VolumeReferenceCount has been incremented
4900 // pVolumeCB->RootFcb == NULL
4903 bReleaseVolumeLock = TRUE;
4909 // AFSInitVolume returns with a VolumeReferenceCount
4910 // obtain one to match
4913 lCount = AFSVolumeIncrement( pVolumeCB,
4914 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4916 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4917 AFS_TRACE_LEVEL_VERBOSE,
4918 "AFSBuildRootVolume Increment count on volume %p Cnt %d\n",
4922 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4926 if( pVolumeCB->RootFcb == NULL)
4929 if ( bReleaseVolumeLock == FALSE)
4932 AFSAcquireExcl( pVolumeCB->VolumeLock,
4935 bReleaseVolumeLock = TRUE;
4939 // Initialize the root fcb for this volume
4942 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4945 if( !NT_SUCCESS( ntStatus))
4948 lCount = AFSVolumeDecrement( pVolumeCB,
4949 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4951 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4952 AFS_TRACE_LEVEL_VERBOSE,
4953 "AFSBuildRootVolume Decrement count on volume %p Cnt %d\n",
4957 AFSReleaseResource( pVolumeCB->VolumeLock);
4959 try_return( ntStatus);
4963 // Drop the lock acquired above
4966 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4969 if ( bReleaseVolumeLock == TRUE)
4972 AFSReleaseResource( pVolumeCB->VolumeLock);
4975 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4976 AFS_TRACE_LEVEL_VERBOSE_2,
4977 "AFSBuildRootVolume Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4978 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4979 pVolumeCB->ObjectInformation.FileId.Cell,
4980 pVolumeCB->ObjectInformation.FileId.Volume,
4981 pVolumeCB->ObjectInformation.FileId.Vnode,
4982 pVolumeCB->ObjectInformation.FileId.Unique));
4984 *TargetVolumeCB = pVolumeCB;
4995 AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
4996 IN PFILE_OBJECT FileObject,
4997 IN UNICODE_STRING *RemainingPath,
4999 OUT PUNICODE_STRING TargetName)
5002 NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
5003 UNICODE_STRING uniReparseName;
5004 UNICODE_STRING uniMUPDeviceName;
5005 UNICODE_STRING uniIOMgrDeviceName;
5006 AFSDirEnumEntry *pDirEntry = NULL;
5011 if ( FileObject != NULL && TargetName != NULL ||
5012 FileObject == NULL && TargetName == NULL)
5015 try_return( ntStatus = STATUS_INVALID_PARAMETER);
5019 // Build up the name to reparse
5022 RtlInitUnicodeString( &uniMUPDeviceName,
5025 RtlInitUnicodeString( &uniIOMgrDeviceName,
5028 uniReparseName.Length = 0;
5029 uniReparseName.Buffer = NULL;
5032 // Be sure we have a target name
5035 if( DirEntry->NameInformation.TargetName.Length == 0)
5038 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
5043 if( !NT_SUCCESS( ntStatus) ||
5044 pDirEntry->TargetNameLength == 0)
5047 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5048 AFS_TRACE_LEVEL_ERROR,
5049 "AFSProcessDFSLink EvaluateTargetByID failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
5050 &DirEntry->NameInformation.FileName,
5051 DirEntry->ObjectInformation->FileId.Cell,
5052 DirEntry->ObjectInformation->FileId.Volume,
5053 DirEntry->ObjectInformation->FileId.Vnode,
5054 DirEntry->ObjectInformation->FileId.Unique,
5057 if( NT_SUCCESS( ntStatus))
5060 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
5063 try_return( ntStatus);
5067 // Update the target name
5070 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
5073 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
5075 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
5076 (USHORT)pDirEntry->TargetNameLength);
5078 if( !NT_SUCCESS( ntStatus))
5081 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5082 AFS_TRACE_LEVEL_ERROR,
5083 "AFSProcessDFSLink UpdateTargetName failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
5084 &DirEntry->NameInformation.FileName,
5085 DirEntry->ObjectInformation->FileId.Cell,
5086 DirEntry->ObjectInformation->FileId.Volume,
5087 DirEntry->ObjectInformation->FileId.Vnode,
5088 DirEntry->ObjectInformation->FileId.Unique,
5091 AFSReleaseResource( &DirEntry->NonPaged->Lock);
5093 try_return( ntStatus);
5096 AFSConvertToShared( &DirEntry->NonPaged->Lock);
5100 AFSAcquireShared( &DirEntry->NonPaged->Lock,
5104 uniReparseName.MaximumLength = uniMUPDeviceName.Length +
5106 DirEntry->NameInformation.TargetName.Length +
5109 if( RemainingPath != NULL &&
5110 RemainingPath->Length > 0)
5113 uniReparseName.MaximumLength += RemainingPath->Length;
5117 // Allocate the reparse buffer (from FS because might be returned in FileObject)
5120 uniReparseName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5121 uniReparseName.MaximumLength,
5122 AFS_REPARSE_NAME_TAG);
5124 if( uniReparseName.Buffer == NULL)
5127 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5128 AFS_TRACE_LEVEL_ERROR,
5129 "AFSProcessDFSLink uniReparseName.Buffer == NULL Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
5130 &DirEntry->NameInformation.FileName,
5131 DirEntry->ObjectInformation->FileId.Cell,
5132 DirEntry->ObjectInformation->FileId.Volume,
5133 DirEntry->ObjectInformation->FileId.Vnode,
5134 DirEntry->ObjectInformation->FileId.Unique,
5135 STATUS_INSUFFICIENT_RESOURCES));
5137 AFSReleaseResource( &DirEntry->NonPaged->Lock);
5139 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5143 // Start building the name
5146 if ( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\' &&
5147 DirEntry->NameInformation.TargetName.Buffer[ 1] == L':')
5150 RtlCopyMemory( uniReparseName.Buffer,
5151 uniIOMgrDeviceName.Buffer,
5152 uniIOMgrDeviceName.Length);
5154 uniReparseName.Length = uniIOMgrDeviceName.Length;
5159 RtlCopyMemory( uniReparseName.Buffer,
5160 uniMUPDeviceName.Buffer,
5161 uniMUPDeviceName.Length);
5163 uniReparseName.Length = uniMUPDeviceName.Length;
5165 if( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\')
5168 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
5170 uniReparseName.Length += sizeof( WCHAR);
5174 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
5175 DirEntry->NameInformation.TargetName.Buffer,
5176 DirEntry->NameInformation.TargetName.Length);
5178 uniReparseName.Length += DirEntry->NameInformation.TargetName.Length;
5180 AFSReleaseResource( &DirEntry->NonPaged->Lock);
5182 if( RemainingPath != NULL &&
5183 RemainingPath->Length > 0)
5186 if( uniReparseName.Buffer[ (uniReparseName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
5187 RemainingPath->Buffer[ 0] != L'\\')
5190 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
5192 uniReparseName.Length += sizeof( WCHAR);
5195 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
5196 RemainingPath->Buffer,
5197 RemainingPath->Length);
5199 uniReparseName.Length += RemainingPath->Length;
5202 if( FileObject != NULL)
5205 // Update the name in the file object
5208 if( FileObject->FileName.Buffer != NULL)
5212 // original FileObject buffer was not allocated by AFS
5215 ExFreePoolWithTag( FileObject->FileName.Buffer, 0);
5218 FileObject->FileName = uniReparseName;
5223 *TargetName = uniReparseName;
5226 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5227 AFS_TRACE_LEVEL_VERBOSE,
5228 "AFSProcessDFSLink Reparsing access to Fcb %wZ FID %08lX-%08lX-%08lX-%08lX to %wZ\n",
5229 &DirEntry->NameInformation.FileName,
5230 DirEntry->ObjectInformation->FileId.Cell,
5231 DirEntry->ObjectInformation->FileId.Volume,
5232 DirEntry->ObjectInformation->FileId.Vnode,
5233 DirEntry->ObjectInformation->FileId.Unique,
5237 // Return status reparse ...
5240 ntStatus = STATUS_REPARSE;
5247 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
5255 AFSGetFullFileName( IN AFSFcb *Fcb,
5257 OUT ULONG *FileNameLength,
5258 OUT WCHAR *FileName,
5259 IN OUT LONG *RemainingLength)
5262 NTSTATUS ntStatus = STATUS_SUCCESS;
5263 ULONG ulCopyLength = 0;
5264 ULONG cchCopied = 0;
5265 BOOLEAN bAddTrailingSlash = FALSE;
5266 USHORT usFullNameLength = 0;
5272 // Add a trailing slash for anything which is of the form \server\share
5275 if( ( Fcb->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY ||
5276 Fcb->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT) &&
5277 Ccb->FullFileName.Length > sizeof( WCHAR) &&
5278 Ccb->FullFileName.Buffer[ (Ccb->FullFileName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
5279 AFSIsShareName( &Ccb->FullFileName))
5281 bAddTrailingSlash = TRUE;
5284 usFullNameLength = sizeof( WCHAR) +
5285 AFSServerName.Length +
5286 Ccb->FullFileName.Length;
5288 if( bAddTrailingSlash)
5290 usFullNameLength += sizeof( WCHAR);
5293 if( *RemainingLength >= (LONG)usFullNameLength)
5295 ulCopyLength = (LONG)usFullNameLength;
5300 ulCopyLength = *RemainingLength;
5302 ntStatus = STATUS_BUFFER_OVERFLOW;
5305 *FileNameLength = (ULONG)usFullNameLength;
5307 if( ulCopyLength > 0)
5310 FileName[ 0] = L'\\';
5311 ulCopyLength -= sizeof( WCHAR);
5313 *RemainingLength -= sizeof( WCHAR);
5316 if( ulCopyLength >= AFSServerName.Length)
5319 RtlCopyMemory( &FileName[ 1],
5320 AFSServerName.Buffer,
5321 AFSServerName.Length);
5323 ulCopyLength -= AFSServerName.Length;
5324 *RemainingLength -= AFSServerName.Length;
5325 cchCopied += AFSServerName.Length/sizeof( WCHAR);
5327 if( ulCopyLength >= Ccb->FullFileName.Length)
5330 RtlCopyMemory( &FileName[ cchCopied],
5331 Ccb->FullFileName.Buffer,
5332 Ccb->FullFileName.Length);
5334 ulCopyLength -= Ccb->FullFileName.Length;
5335 *RemainingLength -= Ccb->FullFileName.Length;
5336 cchCopied += Ccb->FullFileName.Length/sizeof( WCHAR);
5338 if( ulCopyLength > 0 &&
5341 FileName[ cchCopied] = L'\\';
5343 *RemainingLength -= sizeof( WCHAR);
5349 RtlCopyMemory( &FileName[ cchCopied],
5350 Ccb->FullFileName.Buffer,
5353 *RemainingLength -= ulCopyLength;