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 be released. On successful exit, *VolumeCB
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.
53 AFSLocateNameEntry( IN GUID *AuthGroup,
54 IN PFILE_OBJECT FileObject,
55 IN UNICODE_STRING *RootPathName,
56 IN UNICODE_STRING *ParsedPathName,
57 IN AFSNameArrayHdr *NameArray,
59 IN OUT AFSVolumeCB **VolumeCB,
60 IN OUT LONG *pVolumeReferenceReason,
61 IN OUT AFSDirectoryCB **ParentDirectoryCB,
62 OUT AFSDirectoryCB **DirectoryCB,
63 OUT PUNICODE_STRING ComponentName)
66 NTSTATUS ntStatus = STATUS_SUCCESS;
67 UNICODE_STRING uniPathName, uniComponentName, uniRemainingPath, uniSearchName, uniFullPathName;
69 AFSDirectoryCB *pDirEntry = NULL, *pParentDirEntry = NULL;
70 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
71 UNICODE_STRING uniSysName;
72 ULONG ulSubstituteIndex = 0;
73 BOOLEAN bSubstituteName = FALSE;
74 AFSNameArrayHdr *pNameArray = NameArray;
75 BOOLEAN bAllocatedSymLinkBuffer = FALSE;
76 UNICODE_STRING uniRelativeName, uniNoOpName;
77 AFSObjectInfoCB *pCurrentObject = NULL;
78 AFSObjectInfoCB *pParentObjectInfo = NULL;
79 AFSVolumeCB *pCurrentVolume = *VolumeCB;
80 AFSVolumeCB *pTargetVolume = NULL;
81 BOOLEAN bReleaseCurrentVolume = TRUE;
82 LONG VolumeReferenceReason = *pVolumeReferenceReason;
83 BOOLEAN bSubstitutedName = FALSE;
89 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
90 AFS_TRACE_LEVEL_VERBOSE_2,
91 "AFSLocateNameEntry (FO: %p) Processing full name %wZ\n",
95 RtlInitUnicodeString( &uniSysName,
98 RtlInitUnicodeString( &uniRelativeName,
101 RtlInitUnicodeString( &uniNoOpName,
105 // Cleanup some parameters
108 if( ComponentName != NULL)
111 ComponentName->Length = 0;
112 ComponentName->MaximumLength = 0;
113 ComponentName->Buffer = NULL;
117 // We will parse through the filename, locating the directory nodes until we encounter a cache miss
118 // Starting at the root node
121 pParentDirEntry = NULL;
123 pDirEntry = *ParentDirectoryCB;
125 uniPathName = *ParsedPathName;
127 uniFullPathName = *RootPathName;
129 uniComponentName.Length = uniComponentName.MaximumLength = 0;
130 uniComponentName.Buffer = NULL;
132 uniRemainingPath.Length = uniRemainingPath.MaximumLength = 0;
133 uniRemainingPath.Buffer = NULL;
135 uniSearchName.Length = uniSearchName.MaximumLength = 0;
136 uniSearchName.Buffer = NULL;
141 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
143 ASSERT( pDirEntry->DirOpenReferenceCount > 0);
146 // Check our total link count for this name array
149 if( pNameArray->LinkCount >= (LONG)pDevExt->Specific.RDR.MaxLinkCount)
152 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
155 pCurrentObject = pDirEntry->ObjectInformation;
157 KeQueryTickCount( &pCurrentObject->LastAccessCount);
160 // Check that the directory entry is not deleted or pending delete
163 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
166 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
167 AFS_TRACE_LEVEL_ERROR,
168 "AFSLocateNameEntry (FO: %p) Deleted parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
170 &pDirEntry->NameInformation.FileName,
171 pCurrentObject->FileId.Cell,
172 pCurrentObject->FileId.Volume,
173 pCurrentObject->FileId.Vnode,
174 pCurrentObject->FileId.Unique,
175 STATUS_FILE_DELETED);
177 try_return( ntStatus = STATUS_FILE_DELETED);
180 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
183 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
184 AFS_TRACE_LEVEL_ERROR,
185 "AFSLocateNameEntry (FO: %p) Delete pending on %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
187 &pDirEntry->NameInformation.FileName,
188 pCurrentObject->FileId.Cell,
189 pCurrentObject->FileId.Volume,
190 pCurrentObject->FileId.Vnode,
191 pCurrentObject->FileId.Unique,
192 STATUS_DELETE_PENDING);
194 try_return( ntStatus = STATUS_DELETE_PENDING);
198 // Check if the directory requires verification
201 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
202 ( pCurrentObject->FileType != AFS_FILE_TYPE_DIRECTORY ||
203 !AFSIsEnumerationInProcess( pCurrentObject)))
206 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
207 AFS_TRACE_LEVEL_VERBOSE,
208 "AFSLocateNameEntry (FO: %p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
210 &pDirEntry->NameInformation.FileName,
211 pCurrentObject->FileId.Cell,
212 pCurrentObject->FileId.Volume,
213 pCurrentObject->FileId.Vnode,
214 pCurrentObject->FileId.Unique);
217 // Directory TreeLock should be exclusively held
220 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
223 ntStatus = AFSVerifyEntry( AuthGroup,
226 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
228 if( !NT_SUCCESS( ntStatus))
231 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
232 AFS_TRACE_LEVEL_ERROR,
233 "AFSLocateNameEntry (FO: %p) Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
235 &pDirEntry->NameInformation.FileName,
236 pCurrentObject->FileId.Cell,
237 pCurrentObject->FileId.Volume,
238 pCurrentObject->FileId.Vnode,
239 pCurrentObject->FileId.Unique,
242 try_return( ntStatus);
247 // Ensure the parent node has been evaluated, if not then go do it now
250 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) ||
251 pCurrentObject->FileType == AFS_FILE_TYPE_UNKNOWN)
254 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
255 AFS_TRACE_LEVEL_VERBOSE,
256 "AFSLocateNameEntry (FO: %p) Evaluating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
258 &pDirEntry->NameInformation.FileName,
259 pCurrentObject->FileId.Cell,
260 pCurrentObject->FileId.Volume,
261 pCurrentObject->FileId.Vnode,
262 pCurrentObject->FileId.Unique);
264 ntStatus = AFSEvaluateNode( AuthGroup,
267 if( !NT_SUCCESS( ntStatus))
270 if ( ntStatus == STATUS_NOT_A_DIRECTORY)
273 if ( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
276 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
277 AFS_TRACE_LEVEL_ERROR,
278 "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT NULL Status %08lX\n",
280 &pDirEntry->NameInformation.FileName,
281 pCurrentObject->FileId.Cell,
282 pCurrentObject->FileId.Volume,
283 pCurrentObject->FileId.Vnode,
284 pCurrentObject->FileId.Unique,
290 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
291 AFS_TRACE_LEVEL_ERROR,
292 "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT %08lX-%08lX-%08lX-%08lX Status %08lX\n",
294 &pDirEntry->NameInformation.FileName,
295 pCurrentObject->FileId.Cell,
296 pCurrentObject->FileId.Volume,
297 pCurrentObject->FileId.Vnode,
298 pCurrentObject->FileId.Unique,
299 pCurrentObject->ParentFileId.Cell,
300 pCurrentObject->ParentFileId.Volume,
301 pCurrentObject->ParentFileId.Vnode,
302 pCurrentObject->ParentFileId.Unique,
308 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
309 AFS_TRACE_LEVEL_ERROR,
310 "AFSLocateNameEntry (FO: %p) Failed to evaluate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
312 &pDirEntry->NameInformation.FileName,
313 pCurrentObject->FileId.Cell,
314 pCurrentObject->FileId.Volume,
315 pCurrentObject->FileId.Vnode,
316 pCurrentObject->FileId.Unique,
320 try_return( ntStatus);
323 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
327 // If this is a mount point or symlink then go get the real directory node
330 switch( pCurrentObject->FileType)
333 case AFS_FILE_TYPE_SYMLINK:
336 UNICODE_STRING uniTempName;
337 WCHAR *pTmpBuffer = NULL;
341 // Check if the flag is set to NOT evaluate a symlink
342 // and we are done with the parsing
345 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL) &&
346 uniRemainingPath.Length == 0)
350 // Pass back the directory entries
353 *ParentDirectoryCB = pParentDirEntry;
355 *DirectoryCB = pDirEntry;
357 *VolumeCB = pCurrentVolume;
359 *RootPathName = uniFullPathName;
361 try_return( ntStatus);
364 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
367 AFSAcquireExcl( &pDirEntry->NonPaged->Lock,
370 if( pDirEntry->NameInformation.TargetName.Length == 0)
374 // We'll reset the DV to ensure we validate the metadata content
377 pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
379 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
381 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
382 AFS_TRACE_LEVEL_VERBOSE,
383 "AFSLocateNameEntry (FO: %p) Verifying symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
385 &pDirEntry->NameInformation.FileName,
386 pCurrentObject->FileId.Cell,
387 pCurrentObject->FileId.Volume,
388 pCurrentObject->FileId.Vnode,
389 pCurrentObject->FileId.Unique);
392 // Directory TreeLock should be exclusively held
395 ntStatus = AFSVerifyEntry( AuthGroup,
398 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
400 if( !NT_SUCCESS( ntStatus))
403 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
404 AFS_TRACE_LEVEL_ERROR,
405 "AFSLocateNameEntry (FO: %p) Failed to verify symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
407 &pDirEntry->NameInformation.FileName,
408 pCurrentObject->FileId.Cell,
409 pCurrentObject->FileId.Volume,
410 pCurrentObject->FileId.Vnode,
411 pCurrentObject->FileId.Unique,
414 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
416 try_return( ntStatus);
420 // If the type changed then reprocess this entry
423 if( pCurrentObject->FileType != AFS_FILE_TYPE_SYMLINK)
426 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
434 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
438 // If we were given a zero length target name then deny access to the entry
441 if( pDirEntry->NameInformation.TargetName.Length == 0)
444 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
446 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
447 AFS_TRACE_LEVEL_ERROR,
448 "AFSLocateNameEntry (FO: %p) Failed to retrieve target name for symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
450 &pDirEntry->NameInformation.FileName,
451 pCurrentObject->FileId.Cell,
452 pCurrentObject->FileId.Volume,
453 pCurrentObject->FileId.Vnode,
454 pCurrentObject->FileId.Unique,
457 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
459 try_return( ntStatus);
462 if( AFSIsRelativeName( &pDirEntry->NameInformation.TargetName))
465 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
466 AFS_TRACE_LEVEL_VERBOSE,
467 "AFSLocateNameEntry (FO: %p) Processing relative symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
469 &pDirEntry->NameInformation.TargetName,
470 &pDirEntry->NameInformation.FileName,
471 pCurrentObject->FileId.Cell,
472 pCurrentObject->FileId.Volume,
473 pCurrentObject->FileId.Vnode,
474 pCurrentObject->FileId.Unique);
477 // We'll substitute this name into the current process name
478 // starting at where we sit in the path
481 uniTempName.Length = 0;
482 uniTempName.MaximumLength = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer) +
483 pDirEntry->NameInformation.TargetName.Length +
485 uniRemainingPath.Length;
487 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
488 uniTempName.MaximumLength,
489 AFS_NAME_BUFFER_ONE_TAG);
491 if( uniTempName.Buffer == NULL)
494 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
496 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
500 // We have so first copy in the portion up to the component
504 RtlCopyMemory( uniTempName.Buffer,
505 uniFullPathName.Buffer,
506 (ULONG)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer));
508 uniTempName.Length = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer);
510 if( bAllocatedSymLinkBuffer ||
514 pTmpBuffer = uniFullPathName.Buffer;
517 bAllocatedSymLinkBuffer = TRUE;
520 // Have we parsed this name yet? Better have at least once ...
523 if( uniComponentName.Length == 0)
529 // Copy in the target name ...
532 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
533 pDirEntry->NameInformation.TargetName.Buffer,
534 pDirEntry->NameInformation.TargetName.Length);
536 uniPathName.Buffer = &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)];
538 uniPathName.Length += pDirEntry->NameInformation.TargetName.Length;
539 uniPathName.MaximumLength = uniTempName.MaximumLength;
541 uniTempName.Length += pDirEntry->NameInformation.TargetName.Length;
544 // And now any remaining portion of the name
547 if( uniRemainingPath.Length > 0)
550 if( uniRemainingPath.Buffer[ 0] != L'\\')
553 uniRemainingPath.Buffer--;
554 uniRemainingPath.Length += sizeof( WCHAR);
556 uniPathName.Length += sizeof( WCHAR);
559 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
560 uniRemainingPath.Buffer,
561 uniRemainingPath.Length);
563 uniTempName.Length += uniRemainingPath.Length;
566 uniFullPathName = uniTempName;
568 if( pTmpBuffer != NULL)
571 AFSExFreePoolWithTag( pTmpBuffer, 0);
574 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
577 // Dereference the current entry ..
580 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
582 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
583 AFS_TRACE_LEVEL_VERBOSE,
584 "AFSLocateNameEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
585 &pDirEntry->NameInformation.FileName,
590 ASSERT( lCount >= 0);
593 // OK, need to back up one entry for the correct parent since the current
594 // entry we are on is the symlink itself
597 pDirEntry = AFSBackupEntry( pNameArray);
600 // Increment our reference on this dir entry
603 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
605 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
606 AFS_TRACE_LEVEL_VERBOSE,
607 "AFSLocateNameEntry Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
608 &pDirEntry->NameInformation.FileName,
613 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
616 pParentDirEntry = NULL;
621 pParentDirEntry = AFSGetParentEntry( pNameArray);
623 ASSERT( pParentDirEntry != pDirEntry);
629 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
630 AFS_TRACE_LEVEL_VERBOSE,
631 "AFSLocateNameEntry (FO: %p) Processing absolute symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
633 &pDirEntry->NameInformation.TargetName,
634 &pDirEntry->NameInformation.FileName,
635 pCurrentObject->FileId.Cell,
636 pCurrentObject->FileId.Volume,
637 pCurrentObject->FileId.Vnode,
638 pCurrentObject->FileId.Unique);
640 if ( !AFSIsAbsoluteAFSName( &pDirEntry->NameInformation.TargetName))
643 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
644 AFS_TRACE_LEVEL_ERROR,
645 "AFSLocateNameEntry Name %wZ contains invalid server name\n",
646 &pDirEntry->NameInformation.TargetName);
649 // The correct response would be STATUS_OBJECT_PATH_INVALID
650 // but that prevents cmd.exe from performing a recursive
651 // directory enumeration when opening a directory entry
652 // that represents a symlink to an invalid path is discovered.
655 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
657 try_return( ntStatus = STATUS_OBJECT_PATH_NOT_FOUND);
661 // We'll substitute this name into the current process name
662 // starting at where we sit in the path
665 uniTempName.Length = 0;
666 uniTempName.MaximumLength = pDirEntry->NameInformation.TargetName.Length +
668 uniRemainingPath.Length;
670 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
671 uniTempName.MaximumLength,
672 AFS_NAME_BUFFER_TWO_TAG);
674 if( uniTempName.Buffer == NULL)
677 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
679 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
682 if( bAllocatedSymLinkBuffer ||
686 pTmpBuffer = uniFullPathName.Buffer;
689 bAllocatedSymLinkBuffer = TRUE;
692 // Have we parsed this name yet? Better have at least once ...
695 if( uniComponentName.Length == 0)
701 // Copy in the target name ...
704 RtlCopyMemory( uniTempName.Buffer,
705 &pDirEntry->NameInformation.TargetName.Buffer[ AFSMountRootName.Length/sizeof( WCHAR)],
706 pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length);
708 uniTempName.Length = pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length;
711 // And now any remaining portion of the name
714 if( uniRemainingPath.Length > 0)
717 if( uniRemainingPath.Buffer[ 0] != L'\\')
720 uniRemainingPath.Buffer--;
721 uniRemainingPath.Length += sizeof( WCHAR);
724 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
725 uniRemainingPath.Buffer,
726 uniRemainingPath.Length);
728 uniTempName.Length += uniRemainingPath.Length;
731 uniFullPathName = uniTempName;
733 uniPathName = uniTempName;
735 if( pTmpBuffer != NULL)
738 AFSExFreePoolWithTag( pTmpBuffer, 0);
741 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
744 // If our current volume is not the global root then make it so ...
747 if( pCurrentVolume != AFSGlobalRoot)
750 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
751 AFS_TRACE_LEVEL_VERBOSE,
752 "AFSLocateNameEntry (FO: %p) Current volume not global, resetting for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
754 &pDirEntry->NameInformation.FileName,
755 pCurrentObject->FileId.Cell,
756 pCurrentObject->FileId.Volume,
757 pCurrentObject->FileId.Vnode,
758 pCurrentObject->FileId.Unique);
760 lCount = AFSVolumeDecrement( pCurrentVolume,
761 VolumeReferenceReason);
763 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
764 AFS_TRACE_LEVEL_VERBOSE,
765 "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
767 VolumeReferenceReason,
770 pCurrentVolume = AFSGlobalRoot;
772 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
774 lCount = AFSVolumeIncrement( pCurrentVolume,
775 VolumeReferenceReason);
777 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
778 AFS_TRACE_LEVEL_VERBOSE,
779 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
781 VolumeReferenceReason,
786 // Dereference our current dir entry
789 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
791 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
792 AFS_TRACE_LEVEL_VERBOSE,
793 "AFSLocateNameEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
794 &pDirEntry->NameInformation.FileName,
799 ASSERT( lCount >= 0);
801 pDirEntry = pCurrentVolume->DirectoryCB;
804 // Reference the new dir entry
807 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
809 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
810 AFS_TRACE_LEVEL_VERBOSE,
811 "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
812 &pDirEntry->NameInformation.FileName,
818 // Reset the name array
819 // Persist the link count in the name array
822 lLinkCount = pNameArray->LinkCount;
824 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
825 AFS_TRACE_LEVEL_VERBOSE,
826 "AFSLocateNameEntry (FO: %p) Resetting name array for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
828 &pDirEntry->NameInformation.FileName,
829 pCurrentObject->FileId.Cell,
830 pCurrentObject->FileId.Volume,
831 pCurrentObject->FileId.Vnode,
832 pCurrentObject->FileId.Unique);
834 AFSResetNameArray( pNameArray,
837 pNameArray->LinkCount = lLinkCount;
839 pParentDirEntry = NULL;
843 // Increment our link count
846 lCount = InterlockedIncrement( &pNameArray->LinkCount);
851 case AFS_FILE_TYPE_MOUNTPOINT:
855 // Check if the flag is set to NOT evaluate a mount point
856 // and we are done with the parsing
859 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL) &&
860 uniRemainingPath.Length == 0)
864 // Pass back the directory entries
867 *ParentDirectoryCB = pParentDirEntry;
869 *DirectoryCB = pDirEntry;
871 *VolumeCB = pCurrentVolume;
873 *RootPathName = uniFullPathName;
875 try_return( ntStatus);
878 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
879 AFS_TRACE_LEVEL_VERBOSE,
880 "AFSLocateNameEntry (FO: %p) Building MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
882 &pDirEntry->NameInformation.FileName,
883 pCurrentObject->FileId.Cell,
884 pCurrentObject->FileId.Volume,
885 pCurrentObject->FileId.Vnode,
886 pCurrentObject->FileId.Unique);
889 // Go retrieve the target entry for this node
890 // Release the current volume cb entry since we would
891 // have lock inversion in the following call
892 // Also decrement the ref count on the volume
895 ntStatus = AFSBuildMountPointTarget( AuthGroup,
899 if( !NT_SUCCESS( ntStatus))
902 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
903 AFS_TRACE_LEVEL_ERROR,
904 "AFSLocateNameEntry (FO: %p) Failed to build MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
906 &pDirEntry->NameInformation.FileName,
907 pCurrentObject->FileId.Cell,
908 pCurrentObject->FileId.Volume,
909 pCurrentObject->FileId.Vnode,
910 pCurrentObject->FileId.Unique,
913 try_return( ntStatus);
916 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
918 lCount = AFSVolumeDecrement( pCurrentVolume,
919 VolumeReferenceReason);
921 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
922 AFS_TRACE_LEVEL_VERBOSE,
923 "AFSLocateNameEntry Decrement2 count on volume %p Reason %u Cnt %d\n",
925 VolumeReferenceReason,
928 pCurrentVolume = pTargetVolume;
930 pTargetVolume = NULL;
932 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
934 VolumeReferenceReason = AFS_VOLUME_REFERENCE_MOUNTPT;
937 // We want to restart processing here on the new parent ...
938 // Deref and ref count the entries
941 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
943 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
944 AFS_TRACE_LEVEL_VERBOSE,
945 "AFSLocateNameEntry Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
946 &pDirEntry->NameInformation.FileName,
951 ASSERT( lCount >= 0);
953 pDirEntry = pCurrentVolume->DirectoryCB;
955 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
957 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
958 AFS_TRACE_LEVEL_VERBOSE,
959 "AFSLocateNameEntry Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
960 &pDirEntry->NameInformation.FileName,
966 // The name array stores both the mount point and the target.
967 // Insert the target.
970 AFSInsertNextElement( pNameArray,
973 pParentDirEntry = NULL;
976 // Increment our link count
979 lCount = InterlockedIncrement( &pNameArray->LinkCount);
984 case AFS_FILE_TYPE_DFSLINK:
987 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL))
991 // Pass back the directory entries
994 *ParentDirectoryCB = pParentDirEntry;
996 *DirectoryCB = pDirEntry;
998 *VolumeCB = pCurrentVolume;
1000 *RootPathName = uniFullPathName;
1002 try_return( ntStatus);
1006 // This is a DFS link so we need to update the file name and return STATUS_REPARSE to the
1007 // system for it to reevaluate it
1010 if( FileObject != NULL)
1013 ntStatus = AFSProcessDFSLink( pDirEntry,
1022 // This is where we have been re-entered from an NP evaluation call via the BuildBranch()
1026 ntStatus = STATUS_INVALID_PARAMETER;
1029 if( ntStatus != STATUS_SUCCESS &&
1030 ntStatus != STATUS_REPARSE)
1033 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1034 AFS_TRACE_LEVEL_ERROR,
1035 "AFSLocateNameEntry (FO: %p) Failed to process DFSLink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1037 &pDirEntry->NameInformation.FileName,
1038 pCurrentObject->FileId.Cell,
1039 pCurrentObject->FileId.Volume,
1040 pCurrentObject->FileId.Vnode,
1041 pCurrentObject->FileId.Unique,
1045 try_return( ntStatus);
1048 case AFS_FILE_TYPE_UNKNOWN:
1049 case AFS_FILE_TYPE_INVALID:
1053 // Something was not processed ...
1056 try_return( ntStatus = STATUS_ACCESS_DENIED);
1059 } /* end of switch */
1062 // If the parent is not initialized then do it now
1065 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1066 !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1069 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1070 AFS_TRACE_LEVEL_VERBOSE,
1071 "AFSLocateNameEntry (FO: %p) Enumerating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1073 &pDirEntry->NameInformation.FileName,
1074 pCurrentObject->FileId.Cell,
1075 pCurrentObject->FileId.Volume,
1076 pCurrentObject->FileId.Vnode,
1077 pCurrentObject->FileId.Unique);
1079 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1082 if( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1085 ntStatus = AFSEnumerateDirectory( AuthGroup,
1089 if( !NT_SUCCESS( ntStatus))
1092 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1094 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1095 AFS_TRACE_LEVEL_ERROR,
1096 "AFSLocateNameEntry (FO: %p) Failed to enumerate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1098 &pDirEntry->NameInformation.FileName,
1099 pCurrentObject->FileId.Cell,
1100 pCurrentObject->FileId.Volume,
1101 pCurrentObject->FileId.Vnode,
1102 pCurrentObject->FileId.Unique,
1105 try_return( ntStatus);
1108 SetFlag( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1111 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1113 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1116 if( uniPathName.Length > 0)
1119 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1120 AFS_TRACE_LEVEL_ERROR,
1121 "AFSLocateNameEntry (FO: %p) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1123 &pDirEntry->NameInformation.FileName,
1124 pCurrentObject->FileId.Cell,
1125 pCurrentObject->FileId.Volume,
1126 pCurrentObject->FileId.Vnode,
1127 pCurrentObject->FileId.Unique);
1129 // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1130 // one of the components of the path is not a directory. However, returning
1131 // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1132 // Instead IIS insists on treating the target file as if it is a directory containing
1133 // a potential web.config file. NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1134 // AFS will follow suit.
1136 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1141 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1142 AFS_TRACE_LEVEL_VERBOSE,
1143 "AFSLocateNameEntry (FO: %p) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1145 &pDirEntry->NameInformation.FileName,
1146 pCurrentObject->FileId.Cell,
1147 pCurrentObject->FileId.Volume,
1148 pCurrentObject->FileId.Vnode,
1149 pCurrentObject->FileId.Unique);
1152 // Pass back the directory entries
1155 *ParentDirectoryCB = pParentDirEntry;
1157 *DirectoryCB = pDirEntry;
1159 *VolumeCB = pCurrentVolume;
1161 *RootPathName = uniFullPathName;
1164 try_return( ntStatus);
1168 // If we are at the end of the processing, set our returned information and get out
1171 if( uniPathName.Length == 0)
1174 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1175 AFS_TRACE_LEVEL_VERBOSE,
1176 "AFSLocateNameEntry (FO: %p) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1178 &pDirEntry->NameInformation.FileName,
1179 pCurrentObject->FileId.Cell,
1180 pCurrentObject->FileId.Volume,
1181 pCurrentObject->FileId.Vnode,
1182 pCurrentObject->FileId.Unique);
1185 // Pass back the directory entries
1188 *ParentDirectoryCB = pParentDirEntry;
1190 *DirectoryCB = pDirEntry;
1192 *VolumeCB = pCurrentVolume;
1194 *RootPathName = uniFullPathName;
1196 try_return( ntStatus);
1200 // We may have returned to the top of the while( TRUE)
1202 if( bSubstituteName &&
1203 uniSearchName.Buffer != NULL)
1206 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1208 bSubstituteName = FALSE;
1210 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1211 uniSearchName.Buffer = NULL;
1214 ulSubstituteIndex = 1;
1216 ntStatus = STATUS_SUCCESS;
1219 // Get the next component name
1222 FsRtlDissectName( uniPathName,
1227 // Check for the . and .. in the path
1230 if( RtlCompareUnicodeString( &uniComponentName,
1235 uniPathName = uniRemainingPath;
1240 if( RtlCompareUnicodeString( &uniComponentName,
1245 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1246 AFS_TRACE_LEVEL_VERBOSE,
1247 "AFSLocateNameEntry (FO: %p) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1249 &pDirEntry->NameInformation.FileName,
1250 pCurrentObject->FileId.Cell,
1251 pCurrentObject->FileId.Volume,
1252 pCurrentObject->FileId.Vnode,
1253 pCurrentObject->FileId.Unique);
1256 // Need to back up one entry in the name array
1258 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1260 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1261 AFS_TRACE_LEVEL_VERBOSE,
1262 "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1263 &pDirEntry->NameInformation.FileName,
1268 ASSERT( lCount >= 0);
1270 pDirEntry = AFSBackupEntry( NameArray);
1272 if( pDirEntry == NULL)
1275 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1276 AFS_TRACE_LEVEL_ERROR,
1277 "AFSLocateNameEntry AFSBackupEntry failed\n");
1279 try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1282 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1284 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1285 AFS_TRACE_LEVEL_VERBOSE,
1286 "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1287 &pDirEntry->NameInformation.FileName,
1292 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1295 pParentDirEntry = NULL;
1300 pParentDirEntry = AFSGetParentEntry( pNameArray);
1302 ASSERT( pParentDirEntry != pDirEntry);
1305 uniPathName = uniRemainingPath;
1311 // Update our pointers
1314 pParentDirEntry = pDirEntry;
1318 uniSearchName = uniComponentName;
1320 while( pDirEntry == NULL)
1324 // If the SearchName contains @SYS then we perform the substitution.
1325 // If there is no substitution we give up.
1328 if( !bSubstituteName &&
1329 FsRtlIsNameInExpression( &uniSysName,
1335 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1336 AFS_TRACE_LEVEL_VERBOSE_2,
1337 "AFSLocateNameEntry (FO: %p) Processing @SYS substitution for %wZ Index %08lX\n",
1342 ntStatus = AFSSubstituteSysName( &uniComponentName,
1346 if ( NT_SUCCESS( ntStatus))
1349 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1350 AFS_TRACE_LEVEL_VERBOSE_2,
1351 "AFSLocateNameEntry (FO: %p) Located substitution %wZ for %wZ Index %08lX\n",
1358 // Go reparse the name again
1361 bSubstituteName = TRUE;
1363 ulSubstituteIndex++; // For the next entry, if needed
1365 continue; // while( pDirEntry == NULL)
1370 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1371 AFS_TRACE_LEVEL_ERROR,
1372 "AFSLocateNameEntry (FO: %p) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1378 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1382 // Pass back the directory entries
1385 *ParentDirectoryCB = pParentDirEntry;
1387 *DirectoryCB = NULL;
1389 *VolumeCB = pCurrentVolume;
1391 if( ComponentName != NULL)
1394 *ComponentName = uniComponentName;
1397 *RootPathName = uniFullPathName;
1401 // We can't possibly have a pDirEntry since the lookup failed
1403 try_return( ntStatus);
1408 // Generate the CRC on the node and perform a case sensitive lookup
1411 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1412 AFS_TRACE_LEVEL_VERBOSE_2,
1413 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case sensitive\n",
1417 ulCRC = AFSGenerateCRC( &uniSearchName,
1420 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1423 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1427 if( pDirEntry == NULL)
1431 // Missed so perform a case insensitive lookup
1434 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1435 AFS_TRACE_LEVEL_VERBOSE_2,
1436 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case insensitive\n",
1440 ulCRC = AFSGenerateCRC( &uniSearchName,
1443 AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1447 if( pDirEntry == NULL)
1451 // OK, if this component is a valid short name then try
1452 // a lookup in the short name tree
1455 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1456 RtlIsNameLegalDOS8Dot3( &uniSearchName,
1461 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1462 AFS_TRACE_LEVEL_VERBOSE_2,
1463 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ short name\n",
1467 AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1472 if ( pDirEntry == NULL &&
1473 pParentDirEntry->ObjectInformation->VolumeCB == AFSGlobalRoot)
1477 // Check with the service to see if this is a valid cell name
1478 // that can be automatically resolved. Drop the shared TreeLock
1479 // since AFSCheckCellName must acquire it exclusively.
1482 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1484 ntStatus = AFSCheckCellName( AuthGroup,
1488 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1492 if( pDirEntry == NULL)
1496 // If we substituted a name then reset our search name and try again
1499 if( bSubstituteName)
1502 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1504 uniSearchName = uniComponentName;
1506 bSubstituteName = FALSE;
1508 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1510 continue; // while( pDirEntry == NULL)
1513 if( uniRemainingPath.Length > 0)
1516 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1518 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1519 AFS_TRACE_LEVEL_VERBOSE,
1520 "AFSLocateNameEntry (FO: %p) Returning path not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1523 pCurrentObject->FileId.Cell,
1524 pCurrentObject->FileId.Volume,
1525 pCurrentObject->FileId.Vnode,
1526 pCurrentObject->FileId.Unique);
1531 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1533 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1534 AFS_TRACE_LEVEL_VERBOSE,
1535 "AFSLocateNameEntry (FO: %p) Returning name not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1538 pCurrentObject->FileId.Cell,
1539 pCurrentObject->FileId.Volume,
1540 pCurrentObject->FileId.Vnode,
1541 pCurrentObject->FileId.Unique);
1544 // Pass back the directory entries
1547 *ParentDirectoryCB = pParentDirEntry;
1549 *DirectoryCB = NULL;
1551 *VolumeCB = pCurrentVolume;
1553 if( ComponentName != NULL)
1556 *ComponentName = uniComponentName;
1559 *RootPathName = uniFullPathName;
1562 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1565 // Node name not found so get out
1568 try_return( ntStatus); // while( pDirEntry == NULL)
1575 // Here we have a match on the case insensitive lookup for the name. If there
1576 // Is more than one link entry for this node then fail the lookup request
1579 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1580 pDirEntry->CaseInsensitiveList.fLink != NULL)
1584 // Increment our dir entry ref count since we will decrement it on exit
1587 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1589 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1590 AFS_TRACE_LEVEL_VERBOSE,
1591 "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1592 &pDirEntry->NameInformation.FileName,
1597 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1599 try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1604 if( pDirEntry != NULL)
1608 // If the verify flag is set on the parent and the current entry is deleted
1609 // revalidate the parent and search again.
1612 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1613 BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1616 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1618 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1619 AFS_TRACE_LEVEL_VERBOSE,
1620 "AFSLocateNameEntry (FO: %p) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1622 &pParentDirEntry->NameInformation.FileName,
1623 pParentDirEntry->ObjectInformation->FileId.Cell,
1624 pParentDirEntry->ObjectInformation->FileId.Volume,
1625 pParentDirEntry->ObjectInformation->FileId.Vnode,
1626 pParentDirEntry->ObjectInformation->FileId.Unique);
1629 // Directory TreeLock should be exclusively held
1632 AFSAcquireExcl( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1635 ntStatus = AFSVerifyEntry( AuthGroup,
1638 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1640 if( !NT_SUCCESS( ntStatus))
1643 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1644 AFS_TRACE_LEVEL_ERROR,
1645 "AFSLocateNameEntry (FO: %p) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1647 &pParentDirEntry->NameInformation.FileName,
1648 pParentDirEntry->ObjectInformation->FileId.Cell,
1649 pParentDirEntry->ObjectInformation->FileId.Volume,
1650 pParentDirEntry->ObjectInformation->FileId.Vnode,
1651 pParentDirEntry->ObjectInformation->FileId.Unique,
1654 try_return( ntStatus);
1657 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1658 AFS_TRACE_LEVEL_VERBOSE,
1659 "AFSLocateNameEntry (FO: %p) Reprocessing component %wZ in parent %wZ\n",
1662 &pParentDirEntry->NameInformation.FileName);
1671 // Increment our dir entry ref count
1674 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1676 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1677 AFS_TRACE_LEVEL_VERBOSE,
1678 "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1679 &pDirEntry->NameInformation.FileName,
1685 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1687 } // End while( pDirEntry == NULL)
1690 // If we have a dirEntry for this component, perform some basic validation on it
1693 if( pDirEntry != NULL &&
1694 BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1697 pCurrentObject = pDirEntry->ObjectInformation;
1699 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1700 AFS_TRACE_LEVEL_ERROR,
1701 "AFSLocateNameEntry (FO: %p) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1703 &pDirEntry->NameInformation.FileName,
1704 pCurrentObject->FileId.Cell,
1705 pCurrentObject->FileId.Volume,
1706 pCurrentObject->FileId.Vnode,
1707 pCurrentObject->FileId.Unique);
1710 // This entry was deleted through the invalidation call back so perform cleanup
1714 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1717 pParentObjectInfo = AFSFindObjectInfo( pCurrentObject->VolumeCB,
1718 &pCurrentObject->ParentFileId);
1721 ASSERT( pParentObjectInfo != NULL);
1723 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1726 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1729 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1731 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1732 AFS_TRACE_LEVEL_VERBOSE,
1733 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1734 &pDirEntry->NameInformation.FileName,
1739 ASSERT( lCount >= 0);
1744 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1745 AFS_TRACE_LEVEL_VERBOSE,
1746 "AFSLocateNameEntry Deleting dir entry %p (%p) for %wZ\n",
1749 &pDirEntry->NameInformation.FileName);
1752 // Remove and delete the directory entry from the parent list
1755 AFSDeleteDirEntry( pParentObjectInfo,
1758 AFSAcquireShared( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1761 if( pCurrentObject->ObjectReferenceCount <= 0)
1764 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
1767 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1768 AFS_TRACE_LEVEL_VERBOSE,
1769 "AFSLocateNameEntry Removing object %p from volume tree\n",
1772 AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
1773 &pCurrentObject->TreeEntry);
1775 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
1779 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1784 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1785 AFS_TRACE_LEVEL_VERBOSE,
1786 "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
1788 &pDirEntry->NameInformation.FileName);
1790 SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
1792 AFSRemoveNameEntry( pParentObjectInfo,
1796 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1798 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
1800 AFSReleaseObjectInfo( &pParentObjectInfo);
1803 // We deleted the dir entry so check if there is any remaining portion
1804 // of the name to process.
1807 if( uniRemainingPath.Length > 0)
1810 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1812 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1813 AFS_TRACE_LEVEL_VERBOSE,
1814 "AFSLocateNameEntry (FO: %p) Returning path not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1817 pCurrentObject->FileId.Cell,
1818 pCurrentObject->FileId.Volume,
1819 pCurrentObject->FileId.Vnode,
1820 pCurrentObject->FileId.Unique);
1825 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1827 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1828 AFS_TRACE_LEVEL_VERBOSE,
1829 "AFSLocateNameEntry (FO: %p) Returning name not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1832 pCurrentObject->FileId.Cell,
1833 pCurrentObject->FileId.Volume,
1834 pCurrentObject->FileId.Vnode,
1835 pCurrentObject->FileId.Unique);
1838 // Pass back the directory entries
1841 *ParentDirectoryCB = pParentDirEntry;
1843 *DirectoryCB = NULL;
1845 *VolumeCB = pCurrentVolume;
1847 if( ComponentName != NULL)
1850 *ComponentName = uniComponentName;
1853 *RootPathName = uniFullPathName;
1857 if( ntStatus != STATUS_SUCCESS)
1860 try_return( ntStatus);
1864 // Decrement the previous parent
1867 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1869 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1870 AFS_TRACE_LEVEL_VERBOSE,
1871 "AFSLocateNameEntry Decrement5 count on Parent %wZ DE %p Ccb %p Cnt %d\n",
1872 &pParentDirEntry->NameInformation.FileName,
1877 ASSERT( lCount >= 0);
1880 // If we ended up substituting a name in the component then update
1881 // the full path and update the pointers
1884 if( bSubstituteName)
1887 BOOLEAN bRelativeOpen = FALSE;
1889 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1890 AFS_TRACE_LEVEL_VERBOSE_2,
1891 "AFSLocateNameEntry (FO: %p) Substituting %wZ into %wZ Index %08lX\n",
1897 if( FileObject != NULL &&
1898 FileObject->RelatedFileObject != NULL)
1901 bRelativeOpen = TRUE;
1905 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
1906 // and free the prior Buffer contents but only if the fourth
1907 // parameter is TRUE.
1910 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
1915 bAllocatedSymLinkBuffer ||
1918 if( !NT_SUCCESS( ntStatus))
1921 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1922 AFS_TRACE_LEVEL_ERROR,
1923 "AFSLocateNameEntry (FO: %p) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
1930 try_return( ntStatus);
1934 // We have substituted a name into the buffer so if we do this again for this
1935 // path, we need to free up the buffer we allocated.
1938 bSubstitutedName = TRUE;
1942 // Update the search parameters
1945 uniPathName = uniRemainingPath;
1948 // Check if the is a SymLink entry but has no Target FileID or Name. In this
1949 // case it might be a DFS Link so let's go and evaluate it to be sure
1952 if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
1953 ( pCurrentObject->TargetFileId.Vnode == 0 ||
1954 pDirEntry->NameInformation.TargetName.Length == 0))
1957 ntStatus = AFSValidateSymLink( AuthGroup,
1960 if( !NT_SUCCESS( ntStatus))
1963 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1964 AFS_TRACE_LEVEL_ERROR,
1965 "AFSLocateNameEntry (FO: %p) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1967 &pDirEntry->NameInformation.FileName,
1968 pCurrentObject->FileId.Cell,
1969 pCurrentObject->FileId.Volume,
1970 pCurrentObject->FileId.Vnode,
1971 pCurrentObject->FileId.Unique,
1974 try_return( ntStatus);
1979 // Update the name array
1982 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1983 AFS_TRACE_LEVEL_VERBOSE,
1984 "AFSLocateNameEntry (FO: %p) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1986 &pDirEntry->NameInformation.FileName,
1987 pCurrentObject->FileId.Cell,
1988 pCurrentObject->FileId.Volume,
1989 pCurrentObject->FileId.Vnode,
1990 pCurrentObject->FileId.Unique);
1992 ntStatus = AFSInsertNextElement( pNameArray,
1995 if( !NT_SUCCESS( ntStatus))
1998 try_return( ntStatus);
2004 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2005 AFS_TRACE_LEVEL_VERBOSE,
2006 "AFSLocateNameEntry (FO: %p) Completed processing %wZ Status %08lX\n",
2011 if( ( !NT_SUCCESS( ntStatus) &&
2012 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
2013 ntStatus == STATUS_REPARSE)
2016 if( pDirEntry != NULL)
2019 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
2021 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2022 AFS_TRACE_LEVEL_VERBOSE,
2023 "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
2024 &pDirEntry->NameInformation.FileName,
2029 ASSERT( lCount >= 0);
2031 else if( pParentDirEntry != NULL)
2034 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
2036 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2037 AFS_TRACE_LEVEL_VERBOSE,
2038 "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
2039 &pParentDirEntry->NameInformation.FileName,
2044 ASSERT( lCount >= 0);
2047 if( bReleaseCurrentVolume)
2050 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
2052 lCount = AFSVolumeDecrement( pCurrentVolume,
2053 VolumeReferenceReason);
2055 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2056 AFS_TRACE_LEVEL_VERBOSE,
2057 "AFSLocateNameEntry Decrement3 count on volume %p Reason %u Cnt %d\n",
2059 VolumeReferenceReason,
2062 bReleaseCurrentVolume = FALSE;
2065 if( RootPathName->Buffer != uniFullPathName.Buffer)
2068 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
2074 if( *ParentDirectoryCB != NULL)
2077 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2078 AFS_TRACE_LEVEL_VERBOSE,
2079 "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
2080 &(*ParentDirectoryCB)->NameInformation.FileName,
2083 (*ParentDirectoryCB)->DirOpenReferenceCount);
2086 if( *DirectoryCB != NULL)
2089 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2090 AFS_TRACE_LEVEL_VERBOSE,
2091 "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
2092 &(*DirectoryCB)->NameInformation.FileName,
2095 (*DirectoryCB)->DirOpenReferenceCount);
2099 if( bSubstituteName &&
2100 uniSearchName.Buffer != NULL)
2103 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
2106 if ( bReleaseCurrentVolume) {
2108 *pVolumeReferenceReason = VolumeReferenceReason;
2116 AFSCreateDirEntry( IN GUID *AuthGroup,
2117 IN AFSObjectInfoCB *ParentObjectInfo,
2118 IN AFSDirectoryCB *ParentDirCB,
2119 IN PUNICODE_STRING FileName,
2120 IN PUNICODE_STRING ComponentName,
2121 IN ULONG Attributes,
2122 IN OUT AFSDirectoryCB **DirEntry)
2125 UNREFERENCED_PARAMETER(FileName);
2126 NTSTATUS ntStatus = STATUS_SUCCESS;
2127 AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
2128 LARGE_INTEGER liFileSize = {0,0};
2134 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2135 AFS_TRACE_LEVEL_VERBOSE_2,
2136 "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
2137 &ParentDirCB->NameInformation.FileName,
2138 ParentObjectInfo->FileId.Cell,
2139 ParentObjectInfo->FileId.Volume,
2140 ParentObjectInfo->FileId.Vnode,
2141 ParentObjectInfo->FileId.Unique,
2146 // OK, before inserting the node into the parent tree, issue
2147 // the request to the service for node creation
2148 // We will need to drop the lock on the parent node since the create
2149 // could cause a callback into the file system to invalidate it's cache
2152 ntStatus = AFSNotifyFileCreate( AuthGroup,
2160 // If the returned status is STATUS_REPARSE then the entry exists
2161 // and we raced, get out.
2163 if( ntStatus == STATUS_REPARSE)
2166 *DirEntry = pDirNode;
2168 try_return( ntStatus = STATUS_SUCCESS);
2171 if( !NT_SUCCESS( ntStatus))
2174 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2175 AFS_TRACE_LEVEL_ERROR,
2176 "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
2177 &ParentDirCB->NameInformation.FileName,
2178 ParentObjectInfo->FileId.Cell,
2179 ParentObjectInfo->FileId.Volume,
2180 ParentObjectInfo->FileId.Vnode,
2181 ParentObjectInfo->FileId.Unique,
2186 try_return( ntStatus);
2190 // If AFSNotifyFileCreate returns pDirNode != NULL, then its
2191 // DirOpenReferenceCount is held.
2194 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2198 // Before attempting to insert the new entry, check if we need to validate the parent
2201 if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2204 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2205 AFS_TRACE_LEVEL_VERBOSE,
2206 "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2207 &ParentDirCB->NameInformation.FileName,
2208 ParentObjectInfo->FileId.Cell,
2209 ParentObjectInfo->FileId.Volume,
2210 ParentObjectInfo->FileId.Vnode,
2211 ParentObjectInfo->FileId.Unique);
2213 ntStatus = AFSVerifyEntry( AuthGroup,
2216 if( !NT_SUCCESS( ntStatus))
2219 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2220 AFS_TRACE_LEVEL_ERROR,
2221 "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2222 &ParentDirCB->NameInformation.FileName,
2223 ParentObjectInfo->FileId.Cell,
2224 ParentObjectInfo->FileId.Volume,
2225 ParentObjectInfo->FileId.Vnode,
2226 ParentObjectInfo->FileId.Unique,
2229 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2231 try_return( ntStatus);
2236 // Check for the entry in the event we raced with some other thread
2239 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2240 (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2243 if( pExistingDirNode != NULL)
2245 if (AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2246 &pExistingDirNode->ObjectInformation->FileId))
2249 if ( pExistingDirNode != pDirNode)
2252 lCount = InterlockedDecrement( &pDirNode->DirOpenReferenceCount);
2254 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2255 AFS_TRACE_LEVEL_VERBOSE,
2256 "AFSCreateDirEntry Decrement count on %wZ DE %p Cnt %d\n",
2257 &pDirNode->NameInformation.FileName,
2261 AFSDeleteDirEntry( ParentObjectInfo,
2264 lCount = InterlockedIncrement( &pExistingDirNode->DirOpenReferenceCount);
2266 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2267 AFS_TRACE_LEVEL_VERBOSE,
2268 "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2269 &pExistingDirNode->NameInformation.FileName,
2273 *DirEntry = pExistingDirNode;
2276 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2278 try_return( ntStatus = STATUS_SUCCESS);
2284 // Need to tear down this entry and rebuild it below
2287 if( pExistingDirNode->DirOpenReferenceCount <= 0)
2290 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2291 AFS_TRACE_LEVEL_VERBOSE,
2292 "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2294 &pExistingDirNode->NameInformation.FileName,
2295 pExistingDirNode->ObjectInformation->FileId.Cell,
2296 pExistingDirNode->ObjectInformation->FileId.Volume,
2297 pExistingDirNode->ObjectInformation->FileId.Vnode,
2298 pExistingDirNode->ObjectInformation->FileId.Unique,
2299 pDirNode->ObjectInformation->FileId.Cell,
2300 pDirNode->ObjectInformation->FileId.Volume,
2301 pDirNode->ObjectInformation->FileId.Vnode,
2302 pDirNode->ObjectInformation->FileId.Unique);
2304 AFSDeleteDirEntry( ParentObjectInfo,
2310 SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2312 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2313 AFS_TRACE_LEVEL_VERBOSE,
2314 "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2316 &pExistingDirNode->NameInformation.FileName,
2317 pExistingDirNode->ObjectInformation->FileId.Cell,
2318 pExistingDirNode->ObjectInformation->FileId.Volume,
2319 pExistingDirNode->ObjectInformation->FileId.Vnode,
2320 pExistingDirNode->ObjectInformation->FileId.Unique,
2321 pDirNode->ObjectInformation->FileId.Cell,
2322 pDirNode->ObjectInformation->FileId.Volume,
2323 pDirNode->ObjectInformation->FileId.Vnode,
2324 pDirNode->ObjectInformation->FileId.Unique);
2326 AFSRemoveNameEntry( ParentObjectInfo,
2332 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2333 AFS_TRACE_LEVEL_VERBOSE_2,
2334 "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2335 &ParentDirCB->NameInformation.FileName,
2336 ParentObjectInfo->FileId.Cell,
2337 ParentObjectInfo->FileId.Volume,
2338 ParentObjectInfo->FileId.Vnode,
2339 ParentObjectInfo->FileId.Unique,
2343 // Insert the directory node
2346 AFSInsertDirectoryNode( ParentObjectInfo,
2351 // Pass back the dir entry
2354 *DirEntry = pDirNode;
2356 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2367 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2368 IN AFSDirectoryCB *DirEntry,
2369 IN BOOLEAN InsertInEnumList)
2377 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2380 // Insert the node into the directory node tree
2383 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2384 AFS_TRACE_LEVEL_VERBOSE,
2385 "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2387 &DirEntry->NameInformation.FileName);
2389 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2391 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2394 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2396 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2397 AFS_TRACE_LEVEL_VERBOSE,
2398 "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2400 &DirEntry->NameInformation.FileName);
2405 AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2408 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2409 AFS_TRACE_LEVEL_VERBOSE,
2410 "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2412 &DirEntry->NameInformation.FileName);
2415 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2418 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2420 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2422 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2423 AFS_TRACE_LEVEL_VERBOSE,
2424 "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2426 &DirEntry->NameInformation.FileName);
2431 AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2434 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2435 AFS_TRACE_LEVEL_VERBOSE,
2436 "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2438 &DirEntry->NameInformation.FileName);
2442 // Into the shortname tree
2445 if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2448 if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2451 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2453 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2454 AFS_TRACE_LEVEL_VERBOSE,
2455 "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2457 &DirEntry->NameInformation.FileName);
2459 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2464 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2467 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2468 AFS_TRACE_LEVEL_VERBOSE,
2469 "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2471 &DirEntry->NameInformation.FileName);
2475 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2477 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2478 AFS_TRACE_LEVEL_VERBOSE,
2479 "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2481 &DirEntry->NameInformation.FileName);
2486 if( InsertInEnumList)
2490 // And insert the node into the directory list
2493 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2494 AFS_TRACE_LEVEL_VERBOSE,
2495 "AFSInsertDirectoryNode Inserting entry %p %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2497 &DirEntry->NameInformation.FileName,
2498 DirEntry->ObjectInformation->FileId.Cell,
2499 DirEntry->ObjectInformation->FileId.Volume,
2500 DirEntry->ObjectInformation->FileId.Vnode,
2501 DirEntry->ObjectInformation->FileId.Unique);
2503 if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2506 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2511 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2513 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2516 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2518 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2520 lCount = InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2522 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2523 AFS_TRACE_LEVEL_VERBOSE,
2524 "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2525 &DirEntry->NameInformation.FileName,
2527 ParentObjectInfo->FileId.Cell,
2528 ParentObjectInfo->FileId.Volume,
2529 ParentObjectInfo->FileId.Vnode,
2530 ParentObjectInfo->FileId.Unique);
2538 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2539 IN AFSDirectoryCB *DirEntry)
2547 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2548 AFS_TRACE_LEVEL_VERBOSE,
2549 "AFSDeleteDirEntry Deleting dir entry in parent %p Entry %p %wZ FID %08lX-%08lX-%08lX-%08lX RefCount %d\n",
2552 &DirEntry->NameInformation.FileName,
2553 DirEntry->ObjectInformation->FileId.Cell,
2554 DirEntry->ObjectInformation->FileId.Volume,
2555 DirEntry->ObjectInformation->FileId.Vnode,
2556 DirEntry->ObjectInformation->FileId.Unique,
2557 DirEntry->DirOpenReferenceCount);
2559 ASSERT( DirEntry->DirOpenReferenceCount == 0);
2561 AFSRemoveDirNodeFromParent( ParentObjectInfo,
2566 // Free up the name buffer if it was reallocated
2569 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2572 AFSExFreePoolWithTag( DirEntry->NameInformation.FileName.Buffer, 0);
2575 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2578 AFSExFreePoolWithTag( DirEntry->NameInformation.TargetName.Buffer, 0);
2582 // Dereference the object for this dir entry
2585 lCount = AFSObjectInfoDecrement( DirEntry->ObjectInformation,
2586 AFS_OBJECT_REFERENCE_DIRENTRY);
2588 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2589 AFS_TRACE_LEVEL_VERBOSE,
2590 "AFSDeleteDirEntry Decrement count on object %p Cnt %d\n",
2591 DirEntry->ObjectInformation,
2594 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
2595 DirEntry->ObjectInformation->Links == 0)
2598 SetFlag( DirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2601 ExDeleteResourceLite( &DirEntry->NonPaged->Lock);
2603 AFSExFreePoolWithTag( DirEntry->NonPaged, AFS_DIR_ENTRY_NP_TAG);
2606 // Free up the dir entry
2609 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
2610 AFS_TRACE_LEVEL_VERBOSE,
2611 "AFSDeleteDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
2614 AFSExFreePoolWithTag( DirEntry, AFS_DIR_ENTRY_TAG);
2619 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2620 IN AFSDirectoryCB *DirEntry,
2621 IN BOOLEAN RemoveFromEnumList)
2624 NTSTATUS ntStatus = STATUS_SUCCESS;
2631 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2633 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2634 AFS_TRACE_LEVEL_VERBOSE,
2635 "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %p\n",
2637 &DirEntry->NameInformation.FileName,
2638 DirEntry->ObjectInformation->FileId.Cell,
2639 DirEntry->ObjectInformation->FileId.Volume,
2640 DirEntry->ObjectInformation->FileId.Vnode,
2641 DirEntry->ObjectInformation->FileId.Unique,
2644 if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2647 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2648 AFS_TRACE_LEVEL_VERBOSE,
2649 "AFSRemoveDirNodeFromParent Removing DirEntry %p name %wZ\n",
2651 &DirEntry->NameInformation.FileName);
2653 AFSRemoveNameEntry( ParentObjectInfo,
2659 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2660 AFS_TRACE_LEVEL_VERBOSE,
2661 "AFSRemoveDirNodeFromParent DE %p for %wZ NOT removing entry due to flag set\n",
2663 &DirEntry->NameInformation.FileName);
2667 if( RemoveFromEnumList &&
2668 BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST))
2672 // And remove the entry from the enumeration list
2675 if( DirEntry->ListEntry.fLink == NULL)
2678 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = (AFSDirectoryCB *)DirEntry->ListEntry.bLink;
2683 ((AFSDirectoryCB *)DirEntry->ListEntry.fLink)->ListEntry.bLink = DirEntry->ListEntry.bLink;
2686 if( DirEntry->ListEntry.bLink == NULL)
2689 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = (AFSDirectoryCB *)DirEntry->ListEntry.fLink;
2694 ((AFSDirectoryCB *)DirEntry->ListEntry.bLink)->ListEntry.fLink = DirEntry->ListEntry.fLink;
2697 ASSERT( ParentObjectInfo->Specific.Directory.DirectoryNodeCount > 0);
2699 lCount = InterlockedDecrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2701 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2703 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2704 AFS_TRACE_LEVEL_VERBOSE,
2705 "AFSRemoveDirNodeFromParent Removing entry %wZ Dec Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2706 &DirEntry->NameInformation.FileName,
2708 ParentObjectInfo->FileId.Cell,
2709 ParentObjectInfo->FileId.Volume,
2710 ParentObjectInfo->FileId.Vnode,
2711 ParentObjectInfo->FileId.Unique);
2713 DirEntry->ListEntry.fLink = NULL;
2714 DirEntry->ListEntry.bLink = NULL;
2722 AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
2723 IN OUT PUNICODE_STRING TargetFileName)
2726 NTSTATUS ntStatus = STATUS_SUCCESS;
2727 UNICODE_STRING uniFileName;
2733 // We will process backwards from the end of the name looking
2734 // for the first \ we encounter
2737 uniFileName.Length = FileName->Length;
2738 uniFileName.MaximumLength = FileName->MaximumLength;
2740 uniFileName.Buffer = FileName->Buffer;
2745 if( uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
2749 // Subtract one more character off of the filename if it is not the root
2752 if( uniFileName.Length > sizeof( WCHAR))
2755 uniFileName.Length -= sizeof( WCHAR);
2759 // Now build up the target name
2762 TargetFileName->Length = FileName->Length - uniFileName.Length;
2765 // If we are not on the root then fixup the name
2768 if( uniFileName.Length > sizeof( WCHAR))
2771 TargetFileName->Length -= sizeof( WCHAR);
2773 TargetFileName->Buffer = &uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) + 1];
2778 TargetFileName->Buffer = &uniFileName.Buffer[ uniFileName.Length/sizeof( WCHAR)];
2782 // Fixup the passed back filename length
2785 FileName->Length = uniFileName.Length;
2787 TargetFileName->MaximumLength = TargetFileName->Length;
2792 uniFileName.Length -= sizeof( WCHAR);
2800 AFSParseName( IN PIRP Irp,
2802 OUT PUNICODE_STRING FileName,
2803 OUT PUNICODE_STRING ParsedFileName,
2804 OUT PUNICODE_STRING RootFileName,
2805 OUT ULONG *ParseFlags,
2806 OUT AFSVolumeCB **VolumeCB,
2807 OUT AFSDirectoryCB **ParentDirectoryCB,
2808 OUT AFSNameArrayHdr **NameArray)
2811 NTSTATUS ntStatus = STATUS_SUCCESS;
2812 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2813 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2814 UNICODE_STRING uniFullName, uniComponentName, uniRemainingPath;
2816 AFSDirectoryCB *pDirEntry = NULL;
2817 USHORT usIndex = 0, usDriveIndex = 0;
2818 AFSCcb *pRelatedCcb = NULL;
2819 AFSNameArrayHdr *pNameArray = NULL, *pRelatedNameArray = NULL;
2820 USHORT usComponentIndex = 0;
2821 USHORT usComponentLength = 0;
2822 AFSVolumeCB *pVolumeCB = NULL;
2823 AFSFcb *pRelatedFcb = NULL;
2824 BOOLEAN bReleaseTreeLock = FALSE;
2825 BOOLEAN bIsAllShare = FALSE;
2832 // Indicate we are opening a root ...
2835 *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
2837 *ParentDirectoryCB = NULL;
2839 if( pIrpSp->FileObject->RelatedFileObject != NULL)
2842 pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
2844 pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
2846 pRelatedNameArray = pRelatedCcb->NameArray;
2848 uniFullName = pIrpSp->FileObject->FileName;
2850 ASSERT( pRelatedFcb != NULL);
2853 // No wild cards in the name
2856 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2857 AFS_TRACE_LEVEL_VERBOSE_2,
2858 "AFSParseName (%p) Relative open for %wZ FID %08lX-%08lX-%08lX-%08lX component %wZ\n",
2860 &pRelatedCcb->DirectoryCB->NameInformation.FileName,
2861 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Cell,
2862 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Volume,
2863 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
2864 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Unique,
2867 if( FsRtlDoesNameContainWildCards( &uniFullName))
2870 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2871 AFS_TRACE_LEVEL_ERROR,
2872 "AFSParseName (%p) Component %wZ contains wild cards\n",
2876 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
2879 pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
2881 pDirEntry = pRelatedCcb->DirectoryCB;
2883 *FileName = pIrpSp->FileObject->FileName;
2886 // Grab the root node while checking state
2889 AFSAcquireShared( pVolumeCB->VolumeLock,
2892 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
2893 BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
2897 // The volume has been taken off line so fail the access
2900 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2901 AFS_TRACE_LEVEL_ERROR,
2902 "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
2904 pVolumeCB->ObjectInformation.FileId.Cell,
2905 pVolumeCB->ObjectInformation.FileId.Volume);
2907 AFSReleaseResource( pVolumeCB->VolumeLock);
2909 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
2912 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
2915 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2916 AFS_TRACE_LEVEL_VERBOSE,
2917 "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
2919 pVolumeCB->ObjectInformation.FileId.Cell,
2920 pVolumeCB->ObjectInformation.FileId.Volume);
2922 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
2925 if( !NT_SUCCESS( ntStatus))
2928 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2929 AFS_TRACE_LEVEL_ERROR,
2930 "AFSParseName (%p) Failed verification of root Status %08lX\n",
2934 AFSReleaseResource( pVolumeCB->VolumeLock);
2936 try_return( ntStatus);
2940 AFSReleaseResource( pVolumeCB->VolumeLock);
2942 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
2945 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2946 AFS_TRACE_LEVEL_VERBOSE,
2947 "AFSParseName (%p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2949 &pDirEntry->NameInformation.FileName,
2950 pDirEntry->ObjectInformation->FileId.Cell,
2951 pDirEntry->ObjectInformation->FileId.Volume,
2952 pDirEntry->ObjectInformation->FileId.Vnode,
2953 pDirEntry->ObjectInformation->FileId.Unique);
2956 // Directory TreeLock should be exclusively held
2959 AFSAcquireExcl( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
2962 ntStatus = AFSVerifyEntry( AuthGroup,
2965 AFSReleaseResource( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2967 if( !NT_SUCCESS( ntStatus))
2970 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2971 AFS_TRACE_LEVEL_VERBOSE,
2972 "AFSParseName (%p) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2974 &pDirEntry->NameInformation.FileName,
2975 pDirEntry->ObjectInformation->FileId.Cell,
2976 pDirEntry->ObjectInformation->FileId.Volume,
2977 pDirEntry->ObjectInformation->FileId.Vnode,
2978 pDirEntry->ObjectInformation->FileId.Unique,
2981 try_return( ntStatus);
2986 // Create our full path name buffer
2989 uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length +
2991 pIrpSp->FileObject->FileName.Length +
2994 uniFullName.Length = 0;
2996 uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2997 uniFullName.MaximumLength,
2998 AFS_NAME_BUFFER_THREE_TAG);
3000 if( uniFullName.Buffer == NULL)
3003 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3004 AFS_TRACE_LEVEL_ERROR,
3005 "AFSParseName (%p) Failed to allocate full name buffer\n",
3008 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3011 RtlZeroMemory( uniFullName.Buffer,
3012 uniFullName.MaximumLength);
3014 RtlCopyMemory( uniFullName.Buffer,
3015 pRelatedCcb->FullFileName.Buffer,
3016 pRelatedCcb->FullFileName.Length);
3018 uniFullName.Length = pRelatedCcb->FullFileName.Length;
3020 usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
3022 usComponentLength = pIrpSp->FileObject->FileName.Length;
3024 if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
3025 pIrpSp->FileObject->FileName.Length > 0 &&
3026 pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
3027 pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
3030 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
3032 uniFullName.Length += sizeof( WCHAR);
3034 usComponentLength += sizeof( WCHAR);
3037 if( pIrpSp->FileObject->FileName.Length > 0)
3040 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
3041 pIrpSp->FileObject->FileName.Buffer,
3042 pIrpSp->FileObject->FileName.Length);
3044 uniFullName.Length += pIrpSp->FileObject->FileName.Length;
3047 *RootFileName = uniFullName;
3050 // We populate up to the current parent
3053 if( pRelatedNameArray == NULL)
3057 // Init and populate our name array
3060 pNameArray = AFSInitNameArray( NULL,
3063 if( pNameArray == NULL)
3066 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3067 AFS_TRACE_LEVEL_VERBOSE,
3068 "AFSParseName (%p) Failed to initialize name array\n",
3071 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3073 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3076 ntStatus = AFSPopulateNameArray( pNameArray,
3078 pRelatedCcb->DirectoryCB);
3084 // Init and populate our name array
3087 pNameArray = AFSInitNameArray( NULL,
3088 pRelatedNameArray->MaxElementCount);
3090 if( pNameArray == NULL)
3093 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3094 AFS_TRACE_LEVEL_VERBOSE,
3095 "AFSParseName (%p) Failed to initialize name array\n",
3098 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3100 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3103 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
3105 pRelatedCcb->DirectoryCB);
3108 if( !NT_SUCCESS( ntStatus))
3111 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3112 AFS_TRACE_LEVEL_VERBOSE,
3113 "AFSParseName (%p) Failed to populate name array\n",
3116 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3118 try_return( ntStatus);
3121 ParsedFileName->Length = usComponentLength;
3122 ParsedFileName->MaximumLength = uniFullName.MaximumLength;
3124 ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
3127 // Indicate to caller that RootFileName must be freed
3130 SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
3132 *NameArray = pNameArray;
3135 // Increment our volume reference count
3138 lCount = AFSVolumeIncrement( pVolumeCB,
3139 AFS_VOLUME_REFERENCE_PARSE_NAME);
3141 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3142 AFS_TRACE_LEVEL_VERBOSE,
3143 "AFSParseName Increment count on volume %p Cnt %d\n",
3147 *VolumeCB = pVolumeCB;
3149 *ParentDirectoryCB = pDirEntry;
3151 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3152 AFS_TRACE_LEVEL_VERBOSE_2,
3153 "AFSParseName (%p) Returning full name %wZ\n",
3157 try_return( ntStatus);
3161 // No wild cards in the name
3164 uniFullName = pIrpSp->FileObject->FileName;
3166 if( FsRtlDoesNameContainWildCards( &uniFullName) ||
3167 uniFullName.Length < AFSServerName.Length)
3170 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3171 AFS_TRACE_LEVEL_ERROR,
3172 "AFSParseName (%p) Name %wZ contains wild cards or too short\n",
3176 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3180 // The name is a fully qualified name. Parse out the server/share names and
3181 // point to the root qualified name
3182 // First thing is to locate the server name
3185 FsRtlDissectName( uniFullName,
3189 uniFullName = uniRemainingPath;
3192 // This component is the server name we are serving
3195 if( RtlCompareUnicodeString( &uniComponentName,
3201 // Drive letter based name?
3204 uniFullName = pIrpSp->FileObject->FileName;
3206 while( usIndex < uniFullName.Length/sizeof( WCHAR))
3209 if( uniFullName.Buffer[ usIndex] == L':')
3212 uniFullName.Buffer = &uniFullName.Buffer[ usIndex + 2];
3214 uniFullName.Length -= (usIndex + 2) * sizeof( WCHAR);
3216 usDriveIndex = usIndex - 1;
3225 // Do we have the right server name now?
3228 FsRtlDissectName( uniFullName,
3232 uniFullName = uniRemainingPath;
3235 // This component is the server name we are serving
3238 if( RtlCompareUnicodeString( &uniComponentName,
3243 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3244 AFS_TRACE_LEVEL_ERROR,
3245 "AFSParseName (%p) Name %wZ does not have server name\n",
3247 &pIrpSp->FileObject->FileName);
3249 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3253 // Validate this drive letter is actively mapped
3256 if( usDriveIndex > 0 &&
3257 !AFSIsDriveMapped( pIrpSp->FileObject->FileName.Buffer[ usDriveIndex]))
3260 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3261 AFS_TRACE_LEVEL_ERROR,
3262 "AFSParseName (%p) Name %wZ contains invalid drive mapping\n",
3264 &pIrpSp->FileObject->FileName);
3266 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3270 if( FsRtlDoesNameContainWildCards( &uniFullName))
3273 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3274 AFS_TRACE_LEVEL_ERROR,
3275 "AFSParseName (%p) Component %wZ contains wild cards\n",
3279 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3282 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3283 AFS_TRACE_LEVEL_VERBOSE_2,
3284 "AFSParseName (%p) Processing full name %wZ\n",
3288 if( uniFullName.Length > 0 &&
3289 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] == L'\\')
3292 uniFullName.Length -= sizeof( WCHAR);
3296 // Be sure we are online and ready to go
3299 AFSAcquireShared( AFSGlobalRoot->VolumeLock,
3302 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3303 BooleanFlagOn( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3307 // The volume has been taken off line so fail the access
3310 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3311 AFS_TRACE_LEVEL_ERROR,
3312 "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3314 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3315 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3317 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3319 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3322 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3325 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3326 AFS_TRACE_LEVEL_VERBOSE,
3327 "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
3329 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3330 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3332 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3335 if( !NT_SUCCESS( ntStatus))
3338 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3339 AFS_TRACE_LEVEL_ERROR,
3340 "AFSParseName (%p) Failed verification of root Status %08lX\n",
3344 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3346 try_return( ntStatus);
3350 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3352 if( !BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3355 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3356 AFS_TRACE_LEVEL_VERBOSE,
3357 "AFSParseName (%p) Enumerating global root of volume %08lX:%08lX\n",
3359 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3360 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3362 ntStatus = AFSEnumerateGlobalRoot( AuthGroup);
3364 if( !NT_SUCCESS( ntStatus))
3367 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3368 AFS_TRACE_LEVEL_ERROR,
3369 "AFSParseName (%p) Failed enumeraiton of root Status %08lX\n",
3373 try_return( ntStatus);
3378 // Check for the \\Server access and return it as though it were \\Server\Globalroot
3381 if( uniRemainingPath.Buffer == NULL ||
3382 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3383 uniRemainingPath.Buffer[ 0] == L'\\'))
3386 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3387 AFS_TRACE_LEVEL_VERBOSE_2,
3388 "AFSParseName (%p) Returning global root access\n",
3391 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3393 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3394 AFS_TRACE_LEVEL_VERBOSE,
3395 "AFSParseName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3396 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3397 AFSGlobalRoot->DirectoryCB,
3403 FileName->Length = 0;
3404 FileName->MaximumLength = 0;
3405 FileName->Buffer = NULL;
3407 try_return( ntStatus = STATUS_SUCCESS);
3410 *RootFileName = uniFullName;
3413 // Include the starting \ in the root name
3416 if( RootFileName->Buffer[ 0] != L'\\')
3418 RootFileName->Buffer--;
3419 RootFileName->Length += sizeof( WCHAR);
3420 RootFileName->MaximumLength += sizeof( WCHAR);
3424 // Get the 'share' name
3427 FsRtlDissectName( uniFullName,
3431 if( FsRtlDoesNameContainWildCards( &uniFullName))
3434 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3435 AFS_TRACE_LEVEL_ERROR,
3436 "AFSParseName (%p) Component %wZ contains wild cards\n",
3440 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3444 // If this is the ALL access then perform some additional processing
3447 if( uniComponentName.Length == 0 ||
3448 RtlCompareUnicodeString( &uniComponentName,
3456 // If there is nothing else then get out
3459 if( uniRemainingPath.Buffer == NULL ||
3460 uniRemainingPath.Length == 0 ||
3461 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3462 uniRemainingPath.Buffer[ 0] == L'\\'))
3465 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3466 AFS_TRACE_LEVEL_VERBOSE_2,
3467 "AFSParseName (%p) Returning global root access\n",
3470 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3472 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3473 AFS_TRACE_LEVEL_VERBOSE,
3474 "AFSParseName Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
3475 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3476 AFSGlobalRoot->DirectoryCB,
3482 FileName->Length = 0;
3483 FileName->MaximumLength = 0;
3484 FileName->Buffer = NULL;
3486 try_return( ntStatus = STATUS_SUCCESS);
3490 // Process the name again to strip off the ALL portion
3493 uniFullName = uniRemainingPath;
3495 FsRtlDissectName( uniFullName,
3500 // Check for the PIOCtl name
3503 if( RtlCompareUnicodeString( &uniComponentName,
3508 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3509 AFS_TRACE_LEVEL_VERBOSE_2,
3510 "AFSParseName (%p) Returning root PIOCtl access\n",
3513 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3515 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3516 AFS_TRACE_LEVEL_VERBOSE,
3517 "AFSParseName Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
3518 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3519 AFSGlobalRoot->DirectoryCB,
3523 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3527 *FileName = AFSPIOCtlName;
3529 try_return( ntStatus = STATUS_SUCCESS);
3532 else if( (pDirEntry = AFSGetSpecialShareNameEntry( &uniComponentName,
3533 &uniRemainingPath)) != NULL)
3536 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3537 AFS_TRACE_LEVEL_VERBOSE_2,
3538 "AFSParseName (%p) Returning root share name %wZ access\n",
3543 // Add in the full share name to pass back
3546 if( uniRemainingPath.Buffer != NULL)
3550 // This routine strips off the leading slash so add it back in
3553 uniRemainingPath.Buffer--;
3554 uniRemainingPath.Length += sizeof( WCHAR);
3555 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3558 // And the cell name
3561 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3562 uniRemainingPath.Length += uniComponentName.Length;
3563 uniRemainingPath.MaximumLength += uniComponentName.Length;
3565 uniComponentName = uniRemainingPath;
3570 *FileName = uniComponentName;
3572 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3574 *ParentDirectoryCB = pDirEntry;
3576 try_return( ntStatus = STATUS_SUCCESS);
3580 // Determine the 'share' we are accessing
3583 ulCRC = AFSGenerateCRC( &uniComponentName,
3586 AFSAcquireShared( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3589 bReleaseTreeLock = TRUE;
3591 AFSLocateCaseSensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
3595 if( pDirEntry == NULL)
3598 ulCRC = AFSGenerateCRC( &uniComponentName,
3601 AFSLocateCaseInsensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
3605 if( pDirEntry == NULL)
3609 // OK, if this component is a valid short name then try
3610 // a lookup in the short name tree
3613 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3614 RtlIsNameLegalDOS8Dot3( &uniComponentName,
3619 AFSLocateShortNameDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.ShortNameTree,
3624 if( pDirEntry == NULL)
3628 // Check with the service whether it is a valid cell name
3631 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3633 bReleaseTreeLock = FALSE;
3635 ntStatus = AFSCheckCellName( AuthGroup,
3639 if( !NT_SUCCESS( ntStatus))
3643 uniRemainingPath.Length == 0 &&
3644 ntStatus == STATUS_OBJECT_PATH_NOT_FOUND)
3647 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3648 AFS_TRACE_LEVEL_VERBOSE,
3649 "AFSParseName (%p) AFSCheckCellName %wZ returned path not found; ntStatus %08X\n",
3652 STATUS_OBJECT_NAME_NOT_FOUND);
3654 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
3657 try_return( ntStatus);
3663 if( bReleaseTreeLock)
3665 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3670 // Be sure we are starting from the correct volume
3673 if( pDirEntry->ObjectInformation->VolumeCB != AFSGlobalRoot)
3677 // We dropped the global root in the CheckCellName routine which is the
3678 // only way we can be here
3681 pVolumeCB = pDirEntry->ObjectInformation->VolumeCB;
3684 // Init our name array
3687 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
3690 if( pNameArray == NULL)
3693 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3694 AFS_TRACE_LEVEL_VERBOSE,
3695 "AFSParseName (%p) Failed to initialize name array\n",
3698 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3701 ntStatus = AFSInsertNextElement( pNameArray,
3702 pVolumeCB->DirectoryCB);
3707 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3708 AFS_TRACE_LEVEL_VERBOSE,
3709 "AFSParseName (%p) Failed to insert name array element\n",
3712 try_return( ntStatus);
3716 // In this case don't add back in the 'share' name since that is where we are
3717 // starting. Just put the leading slash back in
3720 if( uniRemainingPath.Buffer != NULL)
3723 uniRemainingPath.Buffer--;
3724 uniRemainingPath.Length += sizeof( WCHAR);
3725 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3727 if( uniRemainingPath.Length > sizeof( WCHAR))
3730 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3734 // Pass back the parent being the root of the volume
3737 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3743 // Pass back a root slash
3746 uniRemainingPath = uniComponentName;
3748 uniRemainingPath.Buffer--;
3749 uniRemainingPath.Length = sizeof( WCHAR);
3750 uniRemainingPath.MaximumLength = sizeof( WCHAR);
3753 // This is a root open so pass back no parent
3760 pVolumeCB = AFSGlobalRoot;
3763 // Init our name array
3766 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
3768 if( pNameArray == NULL)
3771 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3772 AFS_TRACE_LEVEL_VERBOSE,
3773 "AFSParseName (%p) Failed to initialize name array\n",
3776 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3780 // Add back in the 'share' portion of the name since we will parse it out on return
3783 if( uniRemainingPath.Buffer != NULL)
3787 // This routine strips off the leading slash so add it back in
3790 uniRemainingPath.Buffer--;
3791 uniRemainingPath.Length += sizeof( WCHAR);
3792 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3794 if( uniRemainingPath.Length > sizeof( WCHAR))
3797 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3801 // And the cell name
3804 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3805 uniRemainingPath.Length += uniComponentName.Length;
3806 uniRemainingPath.MaximumLength += uniComponentName.Length;
3811 uniRemainingPath = uniComponentName;
3815 // And the leading slash again ...
3818 uniRemainingPath.Buffer--;
3819 uniRemainingPath.Length += sizeof( WCHAR);
3820 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3823 // Pass back the parent being the volume root
3826 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3830 // Return the remaining portion as the file name
3833 *FileName = uniRemainingPath;
3835 *ParsedFileName = uniRemainingPath;
3837 *NameArray = pNameArray;
3839 *VolumeCB = pVolumeCB;
3842 // Increment our reference on the volume
3845 lCount = AFSVolumeIncrement( pVolumeCB,
3846 AFS_VOLUME_REFERENCE_PARSE_NAME);
3848 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3849 AFS_TRACE_LEVEL_VERBOSE,
3850 "AFSParseName Increment2 count on global volume %p Cnt %d\n",
3856 if( NT_SUCCESS( ntStatus))
3859 if( *ParentDirectoryCB != NULL)
3862 lCount = InterlockedIncrement( &(*ParentDirectoryCB)->DirOpenReferenceCount);
3864 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3865 AFS_TRACE_LEVEL_VERBOSE,
3866 "AFSParseName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
3867 &(*ParentDirectoryCB)->NameInformation.FileName,
3868 (*ParentDirectoryCB),
3874 if( *VolumeCB != NULL)
3876 ASSERT( (*VolumeCB)->VolumeReferenceCount > 0);
3879 if( ntStatus != STATUS_SUCCESS)
3882 if( pNameArray != NULL)
3885 AFSFreeNameArray( pNameArray);
3894 AFSCheckCellName( IN GUID *AuthGroup,
3895 IN UNICODE_STRING *CellName,
3896 OUT AFSDirectoryCB **ShareDirEntry)
3899 NTSTATUS ntStatus = STATUS_SUCCESS;
3900 UNICODE_STRING uniName;
3901 AFSDirEnumEntry *pDirEnumEntry = NULL;
3902 AFSDirHdr *pDirHdr = &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr;
3903 AFSDirectoryCB *pDirNode = NULL;
3904 UNICODE_STRING uniDirName, uniTargetName;
3905 AFSVolumeCB *pVolumeCB = NULL;
3912 // Look for some default names we will not handle
3915 RtlInitUnicodeString( &uniName,
3918 if( RtlCompareUnicodeString( &uniName,
3923 try_return( ntStatus = STATUS_NO_SUCH_FILE);
3926 RtlInitUnicodeString( &uniName,
3929 if( RtlCompareUnicodeString( &uniName,
3934 try_return( ntStatus = STATUS_NO_SUCH_FILE);
3937 RtlInitUnicodeString( &uniName,
3940 if( RtlCompareUnicodeString( &uniName,
3945 try_return( ntStatus = STATUS_NO_SUCH_FILE);
3948 RtlInitUnicodeString( &uniName,
3951 if( RtlCompareUnicodeString( &uniName,
3956 try_return( ntStatus = STATUS_NO_SUCH_FILE);
3960 // OK, ask the CM about this component name
3963 ntStatus = AFSEvaluateTargetByName( AuthGroup,
3964 &AFSGlobalRoot->ObjectInformation,
3968 if( !NT_SUCCESS( ntStatus))
3971 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3972 AFS_TRACE_LEVEL_WARNING,
3973 "AFSCheckCellName entry %wZ does not exist parent FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3975 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3976 AFSGlobalRoot->ObjectInformation.FileId.Volume,
3977 AFSGlobalRoot->ObjectInformation.FileId.Vnode,
3978 AFSGlobalRoot->ObjectInformation.FileId.Unique,
3981 try_return( ntStatus);
3985 // OK, we have a dir enum entry back so add it to the root node
3988 uniDirName = *CellName;
3990 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
3991 uniTargetName.MaximumLength = uniTargetName.Length;
3992 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
3995 // Is this entry a root volume entry?
3998 if( pDirEnumEntry->FileId.Cell != AFSGlobalRoot->ObjectInformation.FileId.Cell ||
3999 pDirEnumEntry->FileId.Volume != AFSGlobalRoot->ObjectInformation.FileId.Volume)
4003 // Build the root volume entry
4006 ntStatus = AFSBuildRootVolume( AuthGroup,
4007 &pDirEnumEntry->FileId,
4011 // On success returns with a volume reference count held
4014 if( !NT_SUCCESS( ntStatus))
4016 try_return( ntStatus);
4019 *ShareDirEntry = pVolumeCB->DirectoryCB;
4021 lCount = InterlockedIncrement( &pVolumeCB->DirectoryCB->DirOpenReferenceCount);
4023 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4024 AFS_TRACE_LEVEL_VERBOSE,
4025 "AFSCheckCellName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4026 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4027 pVolumeCB->DirectoryCB,
4031 lCount = AFSVolumeDecrement( pVolumeCB,
4032 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4034 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4035 AFS_TRACE_LEVEL_VERBOSE,
4036 "AFSCheckCellName Decrement count on volume %p Cnt %d\n",
4043 lCount = InterlockedIncrement( &pDirHdr->ContentIndex);
4045 pDirNode = AFSInitDirEntry( &AFSGlobalRoot->ObjectInformation,
4051 if( pDirNode == NULL)
4054 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4058 // Init the short name if we have one
4061 if( pDirEnumEntry->ShortNameLength > 0)
4064 pDirNode->NameInformation.ShortNameLength = pDirEnumEntry->ShortNameLength;
4066 RtlCopyMemory( pDirNode->NameInformation.ShortName,
4067 pDirEnumEntry->ShortName,
4068 pDirNode->NameInformation.ShortNameLength);
4071 AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4075 // Insert the node into the name tree
4078 ASSERT( ExIsResourceAcquiredExclusiveLite( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock));
4080 if( pDirHdr->CaseSensitiveTreeHead == NULL)
4083 pDirHdr->CaseSensitiveTreeHead = pDirNode;
4088 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( pDirHdr->CaseSensitiveTreeHead,
4092 AFSDeleteDirEntry( &AFSGlobalRoot->ObjectInformation,
4095 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4097 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4101 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
4103 if( pDirHdr->CaseInsensitiveTreeHead == NULL)
4106 pDirHdr->CaseInsensitiveTreeHead = pDirNode;
4108 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
4113 AFSInsertCaseInsensitiveDirEntry( pDirHdr->CaseInsensitiveTreeHead,
4117 if( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead == NULL)
4120 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead = pDirNode;
4125 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
4127 pDirNode->ListEntry.bLink = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail;
4130 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail = pDirNode;
4132 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
4134 lCount = InterlockedIncrement( &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeCount);
4136 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
4137 AFS_TRACE_LEVEL_VERBOSE,
4138 "AFSCheckCellName Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
4139 &pDirNode->NameInformation.FileName,
4141 AFSGlobalRoot->ObjectInformation.FileId.Cell,
4142 AFSGlobalRoot->ObjectInformation.FileId.Volume,
4143 AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4144 AFSGlobalRoot->ObjectInformation.FileId.Unique);
4146 lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
4148 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4149 AFS_TRACE_LEVEL_VERBOSE,
4150 "AFSCheckCellName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
4151 &pDirNode->NameInformation.FileName,
4156 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4159 // Pass back the dir node
4162 *ShareDirEntry = pDirNode;
4167 if( pDirEnumEntry != NULL)
4170 AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_31_TAG);
4178 AFSBuildMountPointTarget( IN GUID *AuthGroup,
4179 IN AFSDirectoryCB *DirectoryCB,
4180 OUT AFSVolumeCB **TargetVolumeCB)
4183 NTSTATUS ntStatus = STATUS_SUCCESS;
4184 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4185 AFSDirEnumEntry *pDirEntry = NULL;
4186 ULONGLONG ullIndex = 0;
4187 AFSVolumeCB *pVolumeCB = NULL;
4188 AFSFileID stTargetFileID;
4190 BOOLEAN bReleaseVolumeLock = FALSE;
4196 // Loop on each entry, building the chain until we encounter the final target
4199 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4200 AFS_TRACE_LEVEL_VERBOSE_2,
4201 "AFSBuildMountPointTarget Building target directory for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4202 &DirectoryCB->NameInformation.FileName,
4203 DirectoryCB->ObjectInformation->FileId.Cell,
4204 DirectoryCB->ObjectInformation->FileId.Volume,
4205 DirectoryCB->ObjectInformation->FileId.Vnode,
4206 DirectoryCB->ObjectInformation->FileId.Unique);
4209 // Do we need to evaluate the node?
4212 //if( DirectoryCB->ObjectInformation->TargetFileId.Vnode == 0 &&
4213 // DirectoryCB->ObjectInformation->TargetFileId.Unique == 0)
4217 // Go evaluate the current target to get the target fid
4220 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4221 AFS_TRACE_LEVEL_VERBOSE_2,
4222 "AFSBuildMountPointTarget Evaluating target %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4223 &DirectoryCB->NameInformation.FileName,
4224 DirectoryCB->ObjectInformation->FileId.Cell,
4225 DirectoryCB->ObjectInformation->FileId.Volume,
4226 DirectoryCB->ObjectInformation->FileId.Vnode,
4227 DirectoryCB->ObjectInformation->FileId.Unique);
4229 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
4234 if( !NT_SUCCESS( ntStatus))
4237 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4238 AFS_TRACE_LEVEL_ERROR,
4239 "AFSBuildMountPointTarget Failed to evaluate target %wZ Status %08lX\n",
4240 &DirectoryCB->NameInformation.FileName,
4242 try_return( ntStatus);
4245 if( pDirEntry->TargetFileId.Vnode == 0 &&
4246 pDirEntry->TargetFileId.Unique == 0)
4249 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4250 AFS_TRACE_LEVEL_ERROR,
4251 "AFSBuildMountPointTarget Target %wZ FID %08lX-%08lX-%08lX-%08lX service returned zero FID\n",
4252 &DirectoryCB->NameInformation.FileName,
4253 DirectoryCB->ObjectInformation->FileId.Cell,
4254 DirectoryCB->ObjectInformation->FileId.Volume,
4255 DirectoryCB->ObjectInformation->FileId.Vnode,
4256 DirectoryCB->ObjectInformation->FileId.Unique);
4258 try_return( ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED);
4261 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
4264 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
4265 &DirectoryCB->Flags,
4266 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4267 (USHORT)pDirEntry->TargetNameLength);
4269 if( !NT_SUCCESS( ntStatus))
4272 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4274 try_return( ntStatus);
4277 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4279 DirectoryCB->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
4282 stTargetFileID = DirectoryCB->ObjectInformation->TargetFileId;
4285 // Try to locate this FID. First the volume then the
4289 ullIndex = AFSCreateHighIndex( &stTargetFileID);
4291 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4292 AFS_TRACE_LEVEL_VERBOSE,
4293 "AFSBuildMountPointTarget Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4294 &pDevExt->Specific.RDR.VolumeTreeLock,
4295 PsGetCurrentThread());
4297 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4300 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4301 AFS_TRACE_LEVEL_VERBOSE_2,
4302 "AFSBuildMountPointTarget Locating volume for target %I64X\n",
4305 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4307 (AFSBTreeEntry **)&pVolumeCB);
4310 // We can be processing a request for a target that is on a volume
4311 // we have never seen before.
4314 if( pVolumeCB == NULL)
4318 // Locking is held correctly in init routine
4321 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4324 // Go init the root of the volume
4327 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4328 AFS_TRACE_LEVEL_VERBOSE_2,
4329 "AFSBuildMountPointTarget Initializing root for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4330 &DirectoryCB->NameInformation.FileName,
4331 DirectoryCB->ObjectInformation->FileId.Cell,
4332 DirectoryCB->ObjectInformation->FileId.Volume,
4333 DirectoryCB->ObjectInformation->FileId.Vnode,
4334 DirectoryCB->ObjectInformation->FileId.Unique);
4336 ntStatus = AFSInitVolume( AuthGroup,
4338 AFS_VOLUME_REFERENCE_MOUNTPT,
4341 if( !NT_SUCCESS( ntStatus))
4344 try_return( ntStatus);
4348 // pVolumeCB->VolumeLock held exclusive and
4349 // pVolumeCB->VolumeReferenceCount has been incremented
4350 // pVolumeCB->RootFcb == NULL
4353 bReleaseVolumeLock = TRUE;
4359 // AFSInitVolume returns with a VolumeReferenceCount
4360 // obtain one to match
4363 lCount = AFSVolumeIncrement( pVolumeCB,
4364 AFS_VOLUME_REFERENCE_MOUNTPT);
4366 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4367 AFS_TRACE_LEVEL_VERBOSE,
4368 "AFSBuildMountPointTarget Increment count on volume %p Cnt %d\n",
4372 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4375 if( pVolumeCB->RootFcb == NULL)
4378 if ( bReleaseVolumeLock == FALSE)
4381 AFSAcquireExcl( pVolumeCB->VolumeLock,
4384 bReleaseVolumeLock = TRUE;
4388 // Initialize the root fcb for this volume
4391 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4394 if( !NT_SUCCESS( ntStatus))
4397 lCount = AFSVolumeDecrement( pVolumeCB,
4398 AFS_VOLUME_REFERENCE_MOUNTPT);
4400 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4401 AFS_TRACE_LEVEL_VERBOSE,
4402 "AFSBuildMountPoint Decrement count on volume %p Cnt %d\n",
4406 AFSReleaseResource( pVolumeCB->VolumeLock);
4408 try_return( ntStatus);
4412 // Drop the lock acquired above
4415 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4418 if ( bReleaseVolumeLock == TRUE)
4421 AFSReleaseResource( pVolumeCB->VolumeLock);
4424 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4425 AFS_TRACE_LEVEL_VERBOSE_2,
4426 "AFSBuildMountPointTarget Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4427 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4428 pVolumeCB->ObjectInformation.FileId.Cell,
4429 pVolumeCB->ObjectInformation.FileId.Volume,
4430 pVolumeCB->ObjectInformation.FileId.Vnode,
4431 pVolumeCB->ObjectInformation.FileId.Unique);
4433 *TargetVolumeCB = pVolumeCB;
4440 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
4448 AFSBuildRootVolume( IN GUID *AuthGroup,
4449 IN AFSFileID *FileId,
4450 OUT AFSVolumeCB **TargetVolumeCB)
4453 NTSTATUS ntStatus = STATUS_SUCCESS;
4454 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4455 ULONGLONG ullIndex = 0;
4456 AFSVolumeCB *pVolumeCB = NULL;
4458 BOOLEAN bReleaseVolumeLock = FALSE;
4463 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4464 AFS_TRACE_LEVEL_VERBOSE_2,
4465 "AFSBuildRootVolume Building target volume for FID %08lX-%08lX-%08lX-%08lX\n",
4471 ullIndex = AFSCreateHighIndex( FileId);
4473 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4474 AFS_TRACE_LEVEL_VERBOSE,
4475 "AFSBuildRootVolume Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4476 &pDevExt->Specific.RDR.VolumeTreeLock,
4477 PsGetCurrentThread());
4479 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4482 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4483 AFS_TRACE_LEVEL_VERBOSE_2,
4484 "AFSBuildRootVolume Locating volume for target %I64X\n",
4487 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4489 (AFSBTreeEntry **)&pVolumeCB);
4492 // We can be processing a request for a target that is on a volume
4493 // we have never seen before.
4496 if( pVolumeCB == NULL)
4500 // Locking is held correctly in init routine
4503 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4506 // Go init the root of the volume
4509 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4510 AFS_TRACE_LEVEL_VERBOSE_2,
4511 "AFSBuildRootVolume Initializing root for FID %08lX-%08lX-%08lX-%08lX\n",
4517 ntStatus = AFSInitVolume( AuthGroup,
4519 AFS_VOLUME_REFERENCE_BUILD_ROOT,
4522 if( !NT_SUCCESS( ntStatus))
4525 try_return( ntStatus);
4529 // pVolumeCB->VolumeLock is held exclusive
4530 // pVolumeCB->VolumeReferenceCount has been incremented
4531 // pVolumeCB->RootFcb == NULL
4534 bReleaseVolumeLock = TRUE;
4540 // AFSInitVolume returns with a VolumeReferenceCount
4541 // obtain one to match
4544 lCount = AFSVolumeIncrement( pVolumeCB,
4545 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4547 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4548 AFS_TRACE_LEVEL_VERBOSE,
4549 "AFSBuildRootVolume Increment count on volume %p Cnt %d\n",
4553 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4557 if( pVolumeCB->RootFcb == NULL)
4560 if ( bReleaseVolumeLock == FALSE)
4563 AFSAcquireExcl( pVolumeCB->VolumeLock,
4566 bReleaseVolumeLock = TRUE;
4570 // Initialize the root fcb for this volume
4573 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4576 if( !NT_SUCCESS( ntStatus))
4579 lCount = AFSVolumeDecrement( pVolumeCB,
4580 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4582 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4583 AFS_TRACE_LEVEL_VERBOSE,
4584 "AFSBuildRootVolume Decrement count on volume %p Cnt %d\n",
4588 AFSReleaseResource( pVolumeCB->VolumeLock);
4590 try_return( ntStatus);
4594 // Drop the lock acquired above
4597 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4600 if ( bReleaseVolumeLock == TRUE)
4603 AFSReleaseResource( pVolumeCB->VolumeLock);
4606 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4607 AFS_TRACE_LEVEL_VERBOSE_2,
4608 "AFSBuildRootVolume Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4609 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4610 pVolumeCB->ObjectInformation.FileId.Cell,
4611 pVolumeCB->ObjectInformation.FileId.Volume,
4612 pVolumeCB->ObjectInformation.FileId.Vnode,
4613 pVolumeCB->ObjectInformation.FileId.Unique);
4615 *TargetVolumeCB = pVolumeCB;
4626 AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
4627 IN PFILE_OBJECT FileObject,
4628 IN UNICODE_STRING *RemainingPath,
4632 NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
4633 UNICODE_STRING uniReparseName;
4634 UNICODE_STRING uniMUPDeviceName;
4635 UNICODE_STRING uniIOMgrDeviceName;
4636 AFSDirEnumEntry *pDirEntry = NULL;
4642 // Build up the name to reparse
4645 RtlInitUnicodeString( &uniMUPDeviceName,
4648 RtlInitUnicodeString( &uniIOMgrDeviceName,
4651 uniReparseName.Length = 0;
4652 uniReparseName.Buffer = NULL;
4655 // Be sure we have a target name
4658 if( DirEntry->NameInformation.TargetName.Length == 0)
4661 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
4666 if( !NT_SUCCESS( ntStatus) ||
4667 pDirEntry->TargetNameLength == 0)
4670 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4671 AFS_TRACE_LEVEL_ERROR,
4672 "AFSProcessDFSLink EvaluateTargetByID failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4673 &DirEntry->NameInformation.FileName,
4674 DirEntry->ObjectInformation->FileId.Cell,
4675 DirEntry->ObjectInformation->FileId.Volume,
4676 DirEntry->ObjectInformation->FileId.Vnode,
4677 DirEntry->ObjectInformation->FileId.Unique,
4680 if( NT_SUCCESS( ntStatus))
4683 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
4686 try_return( ntStatus);
4690 // Update the target name
4693 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
4696 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
4698 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4699 (USHORT)pDirEntry->TargetNameLength);
4701 if( !NT_SUCCESS( ntStatus))
4704 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4705 AFS_TRACE_LEVEL_ERROR,
4706 "AFSProcessDFSLink UpdateTargetName failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4707 &DirEntry->NameInformation.FileName,
4708 DirEntry->ObjectInformation->FileId.Cell,
4709 DirEntry->ObjectInformation->FileId.Volume,
4710 DirEntry->ObjectInformation->FileId.Vnode,
4711 DirEntry->ObjectInformation->FileId.Unique,
4714 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4716 try_return( ntStatus);
4719 AFSConvertToShared( &DirEntry->NonPaged->Lock);
4723 AFSAcquireShared( &DirEntry->NonPaged->Lock,
4727 uniReparseName.MaximumLength = uniMUPDeviceName.Length +
4729 DirEntry->NameInformation.TargetName.Length +
4732 if( RemainingPath != NULL &&
4733 RemainingPath->Length > 0)
4736 uniReparseName.MaximumLength += RemainingPath->Length;
4740 // Allocate the reparse buffer
4743 uniReparseName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4744 uniReparseName.MaximumLength,
4745 AFS_REPARSE_NAME_TAG);
4747 if( uniReparseName.Buffer == NULL)
4750 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4751 AFS_TRACE_LEVEL_ERROR,
4752 "AFSProcessDFSLink uniReparseName.Buffer == NULL Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4753 &DirEntry->NameInformation.FileName,
4754 DirEntry->ObjectInformation->FileId.Cell,
4755 DirEntry->ObjectInformation->FileId.Volume,
4756 DirEntry->ObjectInformation->FileId.Vnode,
4757 DirEntry->ObjectInformation->FileId.Unique,
4758 STATUS_INSUFFICIENT_RESOURCES);
4760 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4762 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4766 // Start building the name
4769 if ( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\' &&
4770 DirEntry->NameInformation.TargetName.Buffer[ 1] == L':')
4773 RtlCopyMemory( uniReparseName.Buffer,
4774 uniIOMgrDeviceName.Buffer,
4775 uniIOMgrDeviceName.Length);
4777 uniReparseName.Length = uniIOMgrDeviceName.Length;
4782 RtlCopyMemory( uniReparseName.Buffer,
4783 uniMUPDeviceName.Buffer,
4784 uniMUPDeviceName.Length);
4786 uniReparseName.Length = uniMUPDeviceName.Length;
4788 if( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\')
4791 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
4793 uniReparseName.Length += sizeof( WCHAR);
4797 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
4798 DirEntry->NameInformation.TargetName.Buffer,
4799 DirEntry->NameInformation.TargetName.Length);
4801 uniReparseName.Length += DirEntry->NameInformation.TargetName.Length;
4803 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4805 if( RemainingPath != NULL &&
4806 RemainingPath->Length > 0)
4809 if( uniReparseName.Buffer[ (uniReparseName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
4810 RemainingPath->Buffer[ 0] != L'\\')
4813 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
4815 uniReparseName.Length += sizeof( WCHAR);
4818 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
4819 RemainingPath->Buffer,
4820 RemainingPath->Length);
4822 uniReparseName.Length += RemainingPath->Length;
4826 // Update the name in the file object
4829 if( FileObject->FileName.Buffer != NULL)
4832 AFSExFreePoolWithTag( FileObject->FileName.Buffer, 0);
4835 FileObject->FileName = uniReparseName;
4837 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4838 AFS_TRACE_LEVEL_VERBOSE,
4839 "AFSProcessDFSLink Reparsing access to Fcb %wZ FID %08lX-%08lX-%08lX-%08lX to %wZ\n",
4840 &DirEntry->NameInformation.FileName,
4841 DirEntry->ObjectInformation->FileId.Cell,
4842 DirEntry->ObjectInformation->FileId.Volume,
4843 DirEntry->ObjectInformation->FileId.Vnode,
4844 DirEntry->ObjectInformation->FileId.Unique,
4848 // Return status reparse ...
4851 ntStatus = STATUS_REPARSE;
4858 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);