2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSNameSupport.cpp
39 #include "AFSCommon.h"
44 // On entry, *VolumeCB must have a held ReferenceCount provided by
45 // the caller which will not be released. On successful exit, *OutVolumeCB
46 // will be assigned the new current volume with a held ReferenceCount.
48 // On entry, *ParentDirectoryCB must have a held DirOpenReferenceCount
49 // provided by the caller. This reference will not be released.
50 // On exit, if OutParentDirectoryCB is set, it will have a new reference.
52 // On exit, if OutDirectoryCB is set, it will have a reference.
56 AFSLocateNameEntry( IN GUID *AuthGroup,
57 IN PFILE_OBJECT FileObject,
58 IN OUT UNICODE_STRING *RootPathName,
59 IN UNICODE_STRING *ParsedPathName,
60 IN AFSNameArrayHdr *NameArray,
62 IN AFSVolumeCB *VolumeCB,
63 IN AFSDirectoryCB *ParentDirectoryCB,
64 OUT AFSVolumeCB **OutVolumeCB,
65 OUT LONG *OutVolumeReferenceReason,
66 OUT AFSDirectoryCB **OutParentDirectoryCB,
67 OUT AFSDirectoryCB **OutDirectoryCB,
68 OUT PUNICODE_STRING ComponentName)
71 NTSTATUS ntStatus = STATUS_SUCCESS;
72 UNICODE_STRING uniPathName, uniComponentName, uniRemainingPath, uniSearchName, uniFullPathName;
74 AFSDirectoryCB *pDirEntry = NULL, *pParentDirEntry = NULL;
75 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
76 UNICODE_STRING uniSysName;
77 ULONG ulSubstituteIndex = 0;
78 BOOLEAN bSubstituteName = FALSE;
79 AFSNameArrayHdr *pNameArray = NameArray;
80 BOOLEAN bAllocatedSymLinkBuffer = FALSE;
81 UNICODE_STRING uniRelativeName, uniNoOpName;
82 AFSObjectInfoCB *pCurrentObject = NULL;
83 AFSObjectInfoCB *pParentObjectInfo = NULL;
84 AFSVolumeCB *pCurrentVolume = NULL;
85 AFSVolumeCB *pTargetVolume = NULL;
86 BOOLEAN bReleaseCurrentVolume = FALSE;
87 LONG VolumeReferenceReason;
88 BOOLEAN bSubstitutedName = FALSE;
94 ASSERT( *OutVolumeCB != VolumeCB);
96 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
97 AFS_TRACE_LEVEL_VERBOSE_2,
98 "AFSLocateNameEntry (FO: %p) Processing full name %wZ\n",
102 RtlInitUnicodeString( &uniSysName,
105 RtlInitUnicodeString( &uniRelativeName,
108 RtlInitUnicodeString( &uniNoOpName,
112 // Cleanup some parameters
115 if( ComponentName != NULL)
118 ComponentName->Length = 0;
119 ComponentName->MaximumLength = 0;
120 ComponentName->Buffer = NULL;
124 // We will parse through the filename, locating the directory nodes until we encounter a cache miss
125 // Starting at the root node
128 pParentDirEntry = NULL;
130 pDirEntry = ParentDirectoryCB;
133 // Increment our reference on this dir entry
136 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
138 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
139 AFS_TRACE_LEVEL_VERBOSE,
140 "AFSLocateNameEntry Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
141 &pDirEntry->NameInformation.FileName,
146 pCurrentVolume = VolumeCB;
148 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
150 lCount = AFSVolumeIncrement( pCurrentVolume,
151 VolumeReferenceReason);
153 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
154 AFS_TRACE_LEVEL_VERBOSE,
155 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
157 VolumeReferenceReason,
160 bReleaseCurrentVolume = TRUE;
162 uniPathName = *ParsedPathName;
164 uniFullPathName = *RootPathName;
166 uniComponentName.Length = uniComponentName.MaximumLength = 0;
167 uniComponentName.Buffer = NULL;
169 uniRemainingPath.Length = uniRemainingPath.MaximumLength = 0;
170 uniRemainingPath.Buffer = NULL;
172 uniSearchName.Length = uniSearchName.MaximumLength = 0;
173 uniSearchName.Buffer = NULL;
178 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
180 ASSERT( pDirEntry->DirOpenReferenceCount > 0);
183 // Check our total link count for this name array
186 if( pNameArray->LinkCount >= (LONG)pDevExt->Specific.RDR.MaxLinkCount)
189 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
192 pCurrentObject = pDirEntry->ObjectInformation;
194 KeQueryTickCount( &pCurrentObject->LastAccessCount);
197 // Check that the directory entry is not deleted or pending delete
200 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
203 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
204 AFS_TRACE_LEVEL_ERROR,
205 "AFSLocateNameEntry (FO: %p) Deleted parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
207 &pDirEntry->NameInformation.FileName,
208 pCurrentObject->FileId.Cell,
209 pCurrentObject->FileId.Volume,
210 pCurrentObject->FileId.Vnode,
211 pCurrentObject->FileId.Unique,
212 STATUS_FILE_DELETED));
214 try_return( ntStatus = STATUS_FILE_DELETED);
217 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
220 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
221 AFS_TRACE_LEVEL_ERROR,
222 "AFSLocateNameEntry (FO: %p) Delete pending on %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
224 &pDirEntry->NameInformation.FileName,
225 pCurrentObject->FileId.Cell,
226 pCurrentObject->FileId.Volume,
227 pCurrentObject->FileId.Vnode,
228 pCurrentObject->FileId.Unique,
229 STATUS_DELETE_PENDING));
231 try_return( ntStatus = STATUS_DELETE_PENDING);
235 // Check if the directory requires verification
238 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
239 ( pCurrentObject->FileType != AFS_FILE_TYPE_DIRECTORY ||
240 !AFSIsEnumerationInProcess( pCurrentObject)))
243 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
244 AFS_TRACE_LEVEL_VERBOSE,
245 "AFSLocateNameEntry (FO: %p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
247 &pDirEntry->NameInformation.FileName,
248 pCurrentObject->FileId.Cell,
249 pCurrentObject->FileId.Volume,
250 pCurrentObject->FileId.Vnode,
251 pCurrentObject->FileId.Unique));
254 // Directory TreeLock should be exclusively held
257 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
260 ntStatus = AFSVerifyEntry( AuthGroup,
263 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
265 if( !NT_SUCCESS( ntStatus))
268 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
269 AFS_TRACE_LEVEL_ERROR,
270 "AFSLocateNameEntry (FO: %p) Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
272 &pDirEntry->NameInformation.FileName,
273 pCurrentObject->FileId.Cell,
274 pCurrentObject->FileId.Volume,
275 pCurrentObject->FileId.Vnode,
276 pCurrentObject->FileId.Unique,
279 try_return( ntStatus);
284 // Ensure the parent node has been evaluated, if not then go do it now
287 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) ||
288 pCurrentObject->FileType == AFS_FILE_TYPE_UNKNOWN)
291 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
292 AFS_TRACE_LEVEL_VERBOSE,
293 "AFSLocateNameEntry (FO: %p) Evaluating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
295 &pDirEntry->NameInformation.FileName,
296 pCurrentObject->FileId.Cell,
297 pCurrentObject->FileId.Volume,
298 pCurrentObject->FileId.Vnode,
299 pCurrentObject->FileId.Unique));
301 ntStatus = AFSEvaluateNode( AuthGroup,
304 if( !NT_SUCCESS( ntStatus))
307 if ( ntStatus == STATUS_NOT_A_DIRECTORY)
310 if ( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
313 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
314 AFS_TRACE_LEVEL_ERROR,
315 "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT NULL Status %08lX\n",
317 &pDirEntry->NameInformation.FileName,
318 pCurrentObject->FileId.Cell,
319 pCurrentObject->FileId.Volume,
320 pCurrentObject->FileId.Vnode,
321 pCurrentObject->FileId.Unique,
327 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
328 AFS_TRACE_LEVEL_ERROR,
329 "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT %08lX-%08lX-%08lX-%08lX Status %08lX\n",
331 &pDirEntry->NameInformation.FileName,
332 pCurrentObject->FileId.Cell,
333 pCurrentObject->FileId.Volume,
334 pCurrentObject->FileId.Vnode,
335 pCurrentObject->FileId.Unique,
336 pCurrentObject->ParentFileId.Cell,
337 pCurrentObject->ParentFileId.Volume,
338 pCurrentObject->ParentFileId.Vnode,
339 pCurrentObject->ParentFileId.Unique,
345 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
346 AFS_TRACE_LEVEL_ERROR,
347 "AFSLocateNameEntry (FO: %p) Failed to evaluate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
349 &pDirEntry->NameInformation.FileName,
350 pCurrentObject->FileId.Cell,
351 pCurrentObject->FileId.Volume,
352 pCurrentObject->FileId.Vnode,
353 pCurrentObject->FileId.Unique,
357 try_return( ntStatus);
360 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
364 // If this is a mount point or symlink then go get the real directory node
367 switch( pCurrentObject->FileType)
370 case AFS_FILE_TYPE_SYMLINK:
373 UNICODE_STRING uniTempName;
374 WCHAR *pTmpBuffer = NULL;
378 // Check if the flag is set to NOT evaluate a symlink
379 // and we are done with the parsing
382 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL) &&
383 uniRemainingPath.Length == 0)
387 // Pass back the directory entries
390 *OutParentDirectoryCB = pParentDirEntry;
392 pParentDirEntry = NULL;
394 *OutDirectoryCB = pDirEntry;
398 *OutVolumeCB = pCurrentVolume;
400 *OutVolumeReferenceReason = VolumeReferenceReason;
402 bReleaseCurrentVolume = FALSE;
404 *RootPathName = uniFullPathName;
406 try_return( ntStatus);
409 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
412 AFSAcquireExcl( &pDirEntry->NonPaged->Lock,
415 if( pDirEntry->NameInformation.TargetName.Length == 0)
419 // We'll reset the DV to ensure we validate the metadata content
422 pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
424 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
426 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
427 AFS_TRACE_LEVEL_VERBOSE,
428 "AFSLocateNameEntry (FO: %p) Verifying symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
430 &pDirEntry->NameInformation.FileName,
431 pCurrentObject->FileId.Cell,
432 pCurrentObject->FileId.Volume,
433 pCurrentObject->FileId.Vnode,
434 pCurrentObject->FileId.Unique));
437 // Directory TreeLock should be exclusively held
440 ntStatus = AFSVerifyEntry( AuthGroup,
443 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
445 if( !NT_SUCCESS( ntStatus))
448 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
449 AFS_TRACE_LEVEL_ERROR,
450 "AFSLocateNameEntry (FO: %p) Failed to verify symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
452 &pDirEntry->NameInformation.FileName,
453 pCurrentObject->FileId.Cell,
454 pCurrentObject->FileId.Volume,
455 pCurrentObject->FileId.Vnode,
456 pCurrentObject->FileId.Unique,
459 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
461 try_return( ntStatus);
465 // If the type changed then reprocess this entry
468 if( pCurrentObject->FileType != AFS_FILE_TYPE_SYMLINK)
471 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
479 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
483 // If we were given a zero length target name then deny access to the entry
486 if( pDirEntry->NameInformation.TargetName.Length == 0)
489 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
491 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
492 AFS_TRACE_LEVEL_ERROR,
493 "AFSLocateNameEntry (FO: %p) Failed to retrieve target name for symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
495 &pDirEntry->NameInformation.FileName,
496 pCurrentObject->FileId.Cell,
497 pCurrentObject->FileId.Volume,
498 pCurrentObject->FileId.Vnode,
499 pCurrentObject->FileId.Unique,
502 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
504 try_return( ntStatus);
507 if( AFSIsRelativeName( &pDirEntry->NameInformation.TargetName))
510 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
511 AFS_TRACE_LEVEL_VERBOSE,
512 "AFSLocateNameEntry (FO: %p) Processing relative symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
514 &pDirEntry->NameInformation.TargetName,
515 &pDirEntry->NameInformation.FileName,
516 pCurrentObject->FileId.Cell,
517 pCurrentObject->FileId.Volume,
518 pCurrentObject->FileId.Vnode,
519 pCurrentObject->FileId.Unique));
522 // We'll substitute this name into the current process name
523 // starting at where we sit in the path
526 uniTempName.Length = 0;
527 uniTempName.MaximumLength = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer) +
528 pDirEntry->NameInformation.TargetName.Length +
530 uniRemainingPath.Length;
532 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
533 uniTempName.MaximumLength,
534 AFS_NAME_BUFFER_ONE_TAG);
536 if( uniTempName.Buffer == NULL)
539 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
541 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
545 // We have so first copy in the portion up to the component
549 RtlCopyMemory( uniTempName.Buffer,
550 uniFullPathName.Buffer,
551 (ULONG)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer));
553 uniTempName.Length = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer);
555 if( bAllocatedSymLinkBuffer ||
559 pTmpBuffer = uniFullPathName.Buffer;
562 bAllocatedSymLinkBuffer = TRUE;
565 // Have we parsed this name yet? Better have at least once ...
568 if( uniComponentName.Length == 0)
574 // Copy in the target name ...
577 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
578 pDirEntry->NameInformation.TargetName.Buffer,
579 pDirEntry->NameInformation.TargetName.Length);
581 uniPathName.Buffer = &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)];
583 uniPathName.Length += pDirEntry->NameInformation.TargetName.Length;
584 uniPathName.MaximumLength = uniTempName.MaximumLength;
586 uniTempName.Length += pDirEntry->NameInformation.TargetName.Length;
589 // And now any remaining portion of the name
592 if( uniRemainingPath.Length > 0)
595 if( uniRemainingPath.Buffer[ 0] != L'\\')
598 uniRemainingPath.Buffer--;
599 uniRemainingPath.Length += sizeof( WCHAR);
601 uniPathName.Length += sizeof( WCHAR);
604 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
605 uniRemainingPath.Buffer,
606 uniRemainingPath.Length);
608 uniTempName.Length += uniRemainingPath.Length;
611 uniFullPathName = uniTempName;
613 if( pTmpBuffer != NULL)
616 AFSExFreePoolWithTag( pTmpBuffer, 0);
619 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
622 // Dereference the current entry ..
625 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
627 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
628 AFS_TRACE_LEVEL_VERBOSE,
629 "AFSLocateNameEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
630 &pDirEntry->NameInformation.FileName,
635 ASSERT( lCount >= 0);
638 // OK, need to back up one entry for the correct parent since the current
639 // entry we are on is the symlink itself
642 pDirEntry = AFSBackupEntry( pNameArray);
645 // Increment our reference on this dir entry
648 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
650 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
651 AFS_TRACE_LEVEL_VERBOSE,
652 "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
653 &pDirEntry->NameInformation.FileName,
658 if ( pParentDirEntry)
661 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
663 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
664 AFS_TRACE_LEVEL_VERBOSE,
665 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
666 &pParentDirEntry->NameInformation.FileName,
671 pParentDirEntry = NULL;
674 if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
677 pParentDirEntry = AFSGetParentEntry( pNameArray);
679 ASSERT( pParentDirEntry != pDirEntry);
681 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
683 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
684 AFS_TRACE_LEVEL_VERBOSE,
685 "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
686 &pParentDirEntry->NameInformation.FileName,
692 if ( pDirEntry->ObjectInformation->VolumeCB != pCurrentVolume)
695 lCount = AFSVolumeDecrement( pCurrentVolume,
696 VolumeReferenceReason);
698 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
699 AFS_TRACE_LEVEL_VERBOSE,
700 "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
702 VolumeReferenceReason,
705 pCurrentVolume = pDirEntry->ObjectInformation->VolumeCB;
707 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
709 lCount = AFSVolumeIncrement( pCurrentVolume,
710 VolumeReferenceReason);
712 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
713 AFS_TRACE_LEVEL_VERBOSE,
714 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
716 VolumeReferenceReason,
723 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
724 AFS_TRACE_LEVEL_VERBOSE,
725 "AFSLocateNameEntry (FO: %p) Processing absolute symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
727 &pDirEntry->NameInformation.TargetName,
728 &pDirEntry->NameInformation.FileName,
729 pCurrentObject->FileId.Cell,
730 pCurrentObject->FileId.Volume,
731 pCurrentObject->FileId.Vnode,
732 pCurrentObject->FileId.Unique));
734 if ( !AFSIsAbsoluteAFSName( &pDirEntry->NameInformation.TargetName))
737 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
738 AFS_TRACE_LEVEL_ERROR,
739 "AFSLocateNameEntry Name %wZ contains invalid server name\n",
740 &pDirEntry->NameInformation.TargetName));
743 // The correct response would be STATUS_OBJECT_PATH_INVALID
744 // but that prevents cmd.exe from performing a recursive
745 // directory enumeration when opening a directory entry
746 // that represents a symlink to an invalid path is discovered.
749 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
751 try_return( ntStatus = STATUS_OBJECT_PATH_NOT_FOUND);
755 // We'll substitute this name into the current process name
756 // starting at where we sit in the path
759 uniTempName.Length = 0;
760 uniTempName.MaximumLength = pDirEntry->NameInformation.TargetName.Length +
762 uniRemainingPath.Length;
764 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
765 uniTempName.MaximumLength,
766 AFS_NAME_BUFFER_TWO_TAG);
768 if( uniTempName.Buffer == NULL)
771 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
773 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
776 if( bAllocatedSymLinkBuffer ||
780 pTmpBuffer = uniFullPathName.Buffer;
783 bAllocatedSymLinkBuffer = TRUE;
786 // Have we parsed this name yet? Better have at least once ...
789 if( uniComponentName.Length == 0)
795 // Copy in the target name ...
798 RtlCopyMemory( uniTempName.Buffer,
799 &pDirEntry->NameInformation.TargetName.Buffer[ AFSMountRootName.Length/sizeof( WCHAR)],
800 pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length);
802 uniTempName.Length = pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length;
805 // And now any remaining portion of the name
808 if( uniRemainingPath.Length > 0)
811 if( uniRemainingPath.Buffer[ 0] != L'\\')
814 uniRemainingPath.Buffer--;
815 uniRemainingPath.Length += sizeof( WCHAR);
818 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
819 uniRemainingPath.Buffer,
820 uniRemainingPath.Length);
822 uniTempName.Length += uniRemainingPath.Length;
825 uniFullPathName = uniTempName;
827 uniPathName = uniTempName;
829 if( pTmpBuffer != NULL)
832 AFSExFreePoolWithTag( pTmpBuffer, 0);
835 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
838 // If our current volume is not the global root then make it so ...
841 if( pCurrentVolume != AFSGlobalRoot)
844 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
845 AFS_TRACE_LEVEL_VERBOSE,
846 "AFSLocateNameEntry (FO: %p) Current volume not global, resetting for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
848 &pDirEntry->NameInformation.FileName,
849 pCurrentObject->FileId.Cell,
850 pCurrentObject->FileId.Volume,
851 pCurrentObject->FileId.Vnode,
852 pCurrentObject->FileId.Unique));
854 lCount = AFSVolumeDecrement( pCurrentVolume,
855 VolumeReferenceReason);
857 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
858 AFS_TRACE_LEVEL_VERBOSE,
859 "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
861 VolumeReferenceReason,
864 pCurrentVolume = AFSGlobalRoot;
866 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
868 lCount = AFSVolumeIncrement( pCurrentVolume,
869 VolumeReferenceReason);
871 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
872 AFS_TRACE_LEVEL_VERBOSE,
873 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
875 VolumeReferenceReason,
880 // Dereference our current dir entry
883 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
885 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
886 AFS_TRACE_LEVEL_VERBOSE,
887 "AFSLocateNameEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
888 &pDirEntry->NameInformation.FileName,
893 ASSERT( lCount >= 0);
895 pDirEntry = pCurrentVolume->DirectoryCB;
898 // Reference the new dir entry
901 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
903 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
904 AFS_TRACE_LEVEL_VERBOSE,
905 "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
906 &pDirEntry->NameInformation.FileName,
912 // Reset the name array
913 // Persist the link count in the name array
916 lLinkCount = pNameArray->LinkCount;
918 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
919 AFS_TRACE_LEVEL_VERBOSE,
920 "AFSLocateNameEntry (FO: %p) Resetting name array for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
922 &pDirEntry->NameInformation.FileName,
923 pCurrentObject->FileId.Cell,
924 pCurrentObject->FileId.Volume,
925 pCurrentObject->FileId.Vnode,
926 pCurrentObject->FileId.Unique));
928 AFSResetNameArray( pNameArray,
931 pNameArray->LinkCount = lLinkCount;
933 if ( pParentDirEntry)
936 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
938 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
939 AFS_TRACE_LEVEL_VERBOSE,
940 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
941 &pParentDirEntry->NameInformation.FileName,
946 pParentDirEntry = NULL;
951 // Increment our link count
954 lCount = InterlockedIncrement( &pNameArray->LinkCount);
959 case AFS_FILE_TYPE_MOUNTPOINT:
963 // Check if the flag is set to NOT evaluate a mount point
964 // and we are done with the parsing
967 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL) &&
968 uniRemainingPath.Length == 0)
972 // Pass back the directory entries
975 *OutParentDirectoryCB = pParentDirEntry;
977 pParentDirEntry = NULL;
979 *OutDirectoryCB = pDirEntry;
983 *OutVolumeCB = pCurrentVolume;
985 *OutVolumeReferenceReason = VolumeReferenceReason;
987 bReleaseCurrentVolume = FALSE;
989 *RootPathName = uniFullPathName;
991 try_return( ntStatus);
994 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
995 AFS_TRACE_LEVEL_VERBOSE,
996 "AFSLocateNameEntry (FO: %p) Building MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
998 &pDirEntry->NameInformation.FileName,
999 pCurrentObject->FileId.Cell,
1000 pCurrentObject->FileId.Volume,
1001 pCurrentObject->FileId.Vnode,
1002 pCurrentObject->FileId.Unique));
1005 // Go retrieve the target entry for this node
1006 // Release the current volume cb entry since we would
1007 // have lock inversion in the following call
1008 // Also decrement the ref count on the volume
1011 ntStatus = AFSBuildMountPointTarget( AuthGroup,
1015 if( !NT_SUCCESS( ntStatus))
1018 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1019 AFS_TRACE_LEVEL_ERROR,
1020 "AFSLocateNameEntry (FO: %p) Failed to build MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1022 &pDirEntry->NameInformation.FileName,
1023 pCurrentObject->FileId.Cell,
1024 pCurrentObject->FileId.Volume,
1025 pCurrentObject->FileId.Vnode,
1026 pCurrentObject->FileId.Unique,
1029 try_return( ntStatus);
1032 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
1034 lCount = AFSVolumeDecrement( pCurrentVolume,
1035 VolumeReferenceReason);
1037 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1038 AFS_TRACE_LEVEL_VERBOSE,
1039 "AFSLocateNameEntry Decrement2 count on volume %p Reason %u Cnt %d\n",
1041 VolumeReferenceReason,
1044 pCurrentVolume = pTargetVolume;
1046 pTargetVolume = NULL;
1048 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
1050 VolumeReferenceReason = AFS_VOLUME_REFERENCE_MOUNTPT;
1053 // We want to restart processing here on the new parent ...
1054 // Deref and ref count the entries
1057 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1059 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1060 AFS_TRACE_LEVEL_VERBOSE,
1061 "AFSLocateNameEntry Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
1062 &pDirEntry->NameInformation.FileName,
1067 ASSERT( lCount >= 0);
1069 pDirEntry = pCurrentVolume->DirectoryCB;
1071 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1073 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1074 AFS_TRACE_LEVEL_VERBOSE,
1075 "AFSLocateNameEntry Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
1076 &pDirEntry->NameInformation.FileName,
1082 // The name array stores both the mount point and the target.
1083 // Insert the target.
1086 AFSInsertNextElement( pNameArray,
1089 if ( pParentDirEntry)
1092 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1094 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1095 AFS_TRACE_LEVEL_VERBOSE,
1096 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1097 &pParentDirEntry->NameInformation.FileName,
1102 pParentDirEntry = NULL;
1106 // Increment our link count
1109 lCount = InterlockedIncrement( &pNameArray->LinkCount);
1114 case AFS_FILE_TYPE_DFSLINK:
1117 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL))
1121 // Pass back the directory entries
1124 *OutParentDirectoryCB = pParentDirEntry;
1126 pParentDirEntry = NULL;
1128 *OutDirectoryCB = pDirEntry;
1132 *OutVolumeCB = pCurrentVolume;
1134 *OutVolumeReferenceReason = VolumeReferenceReason;
1136 bReleaseCurrentVolume = FALSE;
1138 *RootPathName = uniFullPathName;
1140 try_return( ntStatus);
1144 // This is a DFS link so we need to update the file name and return STATUS_REPARSE to the
1145 // system for it to reevaluate it
1148 if( FileObject != NULL)
1151 ntStatus = AFSProcessDFSLink( pDirEntry,
1160 // This is where we have been re-entered from an NP evaluation call via the BuildBranch()
1164 ntStatus = STATUS_INVALID_PARAMETER;
1167 if( ntStatus != STATUS_SUCCESS &&
1168 ntStatus != STATUS_REPARSE)
1171 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1172 AFS_TRACE_LEVEL_ERROR,
1173 "AFSLocateNameEntry (FO: %p) Failed to process DFSLink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1175 &pDirEntry->NameInformation.FileName,
1176 pCurrentObject->FileId.Cell,
1177 pCurrentObject->FileId.Volume,
1178 pCurrentObject->FileId.Vnode,
1179 pCurrentObject->FileId.Unique,
1183 try_return( ntStatus);
1186 case AFS_FILE_TYPE_UNKNOWN:
1187 case AFS_FILE_TYPE_INVALID:
1191 // Something was not processed ...
1194 try_return( ntStatus = STATUS_ACCESS_DENIED);
1197 } /* end of switch */
1200 // If the parent is not initialized then do it now
1203 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1204 !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED) &&
1205 uniPathName.Length > 0)
1208 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1209 AFS_TRACE_LEVEL_VERBOSE,
1210 "AFSLocateNameEntry (FO: %p) Enumerating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1212 &pDirEntry->NameInformation.FileName,
1213 pCurrentObject->FileId.Cell,
1214 pCurrentObject->FileId.Volume,
1215 pCurrentObject->FileId.Vnode,
1216 pCurrentObject->FileId.Unique));
1218 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1221 if( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1224 ntStatus = AFSEnumerateDirectory( AuthGroup,
1228 if( !NT_SUCCESS( ntStatus))
1231 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1233 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1234 AFS_TRACE_LEVEL_ERROR,
1235 "AFSLocateNameEntry (FO: %p) Failed to enumerate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1237 &pDirEntry->NameInformation.FileName,
1238 pCurrentObject->FileId.Cell,
1239 pCurrentObject->FileId.Volume,
1240 pCurrentObject->FileId.Vnode,
1241 pCurrentObject->FileId.Unique,
1244 try_return( ntStatus);
1248 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1250 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1253 if( uniPathName.Length > 0)
1256 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1257 AFS_TRACE_LEVEL_ERROR,
1258 "AFSLocateNameEntry (FO: %p) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1260 &pDirEntry->NameInformation.FileName,
1261 pCurrentObject->FileId.Cell,
1262 pCurrentObject->FileId.Volume,
1263 pCurrentObject->FileId.Vnode,
1264 pCurrentObject->FileId.Unique));
1266 // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1267 // one of the components of the path is not a directory. However, returning
1268 // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1269 // Instead IIS insists on treating the target file as if it is a directory containing
1270 // a potential web.config file. NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1271 // AFS will follow suit.
1273 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1278 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1279 AFS_TRACE_LEVEL_VERBOSE,
1280 "AFSLocateNameEntry (FO: %p) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1282 &pDirEntry->NameInformation.FileName,
1283 pCurrentObject->FileId.Cell,
1284 pCurrentObject->FileId.Volume,
1285 pCurrentObject->FileId.Vnode,
1286 pCurrentObject->FileId.Unique));
1289 // Pass back the directory entries
1292 *OutParentDirectoryCB = pParentDirEntry;
1294 pParentDirEntry = NULL;
1296 *OutDirectoryCB = pDirEntry;
1300 *OutVolumeCB = pCurrentVolume;
1302 *OutVolumeReferenceReason = VolumeReferenceReason;
1304 bReleaseCurrentVolume = FALSE;
1306 *RootPathName = uniFullPathName;
1309 try_return( ntStatus);
1313 // If we are at the end of the processing, set our returned information and get out
1316 if( uniPathName.Length == 0)
1319 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1320 AFS_TRACE_LEVEL_VERBOSE,
1321 "AFSLocateNameEntry (FO: %p) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1323 &pDirEntry->NameInformation.FileName,
1324 pCurrentObject->FileId.Cell,
1325 pCurrentObject->FileId.Volume,
1326 pCurrentObject->FileId.Vnode,
1327 pCurrentObject->FileId.Unique));
1330 // Pass back the directory entries
1333 *OutParentDirectoryCB = pParentDirEntry;
1335 pParentDirEntry = NULL;
1337 *OutDirectoryCB = pDirEntry;
1341 *OutVolumeCB = pCurrentVolume;
1343 *OutVolumeReferenceReason = VolumeReferenceReason;
1345 bReleaseCurrentVolume = FALSE;
1347 *RootPathName = uniFullPathName;
1349 try_return( ntStatus);
1353 // We may have returned to the top of the while( TRUE)
1355 if( bSubstituteName &&
1356 uniSearchName.Buffer != NULL)
1359 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1361 bSubstituteName = FALSE;
1363 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1364 uniSearchName.Buffer = NULL;
1367 ulSubstituteIndex = 1;
1369 ntStatus = STATUS_SUCCESS;
1372 // Get the next component name
1375 FsRtlDissectName( uniPathName,
1380 // Check for the . and .. in the path
1383 if( RtlCompareUnicodeString( &uniComponentName,
1388 uniPathName = uniRemainingPath;
1393 if( RtlCompareUnicodeString( &uniComponentName,
1398 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1399 AFS_TRACE_LEVEL_VERBOSE,
1400 "AFSLocateNameEntry (FO: %p) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1402 &pDirEntry->NameInformation.FileName,
1403 pCurrentObject->FileId.Cell,
1404 pCurrentObject->FileId.Volume,
1405 pCurrentObject->FileId.Vnode,
1406 pCurrentObject->FileId.Unique));
1409 // Need to back up one entry in the name array
1411 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1413 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1414 AFS_TRACE_LEVEL_VERBOSE,
1415 "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1416 &pDirEntry->NameInformation.FileName,
1421 ASSERT( lCount >= 0);
1423 pDirEntry = AFSBackupEntry( NameArray);
1425 if( pDirEntry == NULL)
1428 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1429 AFS_TRACE_LEVEL_ERROR,
1430 "AFSLocateNameEntry AFSBackupEntry failed\n"));
1432 try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1435 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1437 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1438 AFS_TRACE_LEVEL_VERBOSE,
1439 "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1440 &pDirEntry->NameInformation.FileName,
1445 if ( pParentDirEntry)
1448 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1450 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1451 AFS_TRACE_LEVEL_VERBOSE,
1452 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1453 &pParentDirEntry->NameInformation.FileName,
1458 pParentDirEntry = NULL;
1461 if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1464 pParentDirEntry = AFSGetParentEntry( pNameArray);
1466 ASSERT( pParentDirEntry != pDirEntry);
1468 if ( pParentDirEntry)
1471 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
1473 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1474 AFS_TRACE_LEVEL_VERBOSE,
1475 "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
1476 &pParentDirEntry->NameInformation.FileName,
1483 if ( pDirEntry->ObjectInformation->VolumeCB != pCurrentVolume)
1486 lCount = AFSVolumeDecrement( pCurrentVolume,
1487 VolumeReferenceReason);
1489 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1490 AFS_TRACE_LEVEL_VERBOSE,
1491 "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
1493 VolumeReferenceReason,
1496 pCurrentVolume = pDirEntry->ObjectInformation->VolumeCB;
1498 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
1500 lCount = AFSVolumeIncrement( pCurrentVolume,
1501 VolumeReferenceReason);
1503 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1504 AFS_TRACE_LEVEL_VERBOSE,
1505 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
1507 VolumeReferenceReason,
1511 uniPathName = uniRemainingPath;
1517 // Update our pointers
1520 if ( pParentDirEntry)
1523 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1525 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1526 AFS_TRACE_LEVEL_VERBOSE,
1527 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1528 &pParentDirEntry->NameInformation.FileName,
1534 pParentDirEntry = pDirEntry;
1538 uniSearchName = uniComponentName;
1540 while( pDirEntry == NULL)
1544 // If the SearchName contains @SYS then we perform the substitution.
1545 // If there is no substitution we give up.
1548 if( !bSubstituteName &&
1549 FsRtlIsNameInExpression( &uniSysName,
1555 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1556 AFS_TRACE_LEVEL_VERBOSE_2,
1557 "AFSLocateNameEntry (FO: %p) Processing @SYS substitution for %wZ Index %08lX\n",
1560 ulSubstituteIndex));
1562 ntStatus = AFSSubstituteSysName( &uniComponentName,
1566 if ( NT_SUCCESS( ntStatus))
1569 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1570 AFS_TRACE_LEVEL_VERBOSE_2,
1571 "AFSLocateNameEntry (FO: %p) Located substitution %wZ for %wZ Index %08lX\n",
1575 ulSubstituteIndex));
1578 // Go reparse the name again
1581 bSubstituteName = TRUE;
1583 ulSubstituteIndex++; // For the next entry, if needed
1585 continue; // while( pDirEntry == NULL)
1590 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1591 AFS_TRACE_LEVEL_ERROR,
1592 "AFSLocateNameEntry (FO: %p) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1598 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1602 // Pass back the directory entries
1605 *OutParentDirectoryCB = pParentDirEntry;
1607 pParentDirEntry = NULL;
1609 *OutDirectoryCB = NULL;
1611 *OutVolumeCB = pCurrentVolume;
1613 *OutVolumeReferenceReason = VolumeReferenceReason;
1615 bReleaseCurrentVolume = FALSE;
1617 if( ComponentName != NULL)
1620 *ComponentName = uniComponentName;
1623 *RootPathName = uniFullPathName;
1627 // We can't possibly have a pDirEntry since the lookup failed
1629 try_return( ntStatus);
1634 // Generate the CRC on the node and perform a case sensitive lookup
1637 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1638 AFS_TRACE_LEVEL_VERBOSE_2,
1639 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case sensitive\n",
1643 ulCRC = AFSGenerateCRC( &uniSearchName,
1646 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1649 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1653 if( pDirEntry == NULL)
1657 // Missed so perform a case insensitive lookup
1660 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1661 AFS_TRACE_LEVEL_VERBOSE_2,
1662 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case insensitive\n",
1666 ulCRC = AFSGenerateCRC( &uniSearchName,
1669 AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1673 if( pDirEntry == NULL)
1677 // OK, if this component is a valid short name then try
1678 // a lookup in the short name tree
1681 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1682 RtlIsNameLegalDOS8Dot3( &uniSearchName,
1687 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1688 AFS_TRACE_LEVEL_VERBOSE_2,
1689 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ short name\n",
1693 AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1698 if ( pDirEntry == NULL &&
1699 pParentDirEntry->ObjectInformation->VolumeCB == AFSGlobalRoot)
1703 // Check with the service to see if this is a valid cell name
1704 // that can be automatically resolved. Drop the shared TreeLock
1705 // since AFSCheckCellName must acquire it exclusively.
1708 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1710 ntStatus = AFSCheckCellName( AuthGroup,
1714 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1718 if( pDirEntry == NULL)
1722 // If we substituted a name then reset our search name and try again
1725 if( bSubstituteName)
1728 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1730 uniSearchName = uniComponentName;
1732 bSubstituteName = FALSE;
1734 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1736 continue; // while( pDirEntry == NULL)
1740 // Node name not found so get out
1743 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1745 if( uniRemainingPath.Length > 0)
1748 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1750 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1751 AFS_TRACE_LEVEL_VERBOSE,
1752 "AFSLocateNameEntry (FO: %p) Returning path not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1755 pCurrentObject->FileId.Cell,
1756 pCurrentObject->FileId.Volume,
1757 pCurrentObject->FileId.Vnode,
1758 pCurrentObject->FileId.Unique));
1763 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1765 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1766 AFS_TRACE_LEVEL_VERBOSE,
1767 "AFSLocateNameEntry (FO: %p) Returning name not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1770 pCurrentObject->FileId.Cell,
1771 pCurrentObject->FileId.Volume,
1772 pCurrentObject->FileId.Vnode,
1773 pCurrentObject->FileId.Unique));
1776 // Pass back the directory entries
1779 *OutParentDirectoryCB = pParentDirEntry;
1781 pParentDirEntry = NULL;
1783 *OutDirectoryCB = NULL;
1785 *OutVolumeCB = pCurrentVolume;
1787 *OutVolumeReferenceReason = VolumeReferenceReason;
1789 bReleaseCurrentVolume = FALSE;
1791 if( ComponentName != NULL)
1794 *ComponentName = uniComponentName;
1797 *RootPathName = uniFullPathName;
1800 try_return( ntStatus);
1807 // Here we have a match on the case insensitive lookup for the name. If there
1808 // Is more than one link entry for this node then fail the lookup request
1811 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1812 pDirEntry->CaseInsensitiveList.fLink != NULL)
1816 // Increment our dir entry ref count since we will decrement it on exit
1819 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1821 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1822 AFS_TRACE_LEVEL_VERBOSE,
1823 "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1824 &pDirEntry->NameInformation.FileName,
1829 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1831 try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1836 if( pDirEntry != NULL)
1840 // If the verify flag is set on the parent and the current entry is deleted
1841 // revalidate the parent and search again.
1844 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1845 BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1848 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1850 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1851 AFS_TRACE_LEVEL_VERBOSE,
1852 "AFSLocateNameEntry (FO: %p) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1854 &pParentDirEntry->NameInformation.FileName,
1855 pParentDirEntry->ObjectInformation->FileId.Cell,
1856 pParentDirEntry->ObjectInformation->FileId.Volume,
1857 pParentDirEntry->ObjectInformation->FileId.Vnode,
1858 pParentDirEntry->ObjectInformation->FileId.Unique));
1861 // Directory TreeLock should be exclusively held
1864 AFSAcquireExcl( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1867 ntStatus = AFSVerifyEntry( AuthGroup,
1870 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1872 if( !NT_SUCCESS( ntStatus))
1875 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1876 AFS_TRACE_LEVEL_ERROR,
1877 "AFSLocateNameEntry (FO: %p) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1879 &pParentDirEntry->NameInformation.FileName,
1880 pParentDirEntry->ObjectInformation->FileId.Cell,
1881 pParentDirEntry->ObjectInformation->FileId.Volume,
1882 pParentDirEntry->ObjectInformation->FileId.Vnode,
1883 pParentDirEntry->ObjectInformation->FileId.Unique,
1886 try_return( ntStatus);
1889 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1890 AFS_TRACE_LEVEL_VERBOSE,
1891 "AFSLocateNameEntry (FO: %p) Reprocessing component %wZ in parent %wZ\n",
1894 &pParentDirEntry->NameInformation.FileName));
1903 // Increment our dir entry ref count
1906 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1908 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1909 AFS_TRACE_LEVEL_VERBOSE,
1910 "AFSLocateNameEntry Increment6 count on %wZ DE %p Ccb %p Cnt %d\n",
1911 &pDirEntry->NameInformation.FileName,
1917 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1919 } // End while( pDirEntry == NULL)
1922 // If we have a dirEntry for this component, perform some basic validation on it
1925 if( pDirEntry != NULL &&
1926 BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1929 pCurrentObject = pDirEntry->ObjectInformation;
1931 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1932 AFS_TRACE_LEVEL_ERROR,
1933 "AFSLocateNameEntry (FO: %p) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1935 &pDirEntry->NameInformation.FileName,
1936 pCurrentObject->FileId.Cell,
1937 pCurrentObject->FileId.Volume,
1938 pCurrentObject->FileId.Vnode,
1939 pCurrentObject->FileId.Unique));
1942 // This entry was deleted through the invalidation call back so perform cleanup
1946 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1949 pParentObjectInfo = AFSFindObjectInfo( pCurrentObject->VolumeCB,
1950 &pCurrentObject->ParentFileId,
1954 ASSERT( pParentObjectInfo != NULL);
1956 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1959 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1962 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1964 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1965 AFS_TRACE_LEVEL_VERBOSE,
1966 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1967 &pDirEntry->NameInformation.FileName,
1972 ASSERT( lCount >= 0);
1975 pDirEntry->NameArrayReferenceCount <= 0)
1978 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1979 AFS_TRACE_LEVEL_VERBOSE,
1980 "AFSLocateNameEntry Deleting dir entry %p (%p) for %wZ\n",
1983 &pDirEntry->NameInformation.FileName));
1986 // Remove and delete the directory entry from the parent list
1989 AFSDeleteDirEntry( pParentObjectInfo,
1992 AFSAcquireShared( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1995 if( pCurrentObject->ObjectReferenceCount <= 0)
1998 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
2001 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2002 AFS_TRACE_LEVEL_VERBOSE,
2003 "AFSLocateNameEntry Removing object %p from volume tree\n",
2006 AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
2007 &pCurrentObject->TreeEntry);
2009 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
2013 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
2018 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2019 AFS_TRACE_LEVEL_VERBOSE,
2020 "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
2022 &pDirEntry->NameInformation.FileName));
2024 SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
2026 AFSRemoveNameEntry( pParentObjectInfo,
2030 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2032 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
2034 AFSReleaseObjectInfo( &pParentObjectInfo);
2037 // We deleted the dir entry so check if there is any remaining portion
2038 // of the name to process.
2041 if( uniRemainingPath.Length > 0)
2044 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
2046 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2047 AFS_TRACE_LEVEL_VERBOSE,
2048 "AFSLocateNameEntry (FO: %p) Returning path not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2051 pCurrentObject->FileId.Cell,
2052 pCurrentObject->FileId.Volume,
2053 pCurrentObject->FileId.Vnode,
2054 pCurrentObject->FileId.Unique));
2059 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
2061 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2062 AFS_TRACE_LEVEL_VERBOSE,
2063 "AFSLocateNameEntry (FO: %p) Returning name not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2066 pCurrentObject->FileId.Cell,
2067 pCurrentObject->FileId.Volume,
2068 pCurrentObject->FileId.Vnode,
2069 pCurrentObject->FileId.Unique));
2072 // Pass back the directory entries
2075 *OutParentDirectoryCB = pParentDirEntry;
2077 pParentDirEntry = NULL;
2079 *OutDirectoryCB = NULL;
2081 *OutVolumeCB = pCurrentVolume;
2083 *OutVolumeReferenceReason = VolumeReferenceReason;
2085 bReleaseCurrentVolume = FALSE;
2087 if( ComponentName != NULL)
2090 *ComponentName = uniComponentName;
2093 *RootPathName = uniFullPathName;
2097 if( ntStatus != STATUS_SUCCESS)
2100 try_return( ntStatus);
2104 // If we ended up substituting a name in the component then update
2105 // the full path and update the pointers
2108 if( bSubstituteName)
2111 BOOLEAN bRelativeOpen = FALSE;
2113 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2114 AFS_TRACE_LEVEL_VERBOSE_2,
2115 "AFSLocateNameEntry (FO: %p) Substituting %wZ into %wZ Index %08lX\n",
2119 ulSubstituteIndex));
2121 if( FileObject != NULL &&
2122 FileObject->RelatedFileObject != NULL)
2125 bRelativeOpen = TRUE;
2129 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
2130 // and free the prior Buffer contents but only if the fourth
2131 // parameter is TRUE.
2134 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
2139 bAllocatedSymLinkBuffer ||
2142 if( !NT_SUCCESS( ntStatus))
2145 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2146 AFS_TRACE_LEVEL_ERROR,
2147 "AFSLocateNameEntry (FO: %p) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
2154 try_return( ntStatus);
2158 // We have substituted a name into the buffer so if we do this again for this
2159 // path, we need to free up the buffer we allocated.
2162 bSubstitutedName = TRUE;
2166 // Update the search parameters
2169 uniPathName = uniRemainingPath;
2172 // Check if the is a SymLink entry but has no Target FileID or Name. In this
2173 // case it might be a DFS Link so let's go and evaluate it to be sure
2176 if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
2177 ( pCurrentObject->TargetFileId.Vnode == 0 ||
2178 pDirEntry->NameInformation.TargetName.Length == 0))
2181 ntStatus = AFSValidateSymLink( AuthGroup,
2184 if( !NT_SUCCESS( ntStatus))
2187 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2188 AFS_TRACE_LEVEL_ERROR,
2189 "AFSLocateNameEntry (FO: %p) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2191 &pDirEntry->NameInformation.FileName,
2192 pCurrentObject->FileId.Cell,
2193 pCurrentObject->FileId.Volume,
2194 pCurrentObject->FileId.Vnode,
2195 pCurrentObject->FileId.Unique,
2198 try_return( ntStatus);
2203 // Update the name array
2206 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2207 AFS_TRACE_LEVEL_VERBOSE,
2208 "AFSLocateNameEntry (FO: %p) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2210 &pDirEntry->NameInformation.FileName,
2211 pCurrentObject->FileId.Cell,
2212 pCurrentObject->FileId.Volume,
2213 pCurrentObject->FileId.Vnode,
2214 pCurrentObject->FileId.Unique));
2216 ntStatus = AFSInsertNextElement( pNameArray,
2219 if( !NT_SUCCESS( ntStatus))
2222 try_return( ntStatus);
2228 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2229 AFS_TRACE_LEVEL_VERBOSE,
2230 "AFSLocateNameEntry (FO: %p) Completed processing %wZ Status %08lX\n",
2235 if( ( !NT_SUCCESS( ntStatus) &&
2236 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
2237 ntStatus == STATUS_REPARSE)
2239 if( RootPathName->Buffer != uniFullPathName.Buffer)
2242 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
2248 if( *OutParentDirectoryCB != NULL)
2251 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2252 AFS_TRACE_LEVEL_VERBOSE,
2253 "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
2254 &(*OutParentDirectoryCB)->NameInformation.FileName,
2255 *OutParentDirectoryCB,
2257 (*OutParentDirectoryCB)->DirOpenReferenceCount));
2260 if( *OutDirectoryCB != NULL)
2263 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2264 AFS_TRACE_LEVEL_VERBOSE,
2265 "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
2266 &(*OutDirectoryCB)->NameInformation.FileName,
2269 (*OutDirectoryCB)->DirOpenReferenceCount));
2273 if( pDirEntry != NULL)
2276 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
2278 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2279 AFS_TRACE_LEVEL_VERBOSE,
2280 "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
2281 &pDirEntry->NameInformation.FileName,
2286 ASSERT( lCount >= 0);
2289 if( pParentDirEntry != NULL)
2292 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
2294 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2295 AFS_TRACE_LEVEL_VERBOSE,
2296 "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
2297 &pParentDirEntry->NameInformation.FileName,
2302 ASSERT( lCount >= 0);
2305 if( bReleaseCurrentVolume)
2308 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
2310 lCount = AFSVolumeDecrement( pCurrentVolume,
2311 VolumeReferenceReason);
2313 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2314 AFS_TRACE_LEVEL_VERBOSE,
2315 "AFSLocateNameEntry Decrement7 count on volume %p Reason %u Cnt %d\n",
2317 VolumeReferenceReason,
2320 bReleaseCurrentVolume = FALSE;
2323 if( bSubstituteName &&
2324 uniSearchName.Buffer != NULL)
2327 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
2335 AFSCreateDirEntry( IN GUID *AuthGroup,
2336 IN AFSObjectInfoCB *ParentObjectInfo,
2337 IN AFSDirectoryCB *ParentDirCB,
2338 IN PUNICODE_STRING FileName,
2339 IN PUNICODE_STRING ComponentName,
2340 IN ULONG Attributes,
2341 IN OUT AFSDirectoryCB **DirEntry)
2344 UNREFERENCED_PARAMETER(FileName);
2345 NTSTATUS ntStatus = STATUS_SUCCESS;
2346 AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
2347 LARGE_INTEGER liFileSize = {0,0};
2353 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2354 AFS_TRACE_LEVEL_VERBOSE_2,
2355 "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
2356 &ParentDirCB->NameInformation.FileName,
2357 ParentObjectInfo->FileId.Cell,
2358 ParentObjectInfo->FileId.Volume,
2359 ParentObjectInfo->FileId.Vnode,
2360 ParentObjectInfo->FileId.Unique,
2365 // OK, before inserting the node into the parent tree, issue
2366 // the request to the service for node creation
2367 // We will need to drop the lock on the parent node since the create
2368 // could cause a callback into the file system to invalidate it's cache
2371 ntStatus = AFSNotifyFileCreate( AuthGroup,
2379 // If the returned status is STATUS_REPARSE then the entry exists
2380 // and we raced, get out.
2382 if( ntStatus == STATUS_REPARSE)
2385 *DirEntry = pDirNode;
2387 try_return( ntStatus = STATUS_SUCCESS);
2390 if( !NT_SUCCESS( ntStatus))
2393 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2394 AFS_TRACE_LEVEL_ERROR,
2395 "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
2396 &ParentDirCB->NameInformation.FileName,
2397 ParentObjectInfo->FileId.Cell,
2398 ParentObjectInfo->FileId.Volume,
2399 ParentObjectInfo->FileId.Vnode,
2400 ParentObjectInfo->FileId.Unique,
2405 try_return( ntStatus);
2409 // If AFSNotifyFileCreate returns pDirNode != NULL, then its
2410 // DirOpenReferenceCount is held.
2413 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2417 // Before attempting to insert the new entry, check if we need to validate the parent
2420 if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2423 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2424 AFS_TRACE_LEVEL_VERBOSE,
2425 "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2426 &ParentDirCB->NameInformation.FileName,
2427 ParentObjectInfo->FileId.Cell,
2428 ParentObjectInfo->FileId.Volume,
2429 ParentObjectInfo->FileId.Vnode,
2430 ParentObjectInfo->FileId.Unique));
2432 ntStatus = AFSVerifyEntry( AuthGroup,
2435 if( !NT_SUCCESS( ntStatus))
2438 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2439 AFS_TRACE_LEVEL_ERROR,
2440 "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2441 &ParentDirCB->NameInformation.FileName,
2442 ParentObjectInfo->FileId.Cell,
2443 ParentObjectInfo->FileId.Volume,
2444 ParentObjectInfo->FileId.Vnode,
2445 ParentObjectInfo->FileId.Unique,
2448 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2450 try_return( ntStatus);
2455 // Check for the entry in the event we raced with some other thread
2458 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2459 (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2462 if( pExistingDirNode != NULL)
2464 if (AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2465 &pExistingDirNode->ObjectInformation->FileId))
2468 if ( pExistingDirNode != pDirNode)
2471 lCount = InterlockedDecrement( &pDirNode->DirOpenReferenceCount);
2473 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2474 AFS_TRACE_LEVEL_VERBOSE,
2475 "AFSCreateDirEntry Decrement count on %wZ DE %p Cnt %d\n",
2476 &pDirNode->NameInformation.FileName,
2480 AFSDeleteDirEntry( ParentObjectInfo,
2483 lCount = InterlockedIncrement( &pExistingDirNode->DirOpenReferenceCount);
2485 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2486 AFS_TRACE_LEVEL_VERBOSE,
2487 "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2488 &pExistingDirNode->NameInformation.FileName,
2492 *DirEntry = pExistingDirNode;
2495 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2497 try_return( ntStatus = STATUS_SUCCESS);
2503 // Need to tear down this entry and rebuild it below
2506 if( pExistingDirNode->DirOpenReferenceCount <= 0 &&
2507 pExistingDirNode->NameArrayReferenceCount <= 0)
2510 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2511 AFS_TRACE_LEVEL_VERBOSE,
2512 "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2514 &pExistingDirNode->NameInformation.FileName,
2515 pExistingDirNode->ObjectInformation->FileId.Cell,
2516 pExistingDirNode->ObjectInformation->FileId.Volume,
2517 pExistingDirNode->ObjectInformation->FileId.Vnode,
2518 pExistingDirNode->ObjectInformation->FileId.Unique,
2519 pDirNode->ObjectInformation->FileId.Cell,
2520 pDirNode->ObjectInformation->FileId.Volume,
2521 pDirNode->ObjectInformation->FileId.Vnode,
2522 pDirNode->ObjectInformation->FileId.Unique));
2524 AFSDeleteDirEntry( ParentObjectInfo,
2530 SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2532 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2533 AFS_TRACE_LEVEL_VERBOSE,
2534 "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2536 &pExistingDirNode->NameInformation.FileName,
2537 pExistingDirNode->ObjectInformation->FileId.Cell,
2538 pExistingDirNode->ObjectInformation->FileId.Volume,
2539 pExistingDirNode->ObjectInformation->FileId.Vnode,
2540 pExistingDirNode->ObjectInformation->FileId.Unique,
2541 pDirNode->ObjectInformation->FileId.Cell,
2542 pDirNode->ObjectInformation->FileId.Volume,
2543 pDirNode->ObjectInformation->FileId.Vnode,
2544 pDirNode->ObjectInformation->FileId.Unique));
2546 AFSRemoveNameEntry( ParentObjectInfo,
2552 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2553 AFS_TRACE_LEVEL_VERBOSE_2,
2554 "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2555 &ParentDirCB->NameInformation.FileName,
2556 ParentObjectInfo->FileId.Cell,
2557 ParentObjectInfo->FileId.Volume,
2558 ParentObjectInfo->FileId.Vnode,
2559 ParentObjectInfo->FileId.Unique,
2563 // Insert the directory node
2566 AFSInsertDirectoryNode( ParentObjectInfo,
2571 // Pass back the dir entry
2574 *DirEntry = pDirNode;
2576 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2587 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2588 IN AFSDirectoryCB *DirEntry,
2589 IN BOOLEAN InsertInEnumList)
2597 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2600 // Insert the node into the directory node tree
2603 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2604 AFS_TRACE_LEVEL_VERBOSE,
2605 "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2607 &DirEntry->NameInformation.FileName));
2609 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2611 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2614 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2616 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2617 AFS_TRACE_LEVEL_VERBOSE,
2618 "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2620 &DirEntry->NameInformation.FileName));
2625 AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2628 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2629 AFS_TRACE_LEVEL_VERBOSE,
2630 "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2632 &DirEntry->NameInformation.FileName));
2635 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2638 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2640 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2642 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2643 AFS_TRACE_LEVEL_VERBOSE,
2644 "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2646 &DirEntry->NameInformation.FileName));
2651 AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2654 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2655 AFS_TRACE_LEVEL_VERBOSE,
2656 "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2658 &DirEntry->NameInformation.FileName));
2662 // Into the shortname tree
2665 if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2668 if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2671 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2673 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2674 AFS_TRACE_LEVEL_VERBOSE,
2675 "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2677 &DirEntry->NameInformation.FileName));
2679 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2684 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2687 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2688 AFS_TRACE_LEVEL_VERBOSE,
2689 "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2691 &DirEntry->NameInformation.FileName));
2695 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2697 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2698 AFS_TRACE_LEVEL_VERBOSE,
2699 "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2701 &DirEntry->NameInformation.FileName));
2706 if( InsertInEnumList)
2710 // And insert the node into the directory list
2713 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2714 AFS_TRACE_LEVEL_VERBOSE,
2715 "AFSInsertDirectoryNode Inserting entry %p %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2717 &DirEntry->NameInformation.FileName,
2718 DirEntry->ObjectInformation->FileId.Cell,
2719 DirEntry->ObjectInformation->FileId.Volume,
2720 DirEntry->ObjectInformation->FileId.Vnode,
2721 DirEntry->ObjectInformation->FileId.Unique));
2723 if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2726 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2731 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2733 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2736 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2738 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2740 lCount = InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2742 AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2743 AFS_TRACE_LEVEL_VERBOSE,
2744 "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2745 &DirEntry->NameInformation.FileName,
2747 ParentObjectInfo->FileId.Cell,
2748 ParentObjectInfo->FileId.Volume,
2749 ParentObjectInfo->FileId.Vnode,
2750 ParentObjectInfo->FileId.Unique));
2758 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2759 IN AFSDirectoryCB **ppDirEntry)
2763 AFSDirectoryCB *pDirEntry;
2768 pDirEntry = (AFSDirectoryCB *) InterlockedCompareExchangePointer( (PVOID *)ppDirEntry,
2772 if ( pDirEntry == NULL)
2775 try_return( NOTHING);
2778 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2779 AFS_TRACE_LEVEL_VERBOSE,
2780 "AFSDeletepDirEntry Deleting dir entry in parent %p Entry %p object %p %wZ RefCount %d\n",
2783 pDirEntry->ObjectInformation,
2784 &pDirEntry->NameInformation.FileName,
2785 pDirEntry->DirOpenReferenceCount));
2787 ASSERT( pDirEntry->DirOpenReferenceCount == 0);
2789 AFSRemoveDirNodeFromParent( ParentObjectInfo,
2794 // Free up the name buffer if it was reallocated
2797 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2800 AFSExFreePoolWithTag( pDirEntry->NameInformation.FileName.Buffer, 0);
2803 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2806 AFSExFreePoolWithTag( pDirEntry->NameInformation.TargetName.Buffer, 0);
2809 if ( pDirEntry->ObjectInformation != NULL)
2812 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
2813 pDirEntry->ObjectInformation->Links == 0)
2816 SetFlag( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2820 // Dereference the object for this dir entry
2823 lCount = AFSObjectInfoDecrement( pDirEntry->ObjectInformation,
2824 AFS_OBJECT_REFERENCE_DIRENTRY);
2826 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2827 AFS_TRACE_LEVEL_VERBOSE,
2828 "AFSDeletepDirEntry Decrement count on object %p Cnt %d\n",
2829 pDirEntry->ObjectInformation,
2833 ExDeleteResourceLite( &pDirEntry->NonPaged->Lock);
2835 AFSExFreePoolWithTag( pDirEntry->NonPaged, AFS_DIR_ENTRY_NP_TAG);
2838 // Free up the dir entry
2841 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
2842 AFS_TRACE_LEVEL_VERBOSE,
2843 "AFSDeletepDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
2846 AFSExFreePoolWithTag( pDirEntry, AFS_DIR_ENTRY_TAG);
2855 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2856 IN AFSDirectoryCB *DirEntry,
2857 IN BOOLEAN RemoveFromEnumList)
2860 NTSTATUS ntStatus = STATUS_SUCCESS;
2867 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2869 if ( DirEntry->ObjectInformation != NULL)
2872 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2873 AFS_TRACE_LEVEL_VERBOSE,
2874 "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %p\n",
2876 &DirEntry->NameInformation.FileName,
2877 DirEntry->ObjectInformation->FileId.Cell,
2878 DirEntry->ObjectInformation->FileId.Volume,
2879 DirEntry->ObjectInformation->FileId.Vnode,
2880 DirEntry->ObjectInformation->FileId.Unique,
2886 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2887 AFS_TRACE_LEVEL_VERBOSE,
2888 "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ from Parent %p\n",
2890 &DirEntry->NameInformation.FileName,
2894 if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2897 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2898 AFS_TRACE_LEVEL_VERBOSE,
2899 "AFSRemoveDirNodeFromParent Removing DirEntry %p name %wZ\n",
2901 &DirEntry->NameInformation.FileName));
2903 AFSRemoveNameEntry( ParentObjectInfo,
2909 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2910 AFS_TRACE_LEVEL_VERBOSE,
2911 "AFSRemoveDirNodeFromParent DE %p for %wZ NOT removing entry due to flag set\n",
2913 &DirEntry->NameInformation.FileName));
2917 if( RemoveFromEnumList &&
2918 BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST))
2922 // And remove the entry from the enumeration list
2925 if( DirEntry->ListEntry.fLink == NULL)
2928 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = (AFSDirectoryCB *)DirEntry->ListEntry.bLink;
2933 ((AFSDirectoryCB *)DirEntry->ListEntry.fLink)->ListEntry.bLink = DirEntry->ListEntry.bLink;
2936 if( DirEntry->ListEntry.bLink == NULL)
2939 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = (AFSDirectoryCB *)DirEntry->ListEntry.fLink;
2944 ((AFSDirectoryCB *)DirEntry->ListEntry.bLink)->ListEntry.fLink = DirEntry->ListEntry.fLink;
2947 ASSERT( ParentObjectInfo->Specific.Directory.DirectoryNodeCount > 0);
2949 lCount = InterlockedDecrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2951 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2953 AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2954 AFS_TRACE_LEVEL_VERBOSE,
2955 "AFSRemoveDirNodeFromParent Removing entry %wZ Dec Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2956 &DirEntry->NameInformation.FileName,
2958 ParentObjectInfo->FileId.Cell,
2959 ParentObjectInfo->FileId.Volume,
2960 ParentObjectInfo->FileId.Vnode,
2961 ParentObjectInfo->FileId.Unique));
2963 DirEntry->ListEntry.fLink = NULL;
2964 DirEntry->ListEntry.bLink = NULL;
2972 AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
2973 IN OUT PUNICODE_STRING TargetFileName)
2976 NTSTATUS ntStatus = STATUS_SUCCESS;
2977 UNICODE_STRING uniFileName;
2983 // We will process backwards from the end of the name looking
2984 // for the first \ we encounter
2987 uniFileName.Length = FileName->Length;
2988 uniFileName.MaximumLength = FileName->MaximumLength;
2990 uniFileName.Buffer = FileName->Buffer;
2995 if( uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
2999 // Subtract one more character off of the filename if it is not the root
3002 if( uniFileName.Length > sizeof( WCHAR))
3005 uniFileName.Length -= sizeof( WCHAR);
3009 // Now build up the target name
3012 TargetFileName->Length = FileName->Length - uniFileName.Length;
3015 // If we are not on the root then fixup the name
3018 if( uniFileName.Length > sizeof( WCHAR))
3021 TargetFileName->Length -= sizeof( WCHAR);
3023 TargetFileName->Buffer = &uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) + 1];
3028 TargetFileName->Buffer = &uniFileName.Buffer[ uniFileName.Length/sizeof( WCHAR)];
3032 // Fixup the passed back filename length
3035 FileName->Length = uniFileName.Length;
3037 TargetFileName->MaximumLength = TargetFileName->Length;
3042 uniFileName.Length -= sizeof( WCHAR);
3050 AFSParseName( IN PIRP Irp,
3052 OUT PUNICODE_STRING FileName,
3053 OUT PUNICODE_STRING ParsedFileName,
3054 OUT PUNICODE_STRING RootFileName,
3055 OUT ULONG *ParseFlags,
3056 OUT AFSVolumeCB **VolumeCB,
3057 OUT AFSDirectoryCB **ParentDirectoryCB,
3058 OUT AFSNameArrayHdr **NameArray)
3061 NTSTATUS ntStatus = STATUS_SUCCESS;
3062 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
3063 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3064 UNICODE_STRING uniFullName, uniComponentName, uniRemainingPath;
3066 AFSDirectoryCB *pDirEntry = NULL;
3067 USHORT usIndex = 0, usDriveIndex = 0;
3068 AFSCcb *pRelatedCcb = NULL;
3069 AFSNameArrayHdr *pNameArray = NULL, *pRelatedNameArray = NULL;
3070 USHORT usComponentIndex = 0;
3071 USHORT usComponentLength = 0;
3072 AFSVolumeCB *pVolumeCB = NULL;
3073 AFSFcb *pRelatedFcb = NULL;
3074 BOOLEAN bReleaseTreeLock = FALSE;
3075 BOOLEAN bIsAllShare = FALSE;
3082 // Indicate we are opening a root ...
3085 *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
3087 *ParentDirectoryCB = NULL;
3089 if( pIrpSp->FileObject->RelatedFileObject != NULL)
3092 pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
3094 pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
3096 pRelatedNameArray = pRelatedCcb->NameArray;
3098 uniFullName = pIrpSp->FileObject->FileName;
3100 ASSERT( pRelatedFcb != NULL);
3103 // No wild cards in the name
3106 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3107 AFS_TRACE_LEVEL_VERBOSE_2,
3108 "AFSParseName (%p) Relative open for %wZ FID %08lX-%08lX-%08lX-%08lX component %wZ\n",
3110 &pRelatedCcb->DirectoryCB->NameInformation.FileName,
3111 pRelatedFcb->ObjectInformation->FileId.Cell,
3112 pRelatedFcb->ObjectInformation->FileId.Volume,
3113 pRelatedFcb->ObjectInformation->FileId.Vnode,
3114 pRelatedFcb->ObjectInformation->FileId.Unique,
3117 if( FsRtlDoesNameContainWildCards( &uniFullName))
3120 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3121 AFS_TRACE_LEVEL_ERROR,
3122 "AFSParseName (%p) Component %wZ contains wild cards\n",
3126 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3129 pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
3131 pDirEntry = pRelatedCcb->DirectoryCB;
3133 *FileName = pIrpSp->FileObject->FileName;
3136 // Grab the root node while checking state
3139 AFSAcquireShared( pVolumeCB->VolumeLock,
3142 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3143 BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3147 // The volume has been taken off line so fail the access
3150 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3151 AFS_TRACE_LEVEL_ERROR,
3152 "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3154 pVolumeCB->ObjectInformation.FileId.Cell,
3155 pVolumeCB->ObjectInformation.FileId.Volume));
3157 AFSReleaseResource( pVolumeCB->VolumeLock);
3159 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3162 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3165 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3166 AFS_TRACE_LEVEL_VERBOSE,
3167 "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
3169 pVolumeCB->ObjectInformation.FileId.Cell,
3170 pVolumeCB->ObjectInformation.FileId.Volume));
3172 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3175 if( !NT_SUCCESS( ntStatus))
3178 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3179 AFS_TRACE_LEVEL_ERROR,
3180 "AFSParseName (%p) Failed verification of root Status %08lX\n",
3184 AFSReleaseResource( pVolumeCB->VolumeLock);
3186 try_return( ntStatus);
3190 AFSReleaseResource( pVolumeCB->VolumeLock);
3192 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
3195 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3196 AFS_TRACE_LEVEL_VERBOSE,
3197 "AFSParseName (%p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3199 &pDirEntry->NameInformation.FileName,
3200 pDirEntry->ObjectInformation->FileId.Cell,
3201 pDirEntry->ObjectInformation->FileId.Volume,
3202 pDirEntry->ObjectInformation->FileId.Vnode,
3203 pDirEntry->ObjectInformation->FileId.Unique));
3206 // Directory TreeLock should be exclusively held
3209 AFSAcquireExcl( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
3212 ntStatus = AFSVerifyEntry( AuthGroup,
3215 AFSReleaseResource( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
3217 if( !NT_SUCCESS( ntStatus))
3220 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3221 AFS_TRACE_LEVEL_VERBOSE,
3222 "AFSParseName (%p) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3224 &pDirEntry->NameInformation.FileName,
3225 pDirEntry->ObjectInformation->FileId.Cell,
3226 pDirEntry->ObjectInformation->FileId.Volume,
3227 pDirEntry->ObjectInformation->FileId.Vnode,
3228 pDirEntry->ObjectInformation->FileId.Unique,
3231 try_return( ntStatus);
3236 // Create our full path name buffer
3239 uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length +
3241 pIrpSp->FileObject->FileName.Length +
3244 uniFullName.Length = 0;
3246 uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
3247 uniFullName.MaximumLength,
3248 AFS_NAME_BUFFER_THREE_TAG);
3250 if( uniFullName.Buffer == NULL)
3253 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3254 AFS_TRACE_LEVEL_ERROR,
3255 "AFSParseName (%p) Failed to allocate full name buffer\n",
3258 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3261 RtlZeroMemory( uniFullName.Buffer,
3262 uniFullName.MaximumLength);
3264 RtlCopyMemory( uniFullName.Buffer,
3265 pRelatedCcb->FullFileName.Buffer,
3266 pRelatedCcb->FullFileName.Length);
3268 uniFullName.Length = pRelatedCcb->FullFileName.Length;
3270 usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
3272 usComponentLength = pIrpSp->FileObject->FileName.Length;
3274 if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
3275 pIrpSp->FileObject->FileName.Length > 0 &&
3276 pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
3277 pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
3280 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
3282 uniFullName.Length += sizeof( WCHAR);
3284 usComponentLength += sizeof( WCHAR);
3287 if( pIrpSp->FileObject->FileName.Length > 0)
3290 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
3291 pIrpSp->FileObject->FileName.Buffer,
3292 pIrpSp->FileObject->FileName.Length);
3294 uniFullName.Length += pIrpSp->FileObject->FileName.Length;
3297 *RootFileName = uniFullName;
3300 // We populate up to the current parent
3303 if( pRelatedNameArray == NULL)
3307 // Init and populate our name array
3310 pNameArray = AFSInitNameArray( NULL,
3313 if( pNameArray == NULL)
3316 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3317 AFS_TRACE_LEVEL_VERBOSE,
3318 "AFSParseName (%p) Failed to initialize name array\n",
3321 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3323 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3326 ntStatus = AFSPopulateNameArray( pNameArray,
3328 pRelatedCcb->DirectoryCB);
3334 // Init and populate our name array
3337 pNameArray = AFSInitNameArray( NULL,
3338 pRelatedNameArray->MaxElementCount);
3340 if( pNameArray == NULL)
3343 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3344 AFS_TRACE_LEVEL_VERBOSE,
3345 "AFSParseName (%p) Failed to initialize name array\n",
3348 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3350 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3353 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
3355 pRelatedCcb->DirectoryCB);
3358 if( !NT_SUCCESS( ntStatus))
3361 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3362 AFS_TRACE_LEVEL_VERBOSE,
3363 "AFSParseName (%p) Failed to populate name array\n",
3366 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3368 try_return( ntStatus);
3371 ParsedFileName->Length = usComponentLength;
3372 ParsedFileName->MaximumLength = uniFullName.MaximumLength;
3374 ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
3377 // Indicate to caller that RootFileName must be freed
3380 SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
3382 *NameArray = pNameArray;
3385 // Increment our volume reference count
3388 lCount = AFSVolumeIncrement( pVolumeCB,
3389 AFS_VOLUME_REFERENCE_PARSE_NAME);
3391 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3392 AFS_TRACE_LEVEL_VERBOSE,
3393 "AFSParseName Increment count on volume %p Cnt %d\n",
3397 *VolumeCB = pVolumeCB;
3399 *ParentDirectoryCB = pDirEntry;
3401 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3402 AFS_TRACE_LEVEL_VERBOSE_2,
3403 "AFSParseName (%p) Returning full name %wZ\n",
3407 try_return( ntStatus);
3411 // No wild cards in the name
3414 uniFullName = pIrpSp->FileObject->FileName;
3416 if( FsRtlDoesNameContainWildCards( &uniFullName) ||
3417 uniFullName.Length < AFSServerName.Length)
3420 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3421 AFS_TRACE_LEVEL_ERROR,
3422 "AFSParseName (%p) Name %wZ contains wild cards or too short\n",
3426 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3430 // The name is a fully qualified name. Parse out the server/share names and
3431 // point to the root qualified name
3432 // First thing is to locate the server name
3435 FsRtlDissectName( uniFullName,
3439 uniFullName = uniRemainingPath;
3442 // This component is the server name we are serving
3445 if( RtlCompareUnicodeString( &uniComponentName,
3451 // Drive letter based name?
3454 uniFullName = pIrpSp->FileObject->FileName;
3456 while( usIndex < uniFullName.Length/sizeof( WCHAR))
3459 if( uniFullName.Buffer[ usIndex] == L':')
3462 uniFullName.Buffer = &uniFullName.Buffer[ usIndex + 2];
3464 uniFullName.Length -= (usIndex + 2) * sizeof( WCHAR);
3466 usDriveIndex = usIndex - 1;
3475 // Do we have the right server name now?
3478 FsRtlDissectName( uniFullName,
3482 uniFullName = uniRemainingPath;
3485 // This component is the server name we are serving
3488 if( RtlCompareUnicodeString( &uniComponentName,
3493 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3494 AFS_TRACE_LEVEL_ERROR,
3495 "AFSParseName (%p) Name %wZ does not have server name\n",
3497 &pIrpSp->FileObject->FileName));
3499 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3503 // Validate this drive letter is actively mapped
3506 if( usDriveIndex > 0 &&
3507 !AFSIsDriveMapped( pIrpSp->FileObject->FileName.Buffer[ usDriveIndex]))
3510 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3511 AFS_TRACE_LEVEL_ERROR,
3512 "AFSParseName (%p) Name %wZ contains invalid drive mapping\n",
3514 &pIrpSp->FileObject->FileName));
3516 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3520 if( FsRtlDoesNameContainWildCards( &uniFullName))
3523 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3524 AFS_TRACE_LEVEL_ERROR,
3525 "AFSParseName (%p) Component %wZ contains wild cards\n",
3529 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3532 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3533 AFS_TRACE_LEVEL_VERBOSE_2,
3534 "AFSParseName (%p) Processing full name %wZ\n",
3538 if( uniFullName.Length > 0 &&
3539 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] == L'\\')
3542 uniFullName.Length -= sizeof( WCHAR);
3546 // Be sure we are online and ready to go
3549 AFSAcquireShared( AFSGlobalRoot->VolumeLock,
3552 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3553 BooleanFlagOn( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3557 // The volume has been taken off line so fail the access
3560 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3561 AFS_TRACE_LEVEL_ERROR,
3562 "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3564 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3565 AFSGlobalRoot->ObjectInformation.FileId.Volume));
3567 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3569 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3572 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3575 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3576 AFS_TRACE_LEVEL_VERBOSE,
3577 "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
3579 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3580 AFSGlobalRoot->ObjectInformation.FileId.Volume));
3582 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3585 if( !NT_SUCCESS( ntStatus))
3588 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3589 AFS_TRACE_LEVEL_ERROR,
3590 "AFSParseName (%p) Failed verification of root Status %08lX\n",
3594 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3596 try_return( ntStatus);
3600 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3602 if( !BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3605 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3606 AFS_TRACE_LEVEL_VERBOSE,
3607 "AFSParseName (%p) Enumerating global root of volume %08lX:%08lX\n",
3609 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3610 AFSGlobalRoot->ObjectInformation.FileId.Volume));
3612 ntStatus = AFSEnumerateGlobalRoot( AuthGroup);
3614 if( !NT_SUCCESS( ntStatus))
3617 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3618 AFS_TRACE_LEVEL_ERROR,
3619 "AFSParseName (%p) Failed enumeraiton of root Status %08lX\n",
3623 try_return( ntStatus);
3628 // Check for the \\Server access and return it as though it were \\Server\Globalroot
3631 if( uniRemainingPath.Buffer == NULL ||
3632 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3633 uniRemainingPath.Buffer[ 0] == L'\\'))
3636 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3637 AFS_TRACE_LEVEL_VERBOSE_2,
3638 "AFSParseName (%p) Returning global root access\n",
3641 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3643 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3644 AFS_TRACE_LEVEL_VERBOSE,
3645 "AFSParseName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3646 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3647 AFSGlobalRoot->DirectoryCB,
3653 FileName->Length = 0;
3654 FileName->MaximumLength = 0;
3655 FileName->Buffer = NULL;
3657 try_return( ntStatus = STATUS_SUCCESS);
3660 *RootFileName = uniFullName;
3663 // Include the starting \ in the root name
3666 if( RootFileName->Buffer[ 0] != L'\\')
3668 RootFileName->Buffer--;
3669 RootFileName->Length += sizeof( WCHAR);
3670 RootFileName->MaximumLength += sizeof( WCHAR);
3674 // Get the 'share' name
3677 FsRtlDissectName( uniFullName,
3681 if( FsRtlDoesNameContainWildCards( &uniFullName))
3684 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3685 AFS_TRACE_LEVEL_ERROR,
3686 "AFSParseName (%p) Component %wZ contains wild cards\n",
3688 &uniComponentName));
3690 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3694 // If this is the ALL access then perform some additional processing
3697 if( uniComponentName.Length == 0 ||
3698 RtlCompareUnicodeString( &uniComponentName,
3706 // If there is nothing else then get out
3709 if( uniRemainingPath.Buffer == NULL ||
3710 uniRemainingPath.Length == 0 ||
3711 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3712 uniRemainingPath.Buffer[ 0] == L'\\'))
3715 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3716 AFS_TRACE_LEVEL_VERBOSE_2,
3717 "AFSParseName (%p) Returning global root access\n",
3720 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3722 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3723 AFS_TRACE_LEVEL_VERBOSE,
3724 "AFSParseName Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
3725 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3726 AFSGlobalRoot->DirectoryCB,
3732 FileName->Length = 0;
3733 FileName->MaximumLength = 0;
3734 FileName->Buffer = NULL;
3736 try_return( ntStatus = STATUS_SUCCESS);
3740 // Process the name again to strip off the ALL portion
3743 uniFullName = uniRemainingPath;
3745 FsRtlDissectName( uniFullName,
3750 // Check for the PIOCtl name
3753 if( RtlCompareUnicodeString( &uniComponentName,
3758 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3759 AFS_TRACE_LEVEL_VERBOSE_2,
3760 "AFSParseName (%p) Returning root PIOCtl access\n",
3763 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3765 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3766 AFS_TRACE_LEVEL_VERBOSE,
3767 "AFSParseName Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
3768 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3769 AFSGlobalRoot->DirectoryCB,
3773 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3777 *FileName = AFSPIOCtlName;
3779 try_return( ntStatus = STATUS_SUCCESS);
3782 else if( (pDirEntry = AFSGetSpecialShareNameEntry( &uniComponentName,
3783 &uniRemainingPath)) != NULL)
3786 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3787 AFS_TRACE_LEVEL_VERBOSE_2,
3788 "AFSParseName (%p) Returning root share name %wZ access\n",
3790 &uniComponentName));
3793 // Add in the full share name to pass back
3796 if( uniRemainingPath.Buffer != NULL)
3800 // This routine strips off the leading slash so add it back in
3803 uniRemainingPath.Buffer--;
3804 uniRemainingPath.Length += sizeof( WCHAR);
3805 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3808 // And the cell name
3811 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3812 uniRemainingPath.Length += uniComponentName.Length;
3813 uniRemainingPath.MaximumLength += uniComponentName.Length;
3815 uniComponentName = uniRemainingPath;
3820 *FileName = uniComponentName;
3822 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3824 *ParentDirectoryCB = pDirEntry;
3826 try_return( ntStatus = STATUS_SUCCESS);
3830 // Determine the 'share' we are accessing
3833 ulCRC = AFSGenerateCRC( &uniComponentName,
3836 AFSAcquireShared( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3839 bReleaseTreeLock = TRUE;
3841 AFSLocateCaseSensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
3845 if( pDirEntry == NULL)
3848 ulCRC = AFSGenerateCRC( &uniComponentName,
3851 AFSLocateCaseInsensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
3855 if( pDirEntry == NULL)
3859 // OK, if this component is a valid short name then try
3860 // a lookup in the short name tree
3863 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3864 RtlIsNameLegalDOS8Dot3( &uniComponentName,
3869 AFSLocateShortNameDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.ShortNameTree,
3874 if( pDirEntry == NULL)
3878 // Check with the service whether it is a valid cell name
3881 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3883 bReleaseTreeLock = FALSE;
3885 ntStatus = AFSCheckCellName( AuthGroup,
3889 if( !NT_SUCCESS( ntStatus))
3893 uniRemainingPath.Length == 0 &&
3894 ntStatus == STATUS_OBJECT_PATH_NOT_FOUND)
3897 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3898 AFS_TRACE_LEVEL_VERBOSE,
3899 "AFSParseName (%p) AFSCheckCellName %wZ returned path not found; ntStatus %08X\n",
3902 STATUS_OBJECT_NAME_NOT_FOUND));
3904 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
3907 try_return( ntStatus);
3913 if( bReleaseTreeLock)
3915 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3920 // Be sure we are starting from the correct volume
3923 if( pDirEntry->ObjectInformation->VolumeCB != AFSGlobalRoot)
3927 // We dropped the global root in the CheckCellName routine which is the
3928 // only way we can be here
3931 pVolumeCB = pDirEntry->ObjectInformation->VolumeCB;
3934 // Init our name array
3937 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
3940 if( pNameArray == NULL)
3943 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3944 AFS_TRACE_LEVEL_VERBOSE,
3945 "AFSParseName (%p) Failed to initialize name array\n",
3948 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3951 ntStatus = AFSInsertNextElement( pNameArray,
3952 pVolumeCB->DirectoryCB);
3957 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3958 AFS_TRACE_LEVEL_VERBOSE,
3959 "AFSParseName (%p) Failed to insert name array element\n",
3962 try_return( ntStatus);
3966 // In this case don't add back in the 'share' name since that is where we are
3967 // starting. Just put the leading slash back in
3970 if( uniRemainingPath.Buffer != NULL)
3973 uniRemainingPath.Buffer--;
3974 uniRemainingPath.Length += sizeof( WCHAR);
3975 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3977 if( uniRemainingPath.Length > sizeof( WCHAR))
3980 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3984 // Pass back the parent being the root of the volume
3987 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3993 // Pass back a root slash
3996 uniRemainingPath = uniComponentName;
3998 uniRemainingPath.Buffer--;
3999 uniRemainingPath.Length = sizeof( WCHAR);
4000 uniRemainingPath.MaximumLength = sizeof( WCHAR);
4003 // This is a root open so pass back no parent
4010 pVolumeCB = AFSGlobalRoot;
4013 // Init our name array
4016 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
4018 if( pNameArray == NULL)
4021 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4022 AFS_TRACE_LEVEL_VERBOSE,
4023 "AFSParseName (%p) Failed to initialize name array\n",
4026 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4030 // Add back in the 'share' portion of the name since we will parse it out on return
4033 if( uniRemainingPath.Buffer != NULL)
4037 // This routine strips off the leading slash so add it back in
4040 uniRemainingPath.Buffer--;
4041 uniRemainingPath.Length += sizeof( WCHAR);
4042 uniRemainingPath.MaximumLength += sizeof( WCHAR);
4044 if( uniRemainingPath.Length > sizeof( WCHAR))
4047 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
4051 // And the cell name
4054 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
4055 uniRemainingPath.Length += uniComponentName.Length;
4056 uniRemainingPath.MaximumLength += uniComponentName.Length;
4061 uniRemainingPath = uniComponentName;
4065 // And the leading slash again ...
4068 uniRemainingPath.Buffer--;
4069 uniRemainingPath.Length += sizeof( WCHAR);
4070 uniRemainingPath.MaximumLength += sizeof( WCHAR);
4073 // Pass back the parent being the volume root
4076 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
4080 // Return the remaining portion as the file name
4083 *FileName = uniRemainingPath;
4085 *ParsedFileName = uniRemainingPath;
4087 *NameArray = pNameArray;
4089 *VolumeCB = pVolumeCB;
4092 // Increment our reference on the volume
4095 lCount = AFSVolumeIncrement( pVolumeCB,
4096 AFS_VOLUME_REFERENCE_PARSE_NAME);
4098 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4099 AFS_TRACE_LEVEL_VERBOSE,
4100 "AFSParseName Increment2 count on global volume %p Cnt %d\n",
4106 if( NT_SUCCESS( ntStatus))
4109 if( *ParentDirectoryCB != NULL)
4112 lCount = InterlockedIncrement( &(*ParentDirectoryCB)->DirOpenReferenceCount);
4114 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4115 AFS_TRACE_LEVEL_VERBOSE,
4116 "AFSParseName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4117 &(*ParentDirectoryCB)->NameInformation.FileName,
4118 (*ParentDirectoryCB),
4124 if( *VolumeCB != NULL)
4126 ASSERT( (*VolumeCB)->VolumeReferenceCount > 0);
4129 if( ntStatus != STATUS_SUCCESS)
4132 if( pNameArray != NULL)
4135 AFSFreeNameArray( pNameArray);
4144 AFSCheckCellName( IN GUID *AuthGroup,
4145 IN UNICODE_STRING *CellName,
4146 OUT AFSDirectoryCB **ShareDirEntry)
4149 NTSTATUS ntStatus = STATUS_SUCCESS;
4150 UNICODE_STRING uniName;
4151 AFSDirEnumEntry *pDirEnumEntry = NULL;
4152 AFSDirHdr *pDirHdr = &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr;
4153 AFSDirectoryCB *pDirNode = NULL;
4154 UNICODE_STRING uniDirName, uniTargetName;
4155 AFSVolumeCB *pVolumeCB = NULL;
4162 // Look for some default names we will not handle
4165 RtlInitUnicodeString( &uniName,
4168 if( RtlCompareUnicodeString( &uniName,
4173 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4176 RtlInitUnicodeString( &uniName,
4179 if( RtlCompareUnicodeString( &uniName,
4184 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4187 RtlInitUnicodeString( &uniName,
4190 if( RtlCompareUnicodeString( &uniName,
4195 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4198 RtlInitUnicodeString( &uniName,
4201 if( RtlCompareUnicodeString( &uniName,
4206 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4210 // OK, ask the CM about this component name
4213 ntStatus = AFSEvaluateTargetByName( AuthGroup,
4214 &AFSGlobalRoot->ObjectInformation,
4219 if( !NT_SUCCESS( ntStatus))
4222 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4223 AFS_TRACE_LEVEL_WARNING,
4224 "AFSCheckCellName entry %wZ does not exist parent FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4226 AFSGlobalRoot->ObjectInformation.FileId.Cell,
4227 AFSGlobalRoot->ObjectInformation.FileId.Volume,
4228 AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4229 AFSGlobalRoot->ObjectInformation.FileId.Unique,
4232 try_return( ntStatus);
4236 // OK, we have a dir enum entry back so add it to the root node
4239 uniDirName = *CellName;
4241 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
4242 uniTargetName.MaximumLength = uniTargetName.Length;
4243 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
4246 // Is this entry a root volume entry?
4249 if( pDirEnumEntry->FileId.Cell != AFSGlobalRoot->ObjectInformation.FileId.Cell ||
4250 pDirEnumEntry->FileId.Volume != AFSGlobalRoot->ObjectInformation.FileId.Volume)
4254 // Build the root volume entry
4257 ntStatus = AFSBuildRootVolume( AuthGroup,
4258 &pDirEnumEntry->FileId,
4262 // On success returns with a volume reference count held
4265 if( !NT_SUCCESS( ntStatus))
4267 try_return( ntStatus);
4270 *ShareDirEntry = pVolumeCB->DirectoryCB;
4272 lCount = InterlockedIncrement( &pVolumeCB->DirectoryCB->DirOpenReferenceCount);
4274 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4275 AFS_TRACE_LEVEL_VERBOSE,
4276 "AFSCheckCellName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4277 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4278 pVolumeCB->DirectoryCB,
4282 lCount = AFSVolumeDecrement( pVolumeCB,
4283 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4285 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4286 AFS_TRACE_LEVEL_VERBOSE,
4287 "AFSCheckCellName Decrement count on volume %p Cnt %d\n",
4294 lCount = InterlockedIncrement( &pDirHdr->ContentIndex);
4296 pDirNode = AFSInitDirEntry( &AFSGlobalRoot->ObjectInformation,
4302 if( pDirNode == NULL)
4305 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4309 // Init the short name if we have one
4312 if( pDirEnumEntry->ShortNameLength > 0)
4315 pDirNode->NameInformation.ShortNameLength = pDirEnumEntry->ShortNameLength;
4317 RtlCopyMemory( pDirNode->NameInformation.ShortName,
4318 pDirEnumEntry->ShortName,
4319 pDirNode->NameInformation.ShortNameLength);
4322 AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4326 // Insert the node into the name tree
4329 ASSERT( ExIsResourceAcquiredExclusiveLite( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock));
4331 if( pDirHdr->CaseSensitiveTreeHead == NULL)
4334 pDirHdr->CaseSensitiveTreeHead = pDirNode;
4339 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( pDirHdr->CaseSensitiveTreeHead,
4343 AFSDeleteDirEntry( &AFSGlobalRoot->ObjectInformation,
4346 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4348 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4352 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
4354 if( pDirHdr->CaseInsensitiveTreeHead == NULL)
4357 pDirHdr->CaseInsensitiveTreeHead = pDirNode;
4359 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
4364 AFSInsertCaseInsensitiveDirEntry( pDirHdr->CaseInsensitiveTreeHead,
4368 if( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead == NULL)
4371 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead = pDirNode;
4376 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
4378 pDirNode->ListEntry.bLink = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail;
4381 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail = pDirNode;
4383 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
4385 lCount = InterlockedIncrement( &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeCount);
4387 AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
4388 AFS_TRACE_LEVEL_VERBOSE,
4389 "AFSCheckCellName Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
4390 &pDirNode->NameInformation.FileName,
4392 AFSGlobalRoot->ObjectInformation.FileId.Cell,
4393 AFSGlobalRoot->ObjectInformation.FileId.Volume,
4394 AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4395 AFSGlobalRoot->ObjectInformation.FileId.Unique));
4397 lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
4399 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4400 AFS_TRACE_LEVEL_VERBOSE,
4401 "AFSCheckCellName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
4402 &pDirNode->NameInformation.FileName,
4407 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4410 // Pass back the dir node
4413 *ShareDirEntry = pDirNode;
4418 if( pDirEnumEntry != NULL)
4421 AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_31_TAG);
4429 AFSBuildMountPointTarget( IN GUID *AuthGroup,
4430 IN AFSDirectoryCB *DirectoryCB,
4431 OUT AFSVolumeCB **TargetVolumeCB)
4434 NTSTATUS ntStatus = STATUS_SUCCESS;
4435 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4436 AFSDirEnumEntry *pDirEntry = NULL;
4437 ULONGLONG ullIndex = 0;
4438 AFSVolumeCB *pVolumeCB = NULL;
4439 AFSFileID stTargetFileID;
4441 BOOLEAN bReleaseVolumeLock = FALSE;
4447 // Loop on each entry, building the chain until we encounter the final target
4450 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4451 AFS_TRACE_LEVEL_VERBOSE_2,
4452 "AFSBuildMountPointTarget Building target directory for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4453 &DirectoryCB->NameInformation.FileName,
4454 DirectoryCB->ObjectInformation->FileId.Cell,
4455 DirectoryCB->ObjectInformation->FileId.Volume,
4456 DirectoryCB->ObjectInformation->FileId.Vnode,
4457 DirectoryCB->ObjectInformation->FileId.Unique));
4460 // Do we need to evaluate the node?
4463 //if( DirectoryCB->ObjectInformation->TargetFileId.Vnode == 0 &&
4464 // DirectoryCB->ObjectInformation->TargetFileId.Unique == 0)
4468 // Go evaluate the current target to get the target fid
4471 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4472 AFS_TRACE_LEVEL_VERBOSE_2,
4473 "AFSBuildMountPointTarget Evaluating target %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4474 &DirectoryCB->NameInformation.FileName,
4475 DirectoryCB->ObjectInformation->FileId.Cell,
4476 DirectoryCB->ObjectInformation->FileId.Volume,
4477 DirectoryCB->ObjectInformation->FileId.Vnode,
4478 DirectoryCB->ObjectInformation->FileId.Unique));
4480 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
4485 if( !NT_SUCCESS( ntStatus))
4488 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4489 AFS_TRACE_LEVEL_ERROR,
4490 "AFSBuildMountPointTarget Failed to evaluate target %wZ Status %08lX\n",
4491 &DirectoryCB->NameInformation.FileName,
4494 try_return( ntStatus);
4497 if( pDirEntry->TargetFileId.Vnode == 0 &&
4498 pDirEntry->TargetFileId.Unique == 0)
4501 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4502 AFS_TRACE_LEVEL_ERROR,
4503 "AFSBuildMountPointTarget Target %wZ FID %08lX-%08lX-%08lX-%08lX service returned zero FID\n",
4504 &DirectoryCB->NameInformation.FileName,
4505 DirectoryCB->ObjectInformation->FileId.Cell,
4506 DirectoryCB->ObjectInformation->FileId.Volume,
4507 DirectoryCB->ObjectInformation->FileId.Vnode,
4508 DirectoryCB->ObjectInformation->FileId.Unique));
4510 try_return( ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED);
4513 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
4516 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
4517 &DirectoryCB->Flags,
4518 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4519 (USHORT)pDirEntry->TargetNameLength);
4521 if( !NT_SUCCESS( ntStatus))
4524 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4526 try_return( ntStatus);
4529 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4531 DirectoryCB->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
4534 stTargetFileID = DirectoryCB->ObjectInformation->TargetFileId;
4537 // Try to locate this FID. First the volume then the
4541 ullIndex = AFSCreateHighIndex( &stTargetFileID);
4543 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4544 AFS_TRACE_LEVEL_VERBOSE,
4545 "AFSBuildMountPointTarget Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4546 &pDevExt->Specific.RDR.VolumeTreeLock,
4547 PsGetCurrentThread()));
4549 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4552 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4553 AFS_TRACE_LEVEL_VERBOSE_2,
4554 "AFSBuildMountPointTarget Locating volume for target %I64X\n",
4557 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4559 (AFSBTreeEntry **)&pVolumeCB);
4562 // We can be processing a request for a target that is on a volume
4563 // we have never seen before.
4566 if( pVolumeCB == NULL)
4570 // Locking is held correctly in init routine
4573 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4576 // Go init the root of the volume
4579 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4580 AFS_TRACE_LEVEL_VERBOSE_2,
4581 "AFSBuildMountPointTarget Initializing root for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4582 &DirectoryCB->NameInformation.FileName,
4583 DirectoryCB->ObjectInformation->FileId.Cell,
4584 DirectoryCB->ObjectInformation->FileId.Volume,
4585 DirectoryCB->ObjectInformation->FileId.Vnode,
4586 DirectoryCB->ObjectInformation->FileId.Unique));
4588 ntStatus = AFSInitVolume( AuthGroup,
4590 AFS_VOLUME_REFERENCE_MOUNTPT,
4593 if( !NT_SUCCESS( ntStatus))
4596 try_return( ntStatus);
4600 // pVolumeCB->VolumeLock held exclusive and
4601 // pVolumeCB->VolumeReferenceCount has been incremented
4602 // pVolumeCB->RootFcb == NULL
4605 bReleaseVolumeLock = TRUE;
4611 // AFSInitVolume returns with a VolumeReferenceCount
4612 // obtain one to match
4615 lCount = AFSVolumeIncrement( pVolumeCB,
4616 AFS_VOLUME_REFERENCE_MOUNTPT);
4618 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4619 AFS_TRACE_LEVEL_VERBOSE,
4620 "AFSBuildMountPointTarget Increment count on volume %p Cnt %d\n",
4624 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4627 if( pVolumeCB->RootFcb == NULL)
4630 if ( bReleaseVolumeLock == FALSE)
4633 AFSAcquireExcl( pVolumeCB->VolumeLock,
4636 bReleaseVolumeLock = TRUE;
4640 // Initialize the root fcb for this volume
4643 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4646 if( !NT_SUCCESS( ntStatus))
4649 lCount = AFSVolumeDecrement( pVolumeCB,
4650 AFS_VOLUME_REFERENCE_MOUNTPT);
4652 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4653 AFS_TRACE_LEVEL_VERBOSE,
4654 "AFSBuildMountPoint Decrement count on volume %p Cnt %d\n",
4658 AFSReleaseResource( pVolumeCB->VolumeLock);
4660 try_return( ntStatus);
4664 // Drop the lock acquired above
4667 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4670 if ( bReleaseVolumeLock == TRUE)
4673 AFSReleaseResource( pVolumeCB->VolumeLock);
4676 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4677 AFS_TRACE_LEVEL_VERBOSE_2,
4678 "AFSBuildMountPointTarget Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4679 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4680 pVolumeCB->ObjectInformation.FileId.Cell,
4681 pVolumeCB->ObjectInformation.FileId.Volume,
4682 pVolumeCB->ObjectInformation.FileId.Vnode,
4683 pVolumeCB->ObjectInformation.FileId.Unique));
4685 *TargetVolumeCB = pVolumeCB;
4692 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
4700 AFSBuildRootVolume( IN GUID *AuthGroup,
4701 IN AFSFileID *FileId,
4702 OUT AFSVolumeCB **TargetVolumeCB)
4705 NTSTATUS ntStatus = STATUS_SUCCESS;
4706 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4707 ULONGLONG ullIndex = 0;
4708 AFSVolumeCB *pVolumeCB = NULL;
4710 BOOLEAN bReleaseVolumeLock = FALSE;
4715 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4716 AFS_TRACE_LEVEL_VERBOSE_2,
4717 "AFSBuildRootVolume Building target volume for FID %08lX-%08lX-%08lX-%08lX\n",
4723 ullIndex = AFSCreateHighIndex( FileId);
4725 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4726 AFS_TRACE_LEVEL_VERBOSE,
4727 "AFSBuildRootVolume Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4728 &pDevExt->Specific.RDR.VolumeTreeLock,
4729 PsGetCurrentThread()));
4731 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4734 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4735 AFS_TRACE_LEVEL_VERBOSE_2,
4736 "AFSBuildRootVolume Locating volume for target %I64X\n",
4739 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4741 (AFSBTreeEntry **)&pVolumeCB);
4744 // We can be processing a request for a target that is on a volume
4745 // we have never seen before.
4748 if( pVolumeCB == NULL)
4752 // Locking is held correctly in init routine
4755 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4758 // Go init the root of the volume
4761 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4762 AFS_TRACE_LEVEL_VERBOSE_2,
4763 "AFSBuildRootVolume Initializing root for FID %08lX-%08lX-%08lX-%08lX\n",
4769 ntStatus = AFSInitVolume( AuthGroup,
4771 AFS_VOLUME_REFERENCE_BUILD_ROOT,
4774 if( !NT_SUCCESS( ntStatus))
4777 try_return( ntStatus);
4781 // pVolumeCB->VolumeLock is held exclusive
4782 // pVolumeCB->VolumeReferenceCount has been incremented
4783 // pVolumeCB->RootFcb == NULL
4786 bReleaseVolumeLock = TRUE;
4792 // AFSInitVolume returns with a VolumeReferenceCount
4793 // obtain one to match
4796 lCount = AFSVolumeIncrement( pVolumeCB,
4797 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4799 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4800 AFS_TRACE_LEVEL_VERBOSE,
4801 "AFSBuildRootVolume Increment count on volume %p Cnt %d\n",
4805 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4809 if( pVolumeCB->RootFcb == NULL)
4812 if ( bReleaseVolumeLock == FALSE)
4815 AFSAcquireExcl( pVolumeCB->VolumeLock,
4818 bReleaseVolumeLock = TRUE;
4822 // Initialize the root fcb for this volume
4825 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4828 if( !NT_SUCCESS( ntStatus))
4831 lCount = AFSVolumeDecrement( pVolumeCB,
4832 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4834 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4835 AFS_TRACE_LEVEL_VERBOSE,
4836 "AFSBuildRootVolume Decrement count on volume %p Cnt %d\n",
4840 AFSReleaseResource( pVolumeCB->VolumeLock);
4842 try_return( ntStatus);
4846 // Drop the lock acquired above
4849 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4852 if ( bReleaseVolumeLock == TRUE)
4855 AFSReleaseResource( pVolumeCB->VolumeLock);
4858 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4859 AFS_TRACE_LEVEL_VERBOSE_2,
4860 "AFSBuildRootVolume Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4861 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4862 pVolumeCB->ObjectInformation.FileId.Cell,
4863 pVolumeCB->ObjectInformation.FileId.Volume,
4864 pVolumeCB->ObjectInformation.FileId.Vnode,
4865 pVolumeCB->ObjectInformation.FileId.Unique));
4867 *TargetVolumeCB = pVolumeCB;
4878 AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
4879 IN PFILE_OBJECT FileObject,
4880 IN UNICODE_STRING *RemainingPath,
4884 NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
4885 UNICODE_STRING uniReparseName;
4886 UNICODE_STRING uniMUPDeviceName;
4887 UNICODE_STRING uniIOMgrDeviceName;
4888 AFSDirEnumEntry *pDirEntry = NULL;
4894 // Build up the name to reparse
4897 RtlInitUnicodeString( &uniMUPDeviceName,
4900 RtlInitUnicodeString( &uniIOMgrDeviceName,
4903 uniReparseName.Length = 0;
4904 uniReparseName.Buffer = NULL;
4907 // Be sure we have a target name
4910 if( DirEntry->NameInformation.TargetName.Length == 0)
4913 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
4918 if( !NT_SUCCESS( ntStatus) ||
4919 pDirEntry->TargetNameLength == 0)
4922 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4923 AFS_TRACE_LEVEL_ERROR,
4924 "AFSProcessDFSLink EvaluateTargetByID failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4925 &DirEntry->NameInformation.FileName,
4926 DirEntry->ObjectInformation->FileId.Cell,
4927 DirEntry->ObjectInformation->FileId.Volume,
4928 DirEntry->ObjectInformation->FileId.Vnode,
4929 DirEntry->ObjectInformation->FileId.Unique,
4932 if( NT_SUCCESS( ntStatus))
4935 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
4938 try_return( ntStatus);
4942 // Update the target name
4945 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
4948 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
4950 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4951 (USHORT)pDirEntry->TargetNameLength);
4953 if( !NT_SUCCESS( ntStatus))
4956 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4957 AFS_TRACE_LEVEL_ERROR,
4958 "AFSProcessDFSLink UpdateTargetName failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4959 &DirEntry->NameInformation.FileName,
4960 DirEntry->ObjectInformation->FileId.Cell,
4961 DirEntry->ObjectInformation->FileId.Volume,
4962 DirEntry->ObjectInformation->FileId.Vnode,
4963 DirEntry->ObjectInformation->FileId.Unique,
4966 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4968 try_return( ntStatus);
4971 AFSConvertToShared( &DirEntry->NonPaged->Lock);
4975 AFSAcquireShared( &DirEntry->NonPaged->Lock,
4979 uniReparseName.MaximumLength = uniMUPDeviceName.Length +
4981 DirEntry->NameInformation.TargetName.Length +
4984 if( RemainingPath != NULL &&
4985 RemainingPath->Length > 0)
4988 uniReparseName.MaximumLength += RemainingPath->Length;
4992 // Allocate the reparse buffer
4995 uniReparseName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4996 uniReparseName.MaximumLength,
4997 AFS_REPARSE_NAME_TAG);
4999 if( uniReparseName.Buffer == NULL)
5002 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5003 AFS_TRACE_LEVEL_ERROR,
5004 "AFSProcessDFSLink uniReparseName.Buffer == NULL Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
5005 &DirEntry->NameInformation.FileName,
5006 DirEntry->ObjectInformation->FileId.Cell,
5007 DirEntry->ObjectInformation->FileId.Volume,
5008 DirEntry->ObjectInformation->FileId.Vnode,
5009 DirEntry->ObjectInformation->FileId.Unique,
5010 STATUS_INSUFFICIENT_RESOURCES));
5012 AFSReleaseResource( &DirEntry->NonPaged->Lock);
5014 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5018 // Start building the name
5021 if ( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\' &&
5022 DirEntry->NameInformation.TargetName.Buffer[ 1] == L':')
5025 RtlCopyMemory( uniReparseName.Buffer,
5026 uniIOMgrDeviceName.Buffer,
5027 uniIOMgrDeviceName.Length);
5029 uniReparseName.Length = uniIOMgrDeviceName.Length;
5034 RtlCopyMemory( uniReparseName.Buffer,
5035 uniMUPDeviceName.Buffer,
5036 uniMUPDeviceName.Length);
5038 uniReparseName.Length = uniMUPDeviceName.Length;
5040 if( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\')
5043 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
5045 uniReparseName.Length += sizeof( WCHAR);
5049 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
5050 DirEntry->NameInformation.TargetName.Buffer,
5051 DirEntry->NameInformation.TargetName.Length);
5053 uniReparseName.Length += DirEntry->NameInformation.TargetName.Length;
5055 AFSReleaseResource( &DirEntry->NonPaged->Lock);
5057 if( RemainingPath != NULL &&
5058 RemainingPath->Length > 0)
5061 if( uniReparseName.Buffer[ (uniReparseName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
5062 RemainingPath->Buffer[ 0] != L'\\')
5065 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
5067 uniReparseName.Length += sizeof( WCHAR);
5070 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
5071 RemainingPath->Buffer,
5072 RemainingPath->Length);
5074 uniReparseName.Length += RemainingPath->Length;
5078 // Update the name in the file object
5081 if( FileObject->FileName.Buffer != NULL)
5084 AFSExFreePoolWithTag( FileObject->FileName.Buffer, 0);
5087 FileObject->FileName = uniReparseName;
5089 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5090 AFS_TRACE_LEVEL_VERBOSE,
5091 "AFSProcessDFSLink Reparsing access to Fcb %wZ FID %08lX-%08lX-%08lX-%08lX to %wZ\n",
5092 &DirEntry->NameInformation.FileName,
5093 DirEntry->ObjectInformation->FileId.Cell,
5094 DirEntry->ObjectInformation->FileId.Volume,
5095 DirEntry->ObjectInformation->FileId.Vnode,
5096 DirEntry->ObjectInformation->FileId.Unique,
5100 // Return status reparse ...
5103 ntStatus = STATUS_REPARSE;
5110 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);