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"
42 AFSLocateNameEntry( IN GUID *AuthGroup,
43 IN PFILE_OBJECT FileObject,
44 IN UNICODE_STRING *RootPathName,
45 IN UNICODE_STRING *ParsedPathName,
46 IN AFSNameArrayHdr *NameArray,
48 OUT AFSVolumeCB **VolumeCB,
49 IN OUT AFSDirectoryCB **ParentDirectoryCB,
50 OUT AFSDirectoryCB **DirectoryCB,
51 OUT PUNICODE_STRING ComponentName)
54 NTSTATUS ntStatus = STATUS_SUCCESS;
55 UNICODE_STRING uniPathName, uniComponentName, uniRemainingPath, uniSearchName, uniFullPathName;
57 AFSDirectoryCB *pDirEntry = NULL, *pParentDirEntry = NULL;
58 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
59 UNICODE_STRING uniSysName;
60 ULONG ulSubstituteIndex = 0;
61 BOOLEAN bSubstituteName = FALSE;
62 AFSNameArrayHdr *pNameArray = NameArray;
63 BOOLEAN bAllocatedSymLinkBuffer = FALSE;
64 UNICODE_STRING uniRelativeName, uniNoOpName;
65 AFSObjectInfoCB *pCurrentObject = NULL;
66 AFSVolumeCB *pCurrentVolume = *VolumeCB;
67 BOOLEAN bReleaseCurrentVolume = TRUE;
68 BOOLEAN bSubstitutedName = FALSE;
73 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
74 AFS_TRACE_LEVEL_VERBOSE_2,
75 "AFSLocateNameEntry (FO: %08lX) Processing full name %wZ\n",
79 RtlInitUnicodeString( &uniSysName,
82 RtlInitUnicodeString( &uniRelativeName,
85 RtlInitUnicodeString( &uniNoOpName,
89 // Cleanup some parameters
92 if( ComponentName != NULL)
95 ComponentName->Length = 0;
96 ComponentName->MaximumLength = 0;
97 ComponentName->Buffer = NULL;
101 // We will parse through the filename, locating the directory nodes until we encounter a cache miss
102 // Starting at the root node
105 pParentDirEntry = NULL;
107 pDirEntry = *ParentDirectoryCB;
109 uniPathName = *ParsedPathName;
111 uniFullPathName = *RootPathName;
113 uniComponentName.Length = uniComponentName.MaximumLength = 0;
114 uniComponentName.Buffer = NULL;
116 uniRemainingPath.Length = uniRemainingPath.MaximumLength = 0;
117 uniRemainingPath.Buffer = NULL;
119 uniSearchName.Length = uniSearchName.MaximumLength = 0;
120 uniSearchName.Buffer = NULL;
122 ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
128 // Check our total link count for this name array
131 if( pNameArray->LinkCount >= (LONG)pDevExt->Specific.RDR.MaxLinkCount)
134 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
137 pCurrentObject = pDirEntry->ObjectInformation;
139 KeQueryTickCount( &pCurrentObject->LastAccessCount);
142 // Check that the directory entry is not deleted or pending delete
145 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
148 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
149 AFS_TRACE_LEVEL_ERROR,
150 "AFSLocateNameEntry (FO: %08lX) Deleted parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
152 &pDirEntry->NameInformation.FileName,
153 pCurrentObject->FileId.Cell,
154 pCurrentObject->FileId.Volume,
155 pCurrentObject->FileId.Vnode,
156 pCurrentObject->FileId.Unique,
159 try_return( ntStatus = STATUS_FILE_DELETED);
162 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
165 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
166 AFS_TRACE_LEVEL_ERROR,
167 "AFSLocateNameEntry (FO: %08lX) Delete pending on %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
169 &pDirEntry->NameInformation.FileName,
170 pCurrentObject->FileId.Cell,
171 pCurrentObject->FileId.Volume,
172 pCurrentObject->FileId.Vnode,
173 pCurrentObject->FileId.Unique,
176 try_return( ntStatus = STATUS_DELETE_PENDING);
180 // Check if the directory requires verification
183 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
184 ( pCurrentObject->FileType != AFS_FILE_TYPE_DIRECTORY ||
185 !AFSIsEnumerationInProcess( pCurrentObject)))
188 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
189 AFS_TRACE_LEVEL_VERBOSE,
190 "AFSLocateNameEntry (FO: %08lX) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
192 &pDirEntry->NameInformation.FileName,
193 pCurrentObject->FileId.Cell,
194 pCurrentObject->FileId.Volume,
195 pCurrentObject->FileId.Vnode,
196 pCurrentObject->FileId.Unique);
198 ntStatus = AFSVerifyEntry( AuthGroup,
201 if( !NT_SUCCESS( ntStatus))
204 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
205 AFS_TRACE_LEVEL_ERROR,
206 "AFSLocateNameEntry (FO: %08lX) Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
208 &pDirEntry->NameInformation.FileName,
209 pCurrentObject->FileId.Cell,
210 pCurrentObject->FileId.Volume,
211 pCurrentObject->FileId.Vnode,
212 pCurrentObject->FileId.Unique,
215 try_return( ntStatus);
220 // Ensure the parent node has been evaluated, if not then go do it now
223 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) ||
224 pCurrentObject->FileType == AFS_FILE_TYPE_UNKNOWN)
227 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
228 AFS_TRACE_LEVEL_VERBOSE,
229 "AFSLocateNameEntry (FO: %08lX) Evaluating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
231 &pDirEntry->NameInformation.FileName,
232 pCurrentObject->FileId.Cell,
233 pCurrentObject->FileId.Volume,
234 pCurrentObject->FileId.Vnode,
235 pCurrentObject->FileId.Unique);
237 ntStatus = AFSEvaluateNode( AuthGroup,
240 if( !NT_SUCCESS( ntStatus))
243 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
244 AFS_TRACE_LEVEL_ERROR,
245 "AFSLocateNameEntry (FO: %08lX) Failed to evaluate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
247 &pDirEntry->NameInformation.FileName,
248 pCurrentObject->FileId.Cell,
249 pCurrentObject->FileId.Volume,
250 pCurrentObject->FileId.Vnode,
251 pCurrentObject->FileId.Unique,
254 try_return( ntStatus);
257 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
261 // If this is a mount point or symlink then go get the real directory node
264 switch( pCurrentObject->FileType)
267 case AFS_FILE_TYPE_SYMLINK:
270 UNICODE_STRING uniTempName;
271 WCHAR *pTmpBuffer = NULL;
275 // Check if the flag is set to NOT evaluate a symlink
276 // and we are done with the parsing
279 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL) &&
280 uniRemainingPath.Length == 0)
284 // Pass back the directory entries
287 *ParentDirectoryCB = pParentDirEntry;
289 *DirectoryCB = pDirEntry;
291 *VolumeCB = pCurrentVolume;
293 *RootPathName = uniFullPathName;
295 try_return( ntStatus);
298 AFSAcquireExcl( &pDirEntry->NonPaged->Lock,
301 if( pDirEntry->NameInformation.TargetName.Length == 0)
305 // We'll reset the DV to ensure we validate the metadata content
308 pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
310 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
312 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
313 AFS_TRACE_LEVEL_VERBOSE,
314 "AFSLocateNameEntry (FO: %08lX) Verifying symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
316 &pDirEntry->NameInformation.FileName,
317 pCurrentObject->FileId.Cell,
318 pCurrentObject->FileId.Volume,
319 pCurrentObject->FileId.Vnode,
320 pCurrentObject->FileId.Unique);
322 ntStatus = AFSVerifyEntry( AuthGroup,
325 if( !NT_SUCCESS( ntStatus))
328 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
329 AFS_TRACE_LEVEL_ERROR,
330 "AFSLocateNameEntry (FO: %08lX) Failed to verify symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
332 &pDirEntry->NameInformation.FileName,
333 pCurrentObject->FileId.Cell,
334 pCurrentObject->FileId.Volume,
335 pCurrentObject->FileId.Vnode,
336 pCurrentObject->FileId.Unique,
339 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
341 try_return( ntStatus);
345 // If the type changed then reprocess this entry
348 if( pCurrentObject->FileType != AFS_FILE_TYPE_SYMLINK)
351 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
358 // If we were given a zero length target name then deny access to the entry
361 if( pDirEntry->NameInformation.TargetName.Length == 0)
364 ntStatus = STATUS_ACCESS_DENIED;
366 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
367 AFS_TRACE_LEVEL_ERROR,
368 "AFSLocateNameEntry (FO: %08lX) Failed to retrieve target name for symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
370 &pDirEntry->NameInformation.FileName,
371 pCurrentObject->FileId.Cell,
372 pCurrentObject->FileId.Volume,
373 pCurrentObject->FileId.Vnode,
374 pCurrentObject->FileId.Unique,
377 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
379 try_return( ntStatus);
382 if( AFSIsRelativeName( &pDirEntry->NameInformation.TargetName))
385 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
386 AFS_TRACE_LEVEL_VERBOSE,
387 "AFSLocateNameEntry (FO: %08lX) Processing relative symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
389 &pDirEntry->NameInformation.TargetName,
390 &pDirEntry->NameInformation.FileName,
391 pCurrentObject->FileId.Cell,
392 pCurrentObject->FileId.Volume,
393 pCurrentObject->FileId.Vnode,
394 pCurrentObject->FileId.Unique);
397 // We'll substitute this name into the current process name
398 // starting at where we sit in the path
401 uniTempName.Length = 0;
402 uniTempName.MaximumLength = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer) +
403 pDirEntry->NameInformation.TargetName.Length +
405 uniRemainingPath.Length;
407 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
408 uniTempName.MaximumLength,
409 AFS_NAME_BUFFER_ONE_TAG);
411 if( uniTempName.Buffer == NULL)
414 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
416 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
420 // We have so first copy in the portion up to the component
424 RtlCopyMemory( uniTempName.Buffer,
425 uniFullPathName.Buffer,
426 (ULONG)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer));
428 uniTempName.Length = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer);
430 if( bAllocatedSymLinkBuffer ||
434 pTmpBuffer = uniFullPathName.Buffer;
437 bAllocatedSymLinkBuffer = TRUE;
440 // Have we parsed this name yet? Better have at least once ...
443 if( uniComponentName.Length == 0)
449 // Copy in the target name ...
452 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
453 pDirEntry->NameInformation.TargetName.Buffer,
454 pDirEntry->NameInformation.TargetName.Length);
456 uniPathName.Buffer = &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)];
458 uniPathName.Length += pDirEntry->NameInformation.TargetName.Length;
459 uniPathName.MaximumLength = uniTempName.MaximumLength;
461 uniTempName.Length += pDirEntry->NameInformation.TargetName.Length;
464 // And now any remaining portion of the name
467 if( uniRemainingPath.Length > 0)
470 if( uniRemainingPath.Buffer[ 0] != L'\\')
473 uniRemainingPath.Buffer--;
474 uniRemainingPath.Length += sizeof( WCHAR);
476 uniPathName.Length += sizeof( WCHAR);
479 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
480 uniRemainingPath.Buffer,
481 uniRemainingPath.Length);
483 uniTempName.Length += uniRemainingPath.Length;
486 uniFullPathName = uniTempName;
488 if( pTmpBuffer != NULL)
491 AFSExFreePool( pTmpBuffer);
494 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
497 // Dereference the current entry ..
500 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
502 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
503 AFS_TRACE_LEVEL_VERBOSE,
504 "AFSLocateNameEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
505 &pDirEntry->NameInformation.FileName,
508 pDirEntry->OpenReferenceCount);
511 // OK, need to back up one entry for the correct parent since the current
512 // entry we are on is the symlink itself
515 pDirEntry = AFSBackupEntry( pNameArray);
518 // Increment our reference on this dir entry
521 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
523 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
524 AFS_TRACE_LEVEL_VERBOSE,
525 "AFSLocateNameEntry Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
526 &pDirEntry->NameInformation.FileName,
529 pDirEntry->OpenReferenceCount);
531 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
534 pParentDirEntry = NULL;
539 pParentDirEntry = AFSGetParentEntry( pNameArray);
541 ASSERT( pParentDirEntry != pDirEntry);
547 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
548 AFS_TRACE_LEVEL_VERBOSE,
549 "AFSLocateNameEntry (FO: %08lX) Processing absolute symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
551 &pDirEntry->NameInformation.TargetName,
552 &pDirEntry->NameInformation.FileName,
553 pCurrentObject->FileId.Cell,
554 pCurrentObject->FileId.Volume,
555 pCurrentObject->FileId.Vnode,
556 pCurrentObject->FileId.Unique);
559 // We'll substitute this name into the current process name
560 // starting at where we sit in the path
563 uniTempName.Length = 0;
564 uniTempName.MaximumLength = pDirEntry->NameInformation.TargetName.Length +
566 uniRemainingPath.Length;
568 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
569 uniTempName.MaximumLength,
570 AFS_NAME_BUFFER_TWO_TAG);
572 if( uniTempName.Buffer == NULL)
575 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
577 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
580 if( bAllocatedSymLinkBuffer ||
584 pTmpBuffer = uniFullPathName.Buffer;
587 bAllocatedSymLinkBuffer = TRUE;
590 // Have we parsed this name yet? Better have at least once ...
593 if( uniComponentName.Length == 0)
599 // Copy in the target name ...
602 RtlCopyMemory( uniTempName.Buffer,
603 pDirEntry->NameInformation.TargetName.Buffer,
604 pDirEntry->NameInformation.TargetName.Length);
606 uniTempName.Length = pDirEntry->NameInformation.TargetName.Length;
609 // And now any remaining portion of the name
612 if( uniRemainingPath.Length > 0)
615 if( uniRemainingPath.Buffer[ 0] != L'\\')
618 uniRemainingPath.Buffer--;
619 uniRemainingPath.Length += sizeof( WCHAR);
622 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
623 uniRemainingPath.Buffer,
624 uniRemainingPath.Length);
626 uniTempName.Length += uniRemainingPath.Length;
629 uniFullPathName = uniTempName;
631 uniPathName = uniTempName;
633 if( pTmpBuffer != NULL)
636 AFSExFreePool( pTmpBuffer);
639 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
642 // If our current volume is not the global root then make it so ...
645 if( pCurrentVolume != AFSGlobalRoot)
648 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
649 AFS_TRACE_LEVEL_VERBOSE,
650 "AFSLocateNameEntry (FO: %08lX) Current volume not global, resetting for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
652 &pDirEntry->NameInformation.FileName,
653 pCurrentObject->FileId.Cell,
654 pCurrentObject->FileId.Volume,
655 pCurrentObject->FileId.Vnode,
656 pCurrentObject->FileId.Unique);
658 InterlockedDecrement( &pCurrentVolume->VolumeReferenceCount);
660 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
661 AFS_TRACE_LEVEL_VERBOSE,
662 "AFSLocateNameEntry Decrement count on volume %08lX Cnt %d\n",
664 pCurrentVolume->VolumeReferenceCount);
666 AFSReleaseResource( pCurrentVolume->VolumeLock);
668 pCurrentVolume = AFSGlobalRoot;
670 AFSAcquireShared( pCurrentVolume->VolumeLock,
673 InterlockedIncrement( &pCurrentVolume->VolumeReferenceCount);
675 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
676 AFS_TRACE_LEVEL_VERBOSE,
677 "AFSLocateNameEntry Increment count on volume %08lX Cnt %d\n",
679 pCurrentVolume->VolumeReferenceCount);
683 // Dereference our current dir entry
686 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
688 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
689 AFS_TRACE_LEVEL_VERBOSE,
690 "AFSLocateNameEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
691 &pDirEntry->NameInformation.FileName,
694 pDirEntry->OpenReferenceCount);
696 pDirEntry = pCurrentVolume->DirectoryCB;
699 // Reference the new dir entry
702 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
704 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
705 AFS_TRACE_LEVEL_VERBOSE,
706 "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
707 &pDirEntry->NameInformation.FileName,
710 pDirEntry->OpenReferenceCount);
713 // Reset the name array
714 // Persist the link count in the name array
717 lLinkCount = pNameArray->LinkCount;
719 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
720 AFS_TRACE_LEVEL_VERBOSE,
721 "AFSLocateNameEntry (FO: %08lX) Resetting name array for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
723 &pDirEntry->NameInformation.FileName,
724 pCurrentObject->FileId.Cell,
725 pCurrentObject->FileId.Volume,
726 pCurrentObject->FileId.Vnode,
727 pCurrentObject->FileId.Unique);
729 AFSResetNameArray( pNameArray,
732 pNameArray->LinkCount = lLinkCount;
735 // Process over the \\<Global root> portion of the name
738 FsRtlDissectName( uniPathName,
742 if( RtlCompareUnicodeString( &uniComponentName,
747 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
748 AFS_TRACE_LEVEL_ERROR,
749 "AFSLocateNameEntry Name %wZ contains invalid server name\n",
753 // The correct response would be STATUS_OBJECT_PATH_INVALID
754 // but that prevents cmd.exe from performing a recursive
755 // directory enumeration when opening a directory entry
756 // that represents a symlink to an invalid path is discovered.
758 try_return( ntStatus = STATUS_OBJECT_PATH_NOT_FOUND);
761 uniPathName = uniRemainingPath;
763 pParentDirEntry = NULL;
767 // Increment our link count
770 InterlockedIncrement( &pNameArray->LinkCount);
775 case AFS_FILE_TYPE_MOUNTPOINT:
779 // Check if the flag is set to NOT evaluate a mount point
780 // and we are done with the parsing
783 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL) &&
784 uniRemainingPath.Length == 0)
788 // Pass back the directory entries
791 *ParentDirectoryCB = pParentDirEntry;
793 *DirectoryCB = pDirEntry;
795 *VolumeCB = pCurrentVolume;
797 *RootPathName = uniFullPathName;
799 try_return( ntStatus);
802 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
803 AFS_TRACE_LEVEL_VERBOSE,
804 "AFSLocateNameEntry (FO: %08lX) Building MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
806 &pDirEntry->NameInformation.FileName,
807 pCurrentObject->FileId.Cell,
808 pCurrentObject->FileId.Volume,
809 pCurrentObject->FileId.Vnode,
810 pCurrentObject->FileId.Unique);
813 // Go retrieve the target entry for this node
814 // Release the current volume cb entry since we would
815 // have lock inversion in the following call
816 // Also decrement the ref count on the volume
819 ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
821 InterlockedDecrement( &pCurrentVolume->VolumeReferenceCount);
823 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
824 AFS_TRACE_LEVEL_VERBOSE,
825 "AFSLocateNameEntry Decrement2 count on volume %08lX Cnt %d\n",
827 pCurrentVolume->VolumeReferenceCount);
829 AFSReleaseResource( pCurrentVolume->VolumeLock);
831 ntStatus = AFSBuildMountPointTarget( AuthGroup,
835 if( !NT_SUCCESS( ntStatus))
838 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
839 AFS_TRACE_LEVEL_ERROR,
840 "AFSLocateNameEntry (FO: %08lX) Failed to build MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
842 &pDirEntry->NameInformation.FileName,
843 pCurrentObject->FileId.Cell,
844 pCurrentObject->FileId.Volume,
845 pCurrentObject->FileId.Vnode,
846 pCurrentObject->FileId.Unique,
850 // We already decremented the current volume above
853 bReleaseCurrentVolume = FALSE;
855 try_return( ntStatus = STATUS_ACCESS_DENIED);
858 ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
860 ASSERT( ExIsResourceAcquiredLite( pCurrentVolume->VolumeLock));
863 // Replace the current name for the mp with the volume root of the target
866 AFSReplaceCurrentElement( pNameArray,
867 pCurrentVolume->DirectoryCB);
870 // We want to restart processing here on the new parent ...
871 // Deref and ref count the entries
874 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
876 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
877 AFS_TRACE_LEVEL_VERBOSE,
878 "AFSLocateNameEntry Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
879 &pDirEntry->NameInformation.FileName,
882 pDirEntry->OpenReferenceCount);
884 pDirEntry = pCurrentVolume->DirectoryCB;
886 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
888 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
889 AFS_TRACE_LEVEL_VERBOSE,
890 "AFSLocateNameEntry Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
891 &pDirEntry->NameInformation.FileName,
894 pDirEntry->OpenReferenceCount);
896 pParentDirEntry = NULL;
899 // Increment our link count
902 InterlockedIncrement( &pNameArray->LinkCount);
907 case AFS_FILE_TYPE_DFSLINK:
910 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL))
914 // Pass back the directory entries
917 *ParentDirectoryCB = pParentDirEntry;
919 *DirectoryCB = pDirEntry;
921 *VolumeCB = pCurrentVolume;
923 *RootPathName = uniFullPathName;
925 try_return( ntStatus);
929 // This is a DFS link so we need to update the file name and return STATUS_REPARSE to the
930 // system for it to reevaluate it
933 if( FileObject != NULL)
936 ntStatus = AFSProcessDFSLink( pDirEntry,
945 // This is where we have been re-entered from an NP evaluation call via the BuildBranch()
949 ntStatus = STATUS_INVALID_PARAMETER;
952 if( ntStatus != STATUS_SUCCESS &&
953 ntStatus != STATUS_REPARSE)
956 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
957 AFS_TRACE_LEVEL_ERROR,
958 "AFSLocateNameEntry (FO: %08lX) Failed to process DFSLink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
960 &pDirEntry->NameInformation.FileName,
961 pCurrentObject->FileId.Cell,
962 pCurrentObject->FileId.Volume,
963 pCurrentObject->FileId.Vnode,
964 pCurrentObject->FileId.Unique,
968 try_return( ntStatus);
971 case AFS_FILE_TYPE_UNKNOWN:
972 case AFS_FILE_TYPE_INVALID:
976 // Something was not processed ...
979 try_return( ntStatus = STATUS_ACCESS_DENIED);
982 } /* end of switch */
985 // If the parent is not initialized then do it now
988 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
989 !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
992 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
993 AFS_TRACE_LEVEL_VERBOSE,
994 "AFSLocateNameEntry (FO: %08lX) Enumerating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
996 &pDirEntry->NameInformation.FileName,
997 pCurrentObject->FileId.Cell,
998 pCurrentObject->FileId.Volume,
999 pCurrentObject->FileId.Vnode,
1000 pCurrentObject->FileId.Unique);
1002 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1005 if( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1008 ntStatus = AFSEnumerateDirectory( AuthGroup,
1012 if( !NT_SUCCESS( ntStatus))
1015 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1017 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1018 AFS_TRACE_LEVEL_ERROR,
1019 "AFSLocateNameEntry (FO: %08lX) Failed to enumerate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1021 &pDirEntry->NameInformation.FileName,
1022 pCurrentObject->FileId.Cell,
1023 pCurrentObject->FileId.Volume,
1024 pCurrentObject->FileId.Vnode,
1025 pCurrentObject->FileId.Unique,
1028 try_return( ntStatus);
1031 SetFlag( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1034 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1036 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1039 if( uniPathName.Length > 0)
1042 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1043 AFS_TRACE_LEVEL_ERROR,
1044 "AFSLocateNameEntry (FO: %08lX) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1046 &pDirEntry->NameInformation.FileName,
1047 pCurrentObject->FileId.Cell,
1048 pCurrentObject->FileId.Volume,
1049 pCurrentObject->FileId.Vnode,
1050 pCurrentObject->FileId.Unique);
1052 // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1053 // one of the components of the path is not a directory. However, returning
1054 // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1055 // Instead IIS insists on treating the target file as if it is a directory containing
1056 // a potential web.config file. NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1057 // AFS will follow suit.
1059 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1064 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1065 AFS_TRACE_LEVEL_VERBOSE,
1066 "AFSLocateNameEntry (FO: %08lX) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1068 &pDirEntry->NameInformation.FileName,
1069 pCurrentObject->FileId.Cell,
1070 pCurrentObject->FileId.Volume,
1071 pCurrentObject->FileId.Vnode,
1072 pCurrentObject->FileId.Unique);
1075 // Pass back the directory entries
1078 *ParentDirectoryCB = pParentDirEntry;
1080 *DirectoryCB = pDirEntry;
1082 *VolumeCB = pCurrentVolume;
1084 *RootPathName = uniFullPathName;
1087 try_return( ntStatus);
1091 // If we are at the end of the processing, set our returned information and get out
1094 if( uniPathName.Length == 0)
1097 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1098 AFS_TRACE_LEVEL_VERBOSE,
1099 "AFSLocateNameEntry (FO: %08lX) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1101 &pDirEntry->NameInformation.FileName,
1102 pCurrentObject->FileId.Cell,
1103 pCurrentObject->FileId.Volume,
1104 pCurrentObject->FileId.Vnode,
1105 pCurrentObject->FileId.Unique);
1108 // Pass back the directory entries
1111 *ParentDirectoryCB = pParentDirEntry;
1113 *DirectoryCB = pDirEntry;
1115 *VolumeCB = pCurrentVolume;
1117 *RootPathName = uniFullPathName;
1119 try_return( ntStatus);
1123 // We may have returned to the top of the while( TRUE)
1125 if( bSubstituteName &&
1126 uniSearchName.Buffer != NULL)
1129 AFSExFreePool( uniSearchName.Buffer);
1131 bSubstituteName = FALSE;
1133 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1134 uniSearchName.Buffer = NULL;
1137 ulSubstituteIndex = 1;
1139 ntStatus = STATUS_SUCCESS;
1142 // Get the next component name
1145 FsRtlDissectName( uniPathName,
1150 // Check for the . and .. in the path
1153 if( RtlCompareUnicodeString( &uniComponentName,
1158 uniPathName = uniRemainingPath;
1163 if( RtlCompareUnicodeString( &uniComponentName,
1168 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1169 AFS_TRACE_LEVEL_VERBOSE,
1170 "AFSLocateNameEntry (FO: %08lX) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1172 &pDirEntry->NameInformation.FileName,
1173 pCurrentObject->FileId.Cell,
1174 pCurrentObject->FileId.Volume,
1175 pCurrentObject->FileId.Vnode,
1176 pCurrentObject->FileId.Unique);
1179 // Need to back up one entry in the name array
1182 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
1184 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1185 AFS_TRACE_LEVEL_VERBOSE,
1186 "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1187 &pDirEntry->NameInformation.FileName,
1190 pDirEntry->OpenReferenceCount);
1192 pDirEntry = AFSBackupEntry( NameArray);
1194 if( pDirEntry == NULL)
1197 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1198 AFS_TRACE_LEVEL_ERROR,
1199 "AFSLocateNameEntry AFSBackupEntry failed\n");
1201 try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1204 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1206 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1209 pParentDirEntry = NULL;
1214 pParentDirEntry = AFSGetParentEntry( pNameArray);
1216 ASSERT( pParentDirEntry != pDirEntry);
1219 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1220 AFS_TRACE_LEVEL_VERBOSE,
1221 "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1222 &pDirEntry->NameInformation.FileName,
1225 pDirEntry->OpenReferenceCount);
1227 uniPathName = uniRemainingPath;
1233 // Update our pointers
1236 pParentDirEntry = pDirEntry;
1240 uniSearchName = uniComponentName;
1242 while( pDirEntry == NULL)
1246 // If the SearchName contains @SYS then we perform the substitution.
1247 // If there is no substitution we give up.
1250 if( !bSubstituteName &&
1251 FsRtlIsNameInExpression( &uniSysName,
1257 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1258 AFS_TRACE_LEVEL_VERBOSE_2,
1259 "AFSLocateNameEntry (FO: %08lX) Processing @SYS substitution for %wZ Index %08lX\n",
1264 ntStatus = AFSSubstituteSysName( &uniComponentName,
1268 if ( NT_SUCCESS( ntStatus))
1271 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1272 AFS_TRACE_LEVEL_VERBOSE_2,
1273 "AFSLocateNameEntry (FO: %08lX) Located substitution %wZ for %wZ Index %08lX\n",
1280 // Go reparse the name again
1283 bSubstituteName = TRUE;
1285 ulSubstituteIndex++; // For the next entry, if needed
1287 continue; // while( pDirEntry == NULL)
1292 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1293 AFS_TRACE_LEVEL_ERROR,
1294 "AFSLocateNameEntry (FO: %08lX) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1300 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1304 // Pass back the directory entries
1307 *ParentDirectoryCB = pParentDirEntry;
1309 *DirectoryCB = NULL;
1311 *VolumeCB = pCurrentVolume;
1313 if( ComponentName != NULL)
1316 *ComponentName = uniComponentName;
1319 *RootPathName = uniFullPathName;
1323 // We can't possibly have a pDirEntry since the lookup failed
1325 try_return( ntStatus);
1330 // Generate the CRC on the node and perform a case sensitive lookup
1333 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1334 AFS_TRACE_LEVEL_VERBOSE_2,
1335 "AFSLocateNameEntry (FO: %08lX) Searching for entry %wZ case sensitive\n",
1339 ulCRC = AFSGenerateCRC( &uniSearchName,
1342 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1345 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1349 if( pDirEntry == NULL)
1353 // Missed so perform a case insensitive lookup
1356 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1357 AFS_TRACE_LEVEL_VERBOSE_2,
1358 "AFSLocateNameEntry (FO: %08lX) Searching for entry %wZ case insensitive\n",
1362 ulCRC = AFSGenerateCRC( &uniSearchName,
1365 AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1369 if( pDirEntry == NULL)
1373 // OK, if this component is a valid short name then try
1374 // a lookup in the short name tree
1377 if( RtlIsNameLegalDOS8Dot3( &uniSearchName,
1382 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1383 AFS_TRACE_LEVEL_VERBOSE_2,
1384 "AFSLocateNameEntry (FO: %08lX) Searching for entry %wZ short name\n",
1388 AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1393 if( pDirEntry == NULL)
1397 // If we substituted a name then reset our search name and try again
1400 if( bSubstituteName)
1403 AFSExFreePool( uniSearchName.Buffer);
1405 uniSearchName = uniComponentName;
1407 bSubstituteName = FALSE;
1409 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1411 continue; // while( pDirEntry == NULL)
1414 if( uniRemainingPath.Length > 0)
1417 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1422 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1424 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1425 AFS_TRACE_LEVEL_VERBOSE,
1426 "AFSLocateNameEntry (FO: %08lX) Returning name not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1429 pCurrentObject->FileId.Cell,
1430 pCurrentObject->FileId.Volume,
1431 pCurrentObject->FileId.Vnode,
1432 pCurrentObject->FileId.Unique);
1435 // Pass back the directory entries
1438 *ParentDirectoryCB = pParentDirEntry;
1440 *DirectoryCB = NULL;
1442 *VolumeCB = pCurrentVolume;
1444 if( ComponentName != NULL)
1447 *ComponentName = uniComponentName;
1450 *RootPathName = uniFullPathName;
1453 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1456 // Node name not found so get out
1459 try_return( ntStatus); // while( pDirEntry == NULL)
1466 // Here we have a match on the case insensitive lookup for the name. If there
1467 // Is more than one link entry for this node then fail the lookup request
1470 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1471 pDirEntry->CaseInsensitiveList.fLink != NULL)
1474 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1476 try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1481 if( pDirEntry != NULL)
1485 // If the verify flag is set on the parent and the current entry is deleted
1486 // revalidate the parent and search again.
1489 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1490 BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1493 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1495 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1496 AFS_TRACE_LEVEL_VERBOSE,
1497 "AFSLocateNameEntry (FO: %08lX) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1499 &pParentDirEntry->NameInformation.FileName,
1500 pParentDirEntry->ObjectInformation->FileId.Cell,
1501 pParentDirEntry->ObjectInformation->FileId.Volume,
1502 pParentDirEntry->ObjectInformation->FileId.Vnode,
1503 pParentDirEntry->ObjectInformation->FileId.Unique);
1505 ntStatus = AFSVerifyEntry( AuthGroup,
1508 if( !NT_SUCCESS( ntStatus))
1511 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1512 AFS_TRACE_LEVEL_ERROR,
1513 "AFSLocateNameEntry (FO: %08lX) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1515 &pParentDirEntry->NameInformation.FileName,
1516 pParentDirEntry->ObjectInformation->FileId.Cell,
1517 pParentDirEntry->ObjectInformation->FileId.Volume,
1518 pParentDirEntry->ObjectInformation->FileId.Vnode,
1519 pParentDirEntry->ObjectInformation->FileId.Unique,
1522 try_return( ntStatus);
1525 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1526 AFS_TRACE_LEVEL_VERBOSE,
1527 "AFSLocateNameEntry (FO: %08lX) Reprocessing component %wZ in parent %wZ\n",
1530 &pParentDirEntry->NameInformation.FileName);
1539 // Increment our dir entry ref count
1542 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1544 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1545 AFS_TRACE_LEVEL_VERBOSE,
1546 "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1547 &pDirEntry->NameInformation.FileName,
1550 pDirEntry->OpenReferenceCount);
1553 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1555 } // End while( pDirEntry == NULL)
1558 // If we have a dirEntry for this component, perform some basic validation on it
1561 if( pDirEntry != NULL &&
1562 BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1565 pCurrentObject = pDirEntry->ObjectInformation;
1567 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1568 AFS_TRACE_LEVEL_ERROR,
1569 "AFSLocateNameEntry (FO: %08lX) Deleted parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1571 &pDirEntry->NameInformation.FileName,
1572 pCurrentObject->FileId.Cell,
1573 pCurrentObject->FileId.Volume,
1574 pCurrentObject->FileId.Vnode,
1575 pCurrentObject->FileId.Unique);
1578 // This entry was deleted through the invalidation call back so perform cleanup
1582 ASSERT( pCurrentObject->ParentObjectInformation != NULL);
1584 AFSAcquireExcl( pCurrentObject->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1587 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1590 if( InterlockedDecrement( &pDirEntry->OpenReferenceCount) == 0)
1593 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1594 AFS_TRACE_LEVEL_VERBOSE,
1595 "AFSLocateNameEntry Deleting dir entry %08lX (%08lX) for %wZ\n",
1598 &pDirEntry->NameInformation.FileName);
1601 // Remove and delete the directory entry from the parent list
1604 AFSDeleteDirEntry( pCurrentObject->ParentObjectInformation,
1607 if( pCurrentObject->ObjectReferenceCount == 0)
1610 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
1613 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1614 AFS_TRACE_LEVEL_VERBOSE,
1615 "AFSLocateNameEntry Removing object %08lX from volume tree\n",
1618 AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
1619 &pCurrentObject->TreeEntry);
1621 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
1628 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1629 AFS_TRACE_LEVEL_VERBOSE,
1630 "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
1632 &pDirEntry->NameInformation.FileName);
1634 SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
1636 AFSRemoveNameEntry( pCurrentObject->ParentObjectInformation,
1640 AFSReleaseResource( pCurrentObject->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1642 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
1645 // We deleted the dir entry so check if there is any remaining portion
1646 // of the name to process.
1649 if( uniRemainingPath.Length > 0)
1651 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1656 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1658 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1659 AFS_TRACE_LEVEL_VERBOSE,
1660 "AFSLocateNameEntry (FO: %08lX) Returning name not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1663 pCurrentObject->FileId.Cell,
1664 pCurrentObject->FileId.Volume,
1665 pCurrentObject->FileId.Vnode,
1666 pCurrentObject->FileId.Unique);
1669 // Pass back the directory entries
1672 *ParentDirectoryCB = pParentDirEntry;
1674 *DirectoryCB = NULL;
1676 *VolumeCB = pCurrentVolume;
1678 if( ComponentName != NULL)
1681 *ComponentName = uniComponentName;
1684 *RootPathName = uniFullPathName;
1688 if( ntStatus != STATUS_SUCCESS)
1691 try_return( ntStatus);
1695 // Decrement the previous parent
1698 InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
1700 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1701 AFS_TRACE_LEVEL_VERBOSE,
1702 "AFSLocateNameEntry Decrement5 count on Parent %wZ DE %p Ccb %p Cnt %d\n",
1703 &pParentDirEntry->NameInformation.FileName,
1706 pParentDirEntry->OpenReferenceCount);
1709 // If we ended up substituting a name in the component then update
1710 // the full path and update the pointers
1713 if( bSubstituteName)
1716 BOOLEAN bRelativeOpen = FALSE;
1718 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1719 AFS_TRACE_LEVEL_VERBOSE_2,
1720 "AFSLocateNameEntry (FO: %08lX) Substituting %wZ into %wZ Index %08lX\n",
1726 if( FileObject != NULL &&
1727 FileObject->RelatedFileObject != NULL)
1730 bRelativeOpen = TRUE;
1734 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
1735 // and free the prior Buffer contents but only if the fourth
1736 // parameter is TRUE.
1739 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
1744 bAllocatedSymLinkBuffer ||
1747 if( !NT_SUCCESS( ntStatus))
1750 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1751 AFS_TRACE_LEVEL_ERROR,
1752 "AFSLocateNameEntry (FO: %08lX) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
1759 try_return( ntStatus);
1763 // We have substituted a name into the buffer so if we do this again for this
1764 // path, we need to free up the buffer we allocated.
1767 bSubstitutedName = TRUE;
1771 // Update the search parameters
1774 uniPathName = uniRemainingPath;
1777 // Check if the is a SymLink entry but has no Target FileID or Name. In this
1778 // case it might be a DFS Link so let's go and evaluate it to be sure
1781 if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
1782 pCurrentObject->TargetFileId.Vnode == 0 &&
1783 pCurrentObject->TargetFileId.Unique == 0 &&
1784 pDirEntry->NameInformation.TargetName.Length == 0)
1787 ntStatus = AFSValidateSymLink( AuthGroup,
1790 if( !NT_SUCCESS( ntStatus))
1793 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1794 AFS_TRACE_LEVEL_ERROR,
1795 "AFSLocateNameEntry (FO: %08lX) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1797 &pDirEntry->NameInformation.FileName,
1798 pCurrentObject->FileId.Cell,
1799 pCurrentObject->FileId.Volume,
1800 pCurrentObject->FileId.Vnode,
1801 pCurrentObject->FileId.Unique,
1804 try_return( ntStatus);
1809 // Update the name array
1812 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1813 AFS_TRACE_LEVEL_VERBOSE,
1814 "AFSLocateNameEntry (FO: %08lX) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1816 &pDirEntry->NameInformation.FileName,
1817 pCurrentObject->FileId.Cell,
1818 pCurrentObject->FileId.Volume,
1819 pCurrentObject->FileId.Vnode,
1820 pCurrentObject->FileId.Unique);
1822 ntStatus = AFSInsertNextElement( pNameArray,
1825 if( !NT_SUCCESS( ntStatus))
1828 try_return( ntStatus);
1834 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1835 AFS_TRACE_LEVEL_VERBOSE,
1836 "AFSLocateNameEntry (FO: %08lX) Completed processing %wZ Status %08lX\n",
1841 if( ( !NT_SUCCESS( ntStatus) &&
1842 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
1843 ntStatus == STATUS_REPARSE)
1846 if( pDirEntry != NULL)
1849 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
1851 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1852 AFS_TRACE_LEVEL_VERBOSE,
1853 "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
1854 &pDirEntry->NameInformation.FileName,
1857 pDirEntry->OpenReferenceCount);
1859 else if( pParentDirEntry != NULL)
1862 InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
1864 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1865 AFS_TRACE_LEVEL_VERBOSE,
1866 "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
1867 &pParentDirEntry->NameInformation.FileName,
1870 pParentDirEntry->OpenReferenceCount);
1873 if( bReleaseCurrentVolume)
1876 ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
1878 ASSERT( ExIsResourceAcquiredLite( pCurrentVolume->VolumeLock));
1880 InterlockedDecrement( &pCurrentVolume->VolumeReferenceCount);
1882 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1883 AFS_TRACE_LEVEL_VERBOSE,
1884 "AFSLocateNameEntry Decrement3 count on volume %08lX Cnt %d\n",
1886 pCurrentVolume->VolumeReferenceCount);
1888 AFSReleaseResource( pCurrentVolume->VolumeLock);
1891 if( RootPathName->Buffer != uniFullPathName.Buffer)
1894 AFSExFreePool( uniFullPathName.Buffer);
1900 if( *ParentDirectoryCB != NULL)
1903 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1904 AFS_TRACE_LEVEL_VERBOSE,
1905 "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
1906 &(*ParentDirectoryCB)->NameInformation.FileName,
1909 (*ParentDirectoryCB)->OpenReferenceCount);
1912 if( *DirectoryCB != NULL)
1915 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1916 AFS_TRACE_LEVEL_VERBOSE,
1917 "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
1918 &(*DirectoryCB)->NameInformation.FileName,
1921 (*DirectoryCB)->OpenReferenceCount);
1925 if( bSubstituteName &&
1926 uniSearchName.Buffer != NULL)
1929 AFSExFreePool( uniSearchName.Buffer);
1937 AFSCreateDirEntry( IN GUID *AuthGroup,
1938 IN AFSObjectInfoCB *ParentObjectInfo,
1939 IN AFSDirectoryCB *ParentDirCB,
1940 IN PUNICODE_STRING FileName,
1941 IN PUNICODE_STRING ComponentName,
1942 IN ULONG Attributes,
1943 IN OUT AFSDirectoryCB **DirEntry)
1946 NTSTATUS ntStatus = STATUS_SUCCESS;
1947 AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
1948 UNICODE_STRING uniShortName;
1949 LARGE_INTEGER liFileSize = {0,0};
1954 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1955 AFS_TRACE_LEVEL_VERBOSE_2,
1956 "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
1957 &ParentDirCB->NameInformation.FileName,
1958 ParentObjectInfo->FileId.Cell,
1959 ParentObjectInfo->FileId.Volume,
1960 ParentObjectInfo->FileId.Vnode,
1961 ParentObjectInfo->FileId.Unique,
1966 // OK, before inserting the node into the parent tree, issue
1967 // the request to the service for node creation
1968 // We will need to drop the lock on the parent node since the create
1969 // could cause a callback into the file system to invalidate it's cache
1972 ntStatus = AFSNotifyFileCreate( AuthGroup,
1980 // If the returned status is STATUS_REPARSE then the entry exists
1981 // and we raced, get out.
1983 if( ntStatus == STATUS_REPARSE)
1986 *DirEntry = pDirNode;
1988 try_return( ntStatus = STATUS_SUCCESS);
1991 if( !NT_SUCCESS( ntStatus))
1994 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1995 AFS_TRACE_LEVEL_ERROR,
1996 "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
1997 &ParentDirCB->NameInformation.FileName,
1998 ParentObjectInfo->FileId.Cell,
1999 ParentObjectInfo->FileId.Volume,
2000 ParentObjectInfo->FileId.Vnode,
2001 ParentObjectInfo->FileId.Unique,
2006 try_return( ntStatus);
2009 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2013 // Before attempting to insert the new entry, check if we need to validate the parent
2016 if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2019 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2020 AFS_TRACE_LEVEL_VERBOSE,
2021 "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2022 &ParentDirCB->NameInformation.FileName,
2023 ParentObjectInfo->FileId.Cell,
2024 ParentObjectInfo->FileId.Volume,
2025 ParentObjectInfo->FileId.Vnode,
2026 ParentObjectInfo->FileId.Unique);
2028 ntStatus = AFSVerifyEntry( AuthGroup,
2031 if( !NT_SUCCESS( ntStatus))
2034 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2035 AFS_TRACE_LEVEL_ERROR,
2036 "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2037 &ParentDirCB->NameInformation.FileName,
2038 ParentObjectInfo->FileId.Cell,
2039 ParentObjectInfo->FileId.Volume,
2040 ParentObjectInfo->FileId.Vnode,
2041 ParentObjectInfo->FileId.Unique,
2044 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2046 try_return( ntStatus);
2051 // Check for the entry in the event we raced with some other thread
2054 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2055 (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2058 if( pExistingDirNode != NULL)
2061 AFSDeleteDirEntry( ParentObjectInfo,
2064 InterlockedIncrement( &pExistingDirNode->OpenReferenceCount);
2066 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2067 AFS_TRACE_LEVEL_VERBOSE,
2068 "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2069 &pExistingDirNode->NameInformation.FileName,
2071 pExistingDirNode->OpenReferenceCount);
2073 *DirEntry = pExistingDirNode;
2075 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2077 try_return( ntStatus = STATUS_SUCCESS);
2080 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2081 AFS_TRACE_LEVEL_VERBOSE_2,
2082 "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2083 &ParentDirCB->NameInformation.FileName,
2084 ParentObjectInfo->FileId.Cell,
2085 ParentObjectInfo->FileId.Volume,
2086 ParentObjectInfo->FileId.Vnode,
2087 ParentObjectInfo->FileId.Unique,
2091 // Insert the directory node
2094 AFSInsertDirectoryNode( ParentObjectInfo,
2098 InterlockedIncrement( &pDirNode->OpenReferenceCount);
2100 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2101 AFS_TRACE_LEVEL_VERBOSE,
2102 "AFSCreateDirEntry Increment2 count on %wZ DE %p Cnt %d\n",
2103 &pDirNode->NameInformation.FileName,
2105 pDirNode->OpenReferenceCount);
2108 // Pass back the dir entry
2111 *DirEntry = pDirNode;
2113 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2124 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2125 IN AFSDirectoryCB *DirEntry,
2126 IN BOOLEAN InsertInEnumList)
2132 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2135 // Insert the node into the directory node tree
2138 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2139 AFS_TRACE_LEVEL_VERBOSE,
2140 "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2142 &DirEntry->NameInformation.FileName);
2144 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2146 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2149 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2151 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2152 AFS_TRACE_LEVEL_VERBOSE,
2153 "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2155 &DirEntry->NameInformation.FileName);
2160 AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2163 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2164 AFS_TRACE_LEVEL_VERBOSE,
2165 "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2167 &DirEntry->NameInformation.FileName);
2170 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2173 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2175 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2177 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2178 AFS_TRACE_LEVEL_VERBOSE,
2179 "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2181 &DirEntry->NameInformation.FileName);
2186 AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2189 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2190 AFS_TRACE_LEVEL_VERBOSE,
2191 "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2193 &DirEntry->NameInformation.FileName);
2197 // Into the shortname tree
2200 if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2203 if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2206 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2208 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2209 AFS_TRACE_LEVEL_VERBOSE,
2210 "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2212 &DirEntry->NameInformation.FileName);
2214 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2219 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2222 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2223 AFS_TRACE_LEVEL_VERBOSE,
2224 "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2226 &DirEntry->NameInformation.FileName);
2230 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2232 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2233 AFS_TRACE_LEVEL_VERBOSE,
2234 "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2236 &DirEntry->NameInformation.FileName);
2241 if( InsertInEnumList)
2245 // And insert the node into the directory list
2248 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2249 AFS_TRACE_LEVEL_VERBOSE,
2250 "AFSInsertDirectoryNode Inserting entry %08lX %wZ FID %08lX-%08lX-%08lX-%08lXStatus %08lX\n",
2252 &DirEntry->NameInformation.FileName,
2253 DirEntry->ObjectInformation->FileId.Cell,
2254 DirEntry->ObjectInformation->FileId.Volume,
2255 DirEntry->ObjectInformation->FileId.Vnode,
2256 DirEntry->ObjectInformation->FileId.Unique);
2258 if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2261 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2266 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2268 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2271 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2273 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2275 InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2277 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2278 AFS_TRACE_LEVEL_VERBOSE,
2279 "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2280 &DirEntry->NameInformation.FileName,
2281 ParentObjectInfo->Specific.Directory.DirectoryNodeCount,
2282 ParentObjectInfo->FileId.Cell,
2283 ParentObjectInfo->FileId.Volume,
2284 ParentObjectInfo->FileId.Vnode,
2285 ParentObjectInfo->FileId.Unique);
2293 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2294 IN AFSDirectoryCB *DirEntry)
2297 NTSTATUS ntStatus = STATUS_SUCCESS;
2302 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2303 AFS_TRACE_LEVEL_VERBOSE,
2304 "AFSDeleteDirEntry Deleting dir entry in parent %08lX Entry %08lX %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2307 &DirEntry->NameInformation.FileName,
2308 DirEntry->ObjectInformation->FileId.Cell,
2309 DirEntry->ObjectInformation->FileId.Volume,
2310 DirEntry->ObjectInformation->FileId.Vnode,
2311 DirEntry->ObjectInformation->FileId.Unique);
2313 AFSRemoveDirNodeFromParent( ParentObjectInfo,
2318 // Free up the name buffer if it was reallocated
2321 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2324 AFSExFreePool( DirEntry->NameInformation.FileName.Buffer);
2327 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2330 AFSExFreePool( DirEntry->NameInformation.TargetName.Buffer);
2334 // Dereference the object for this dir entry
2337 ASSERT( DirEntry->ObjectInformation->ObjectReferenceCount > 0);
2339 if( InterlockedDecrement( &DirEntry->ObjectInformation->ObjectReferenceCount) == 0)
2341 SetFlag( DirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2344 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2345 AFS_TRACE_LEVEL_VERBOSE,
2346 "AFSDeleteDirEntry Decrement count on object %08lX Cnt %d\n",
2347 DirEntry->ObjectInformation,
2348 DirEntry->ObjectInformation->ObjectReferenceCount);
2350 ExDeleteResourceLite( &DirEntry->NonPaged->Lock);
2352 AFSExFreePool( DirEntry->NonPaged);
2355 // Free up the dir entry
2358 AFSExFreePool( DirEntry);
2365 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2366 IN AFSDirectoryCB *DirEntry,
2367 IN BOOLEAN RemoveFromEnumList)
2370 NTSTATUS ntStatus = STATUS_SUCCESS;
2376 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2378 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2379 AFS_TRACE_LEVEL_VERBOSE,
2380 "AFSRemoveDirNodeFromParent Removing DirEntry %08lX %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %08lX\n",
2382 &DirEntry->NameInformation.FileName,
2383 DirEntry->ObjectInformation->FileId.Cell,
2384 DirEntry->ObjectInformation->FileId.Volume,
2385 DirEntry->ObjectInformation->FileId.Vnode,
2386 DirEntry->ObjectInformation->FileId.Unique,
2389 if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2392 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2393 AFS_TRACE_LEVEL_VERBOSE,
2394 "AFSRemoveDirNodeFromParent Removing DirEntry %08lX name %wZ\n",
2396 &DirEntry->NameInformation.FileName);
2398 AFSRemoveNameEntry( ParentObjectInfo,
2404 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2405 AFS_TRACE_LEVEL_VERBOSE,
2406 "AFSRemoveDirNodeFromParent DE %p for %wZ NOT removing entry due to flag set\n",
2408 &DirEntry->NameInformation.FileName);
2412 if( RemoveFromEnumList &&
2413 BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST))
2417 // And remove the entry from the enumeration list
2420 if( DirEntry->ListEntry.fLink == NULL)
2423 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = (AFSDirectoryCB *)DirEntry->ListEntry.bLink;
2428 ((AFSDirectoryCB *)DirEntry->ListEntry.fLink)->ListEntry.bLink = DirEntry->ListEntry.bLink;
2431 if( DirEntry->ListEntry.bLink == NULL)
2434 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = (AFSDirectoryCB *)DirEntry->ListEntry.fLink;
2439 ((AFSDirectoryCB *)DirEntry->ListEntry.bLink)->ListEntry.fLink = DirEntry->ListEntry.fLink;
2442 ASSERT( ParentObjectInfo->Specific.Directory.DirectoryNodeCount > 0);
2444 InterlockedDecrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2446 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2448 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2449 AFS_TRACE_LEVEL_VERBOSE,
2450 "AFSRemoveDirNodeFromParent Removing entry %wZ Dec Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2451 &DirEntry->NameInformation.FileName,
2452 ParentObjectInfo->Specific.Directory.DirectoryNodeCount,
2453 ParentObjectInfo->FileId.Cell,
2454 ParentObjectInfo->FileId.Volume,
2455 ParentObjectInfo->FileId.Vnode,
2456 ParentObjectInfo->FileId.Unique);
2458 DirEntry->ListEntry.fLink = NULL;
2459 DirEntry->ListEntry.bLink = NULL;
2467 AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
2468 IN OUT PUNICODE_STRING TargetFileName)
2471 NTSTATUS ntStatus = STATUS_SUCCESS;
2472 UNICODE_STRING uniFileName;
2478 // We will process backwards from the end of the name looking
2479 // for the first \ we encounter
2482 uniFileName.Length = FileName->Length;
2483 uniFileName.MaximumLength = FileName->MaximumLength;
2485 uniFileName.Buffer = FileName->Buffer;
2490 if( uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
2494 // Subtract one more character off of the filename if it is not the root
2497 if( uniFileName.Length > sizeof( WCHAR))
2500 uniFileName.Length -= sizeof( WCHAR);
2504 // Now build up the target name
2507 TargetFileName->Length = FileName->Length - uniFileName.Length;
2510 // If we are not on the root then fixup the name
2513 if( uniFileName.Length > sizeof( WCHAR))
2516 TargetFileName->Length -= sizeof( WCHAR);
2518 TargetFileName->Buffer = &uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) + 1];
2523 TargetFileName->Buffer = &uniFileName.Buffer[ uniFileName.Length/sizeof( WCHAR)];
2527 // Fixup the passed back filename length
2530 FileName->Length = uniFileName.Length;
2532 TargetFileName->MaximumLength = TargetFileName->Length;
2537 uniFileName.Length -= sizeof( WCHAR);
2545 AFSParseName( IN PIRP Irp,
2547 OUT PUNICODE_STRING FileName,
2548 OUT PUNICODE_STRING ParsedFileName,
2549 OUT PUNICODE_STRING RootFileName,
2550 OUT ULONG *ParseFlags,
2551 OUT AFSVolumeCB **VolumeCB,
2552 OUT AFSDirectoryCB **ParentDirectoryCB,
2553 OUT AFSNameArrayHdr **NameArray)
2556 NTSTATUS ntStatus = STATUS_SUCCESS;
2557 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2558 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2559 UNICODE_STRING uniFullName, uniComponentName, uniRemainingPath;
2561 AFSDirectoryCB *pDirEntry = NULL, *pShareDirEntry = NULL, *pTargetDirEntry = NULL;
2562 USHORT usIndex = 0, usDriveIndex = 0;
2563 AFSCcb *pRelatedCcb = NULL;
2564 AFSNameArrayHdr *pNameArray = NULL, *pRelatedNameArray = NULL;
2565 USHORT usComponentIndex = 0;
2566 USHORT usComponentLength = 0;
2567 AFSVolumeCB *pVolumeCB = NULL;
2568 AFSFcb *pRelatedFcb = NULL;
2569 BOOLEAN bReleaseTreeLock = FALSE;
2570 BOOLEAN bIsAllShare = FALSE;
2576 // Indicate we are opening a root ...
2579 *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
2581 if( pIrpSp->FileObject->RelatedFileObject != NULL)
2584 pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
2586 pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
2588 pRelatedNameArray = pRelatedCcb->NameArray;
2590 uniFullName = pIrpSp->FileObject->FileName;
2592 ASSERT( pRelatedFcb != NULL);
2595 // No wild cards in the name
2598 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2599 AFS_TRACE_LEVEL_VERBOSE_2,
2600 "AFSParseName (%08lX) Relative open for %wZ FID %08lX-%08lX-%08lX-%08lX component %wZ\n",
2602 &pRelatedCcb->DirectoryCB->NameInformation.FileName,
2603 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Cell,
2604 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Volume,
2605 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
2606 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Unique,
2609 if( FsRtlDoesNameContainWildCards( &uniFullName))
2612 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2613 AFS_TRACE_LEVEL_ERROR,
2614 "AFSParseName (%08lX) Component %wZ contains wild cards\n",
2618 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
2621 pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
2623 pDirEntry = pRelatedCcb->DirectoryCB;
2625 *FileName = pIrpSp->FileObject->FileName;
2628 // Grab the root node exclusive before returning
2631 AFSAcquireExcl( pVolumeCB->VolumeLock,
2634 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
2635 BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
2639 // The volume has been taken off line so fail the access
2642 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2643 AFS_TRACE_LEVEL_ERROR,
2644 "AFSParseName (%08lX) Volume %08lX:%08lX OFFLINE/INVALID\n",
2646 pVolumeCB->ObjectInformation.FileId.Cell,
2647 pVolumeCB->ObjectInformation.FileId.Volume);
2649 AFSReleaseResource( pVolumeCB->VolumeLock);
2651 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
2654 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
2657 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2658 AFS_TRACE_LEVEL_VERBOSE,
2659 "AFSParseName (%08lX) Verifying root of volume %08lX:%08lX\n",
2661 pVolumeCB->ObjectInformation.FileId.Cell,
2662 pVolumeCB->ObjectInformation.FileId.Volume);
2664 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
2667 if( !NT_SUCCESS( ntStatus))
2670 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2671 AFS_TRACE_LEVEL_ERROR,
2672 "AFSParseName (%08lX) Failed verification of root Status %08lX\n",
2676 AFSReleaseResource( pVolumeCB->VolumeLock);
2678 try_return( ntStatus);
2682 AFSConvertToShared( pVolumeCB->VolumeLock);
2684 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
2687 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2688 AFS_TRACE_LEVEL_VERBOSE,
2689 "AFSParseName (%08lX) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2691 &pDirEntry->NameInformation.FileName,
2692 pDirEntry->ObjectInformation->FileId.Cell,
2693 pDirEntry->ObjectInformation->FileId.Volume,
2694 pDirEntry->ObjectInformation->FileId.Vnode,
2695 pDirEntry->ObjectInformation->FileId.Unique);
2697 ntStatus = AFSVerifyEntry( AuthGroup,
2700 if( !NT_SUCCESS( ntStatus))
2703 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2704 AFS_TRACE_LEVEL_VERBOSE,
2705 "AFSParseName (%08lX) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2707 &pDirEntry->NameInformation.FileName,
2708 pDirEntry->ObjectInformation->FileId.Cell,
2709 pDirEntry->ObjectInformation->FileId.Volume,
2710 pDirEntry->ObjectInformation->FileId.Vnode,
2711 pDirEntry->ObjectInformation->FileId.Unique,
2714 AFSReleaseResource( pVolumeCB->VolumeLock);
2716 try_return( ntStatus);
2721 // Create our full path name buffer
2724 uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length +
2726 pIrpSp->FileObject->FileName.Length +
2729 uniFullName.Length = 0;
2731 uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2732 uniFullName.MaximumLength,
2733 AFS_NAME_BUFFER_THREE_TAG);
2735 if( uniFullName.Buffer == NULL)
2738 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2739 AFS_TRACE_LEVEL_ERROR,
2740 "AFSParseName (%08lX) Failed to allocate full name buffer\n",
2743 AFSReleaseResource( pVolumeCB->VolumeLock);
2745 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2748 RtlZeroMemory( uniFullName.Buffer,
2749 uniFullName.MaximumLength);
2751 RtlCopyMemory( uniFullName.Buffer,
2752 pRelatedCcb->FullFileName.Buffer,
2753 pRelatedCcb->FullFileName.Length);
2755 uniFullName.Length = pRelatedCcb->FullFileName.Length;
2757 usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
2759 usComponentLength = pIrpSp->FileObject->FileName.Length;
2761 if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
2762 pIrpSp->FileObject->FileName.Length > 0 &&
2763 pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
2764 pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
2767 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
2769 uniFullName.Length += sizeof( WCHAR);
2771 usComponentLength += sizeof( WCHAR);
2774 if( pIrpSp->FileObject->FileName.Length > 0)
2777 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
2778 pIrpSp->FileObject->FileName.Buffer,
2779 pIr
\epSp->FileObject->FileName.Length);
2781 uniFullName.Length += pIrpSp->FileObject->FileName.Length;
2784 *RootFileName = uniFullName;
2787 // We populate up to the current parent
2790 if( pRelatedNameArray == NULL)
2794 // Init and populate our name array
2797 pNameArray = AFSInitNameArray( NULL,
2800 if( pNameArray == NULL)
2803 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2804 AFS_TRACE_LEVEL_VERBOSE,
2805 "AFSParseName (%08lX) Failed to initialize name array\n",
2808 AFSExFreePool( uniFullName.Buffer);
2810 AFSReleaseResource( pVolumeCB->VolumeLock);
2812 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2815 ntStatus = AFSPopulateNameArray( pNameArray,
2817 pRelatedCcb->DirectoryCB);
2823 // Init and populate our name array
2826 pNameArray = AFSInitNameArray( NULL,
2827 pRelatedNameArray->MaxElementCount);
2829 if( pNameArray == NULL)
2832 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2833 AFS_TRACE_LEVEL_VERBOSE,
2834 "AFSParseName (%08lX) Failed to initialize name array\n",
2837 AFSExFreePool( uniFullName.Buffer);
2839 AFSReleaseResource( pVolumeCB->VolumeLock);
2841 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2844 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
2846 pRelatedCcb->DirectoryCB);
2849 if( !NT_SUCCESS( ntStatus))
2852 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2853 AFS_TRACE_LEVEL_VERBOSE,
2854 "AFSParseName (%08lX) Failed to populate name array\n",
2857 AFSExFreePool( uniFullName.Buffer);
2859 AFSReleaseResource( pVolumeCB->VolumeLock);
2861 try_return( ntStatus);
2864 ParsedFileName->Length = usComponentLength;
2865 ParsedFileName->MaximumLength = uniFullName.MaximumLength;
2867 ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
2870 // Indicate to caller that RootFileName must be freed
2873 SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
2875 *NameArray = pNameArray;
2877 *VolumeCB = pVolumeCB;
2880 // Increment our volume reference count
2883 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2885 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2886 AFS_TRACE_LEVEL_VERBOSE,
2887 "AFSParseName Increment count on volume %08lX Cnt %d\n",
2889 pVolumeCB->VolumeReferenceCount);
2891 *ParentDirectoryCB = pDirEntry;
2893 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
2895 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2896 AFS_TRACE_LEVEL_VERBOSE,
2897 "AFSParseName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
2898 &pDirEntry->NameInformation.FileName,
2901 pDirEntry->OpenReferenceCount);
2903 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2904 AFS_TRACE_LEVEL_VERBOSE_2,
2905 "AFSParseName (%08lX) Returning full name %wZ\n",
2909 try_return( ntStatus);
2913 // No wild cards in the name
2916 uniFullName = pIrpSp->FileObject->FileName;
2918 if( FsRtlDoesNameContainWildCards( &uniFullName) ||
2919 uniFullName.Length < AFSServerName.Length)
2922 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2923 AFS_TRACE_LEVEL_ERROR,
2924 "AFSParseName (%08lX) Name %wZ contains wild cards or too short\n",
2928 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
2932 // The name is a fully qualified name. Parse out the server/share names and
2933 // point to the root qualified name
2934 // First thing is to locate the server name
2937 FsRtlDissectName( uniFullName,
2941 uniFullName = uniRemainingPath;
2944 // This component is the server name we are serving
2947 if( RtlCompareUnicodeString( &uniComponentName,
2953 // Drive letter based name?
2956 uniFullName = pIrpSp->FileObject->FileName;
2958 while( usIndex < uniFullName.Length/sizeof( WCHAR))
2961 if( uniFullName.Buffer[ usIndex] == L':')
2964 uniFullName.Buffer = &uniFullName.Buffer[ usIndex + 2];
2966 uniFullName.Length -= (usIndex + 2) * sizeof( WCHAR);
2968 usDriveIndex = usIndex - 1;
2977 // Do we have the right server name now?
2980 FsRtlDissectName( uniFullName,
2984 uniFullName = uniRemainingPath;
2987 // This component is the server name we are serving
2990 if( RtlCompareUnicodeString( &uniComponentName,
2995 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2996 AFS_TRACE_LEVEL_ERROR,
2997 "AFSParseName (%08lX) Name %wZ does not have server name\n",
2999 &pIrpSp->FileObject->FileName);
3001 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3005 // Validate this drive letter is actively mapped
3008 if( usDriveIndex > 0 &&
3009 !AFSIsDriveMapped( pIrpSp->FileObject->FileName.Buffer[ usDriveIndex]))
3012 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3013 AFS_TRACE_LEVEL_ERROR,
3014 "AFSParseName (%08lX) Name %wZ contains invalid drive mapping\n",
3016 &pIrpSp->FileObject->FileName);
3018 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3022 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3023 AFS_TRACE_LEVEL_VERBOSE_2,
3024 "AFSParseName (%08lX) Processing full name %wZ\n",
3028 if( uniFullName.Length > 0 &&
3029 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] == L'\\')
3032 uniFullName.Length -= sizeof( WCHAR);
3036 // Be sure we are online and ready to go
3039 AFSAcquireExcl( AFSGlobalRoot->VolumeLock,
3042 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3043 BooleanFlagOn( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3047 // The volume has been taken off line so fail the access
3050 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3051 AFS_TRACE_LEVEL_ERROR,
3052 "AFSParseName (%08lX) Volume %08lX:%08lX OFFLINE/INVALID\n",
3054 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3055 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3057 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3059 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3062 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3065 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3066 AFS_TRACE_LEVEL_VERBOSE,
3067 "AFSParseName (%08lX) Verifying root of volume %08lX:%08lX\n",
3069 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3070 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3072 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3075 if( !NT_SUCCESS( ntStatus))
3078 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3079 AFS_TRACE_LEVEL_ERROR,
3080 "AFSParseName (%08lX) Failed verification of root Status %08lX\n",
3084 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3086 try_return( ntStatus);
3090 if( !BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3093 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3094 AFS_TRACE_LEVEL_VERBOSE,
3095 "AFSParseName (%08lX) Enumerating global root of volume %08lX:%08lX\n",
3097 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3098 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3100 ntStatus = AFSEnumerateGlobalRoot( AuthGroup);
3102 if( !NT_SUCCESS( ntStatus))
3105 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3106 AFS_TRACE_LEVEL_ERROR,
3107 "AFSParseName (%08lX) Failed enumeraiton of root Status %08lX\n",
3111 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3113 try_return( ntStatus);
3118 // Check for the \\Server access and return it as though it where \\Server\Globalroot
3121 if( uniRemainingPath.Buffer == NULL ||
3122 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3123 uniRemainingPath.Buffer[ 0] == L'\\'))
3126 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3127 AFS_TRACE_LEVEL_VERBOSE_2,
3128 "AFSParseName (%08lX) Returning global root access\n",
3131 InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3133 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3134 AFS_TRACE_LEVEL_VERBOSE,
3135 "AFSParseName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3136 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3137 AFSGlobalRoot->DirectoryCB,
3139 AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3141 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3145 FileName->Length = 0;
3146 FileName->MaximumLength = 0;
3147 FileName->Buffer = NULL;
3149 try_return( ntStatus = STATUS_SUCCESS);
3152 *RootFileName = uniFullName;
3155 // Include the starting \ in the root name
3158 if( RootFileName->Buffer[ 0] != L'\\')
3160 RootFileName->Buffer--;
3161 RootFileName->Length += sizeof( WCHAR);
3162 RootFileName->MaximumLength += sizeof( WCHAR);
3166 // Get the 'share' name
3169 FsRtlDissectName( uniFullName,
3174 // If this is the ALL access then perform some additional processing
3177 if( RtlCompareUnicodeString( &uniComponentName,
3185 // If there is nothing else then get out
3188 if( uniRemainingPath.Buffer == NULL ||
3189 uniRemainingPath.Length == 0 ||
3190 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3191 uniRemainingPath.Buffer[ 0] == L'\\'))
3194 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3195 AFS_TRACE_LEVEL_VERBOSE_2,
3196 "AFSParseName (%08lX) Returning global root access\n",
3199 InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3201 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3202 AFS_TRACE_LEVEL_VERBOSE,
3203 "AFSParseName Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
3204 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3205 AFSGlobalRoot->DirectoryCB,
3207 AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3209 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3213 FileName->Length = 0;
3214 FileName->MaximumLength = 0;
3215 FileName->Buffer = NULL;
3217 try_return( ntStatus = STATUS_SUCCESS);
3221 // Process the name again to strip off the ALL portion
3224 uniFullName = uniRemainingPath;
3226 FsRtlDissectName( uniFullName,
3231 // Check for the PIOCtl name
3234 if( RtlCompareUnicodeString( &uniComponentName,
3239 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3240 AFS_TRACE_LEVEL_VERBOSE_2,
3241 "AFSParseName (%08lX) Returning root PIOCtl access\n",
3244 InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3246 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3247 AFS_TRACE_LEVEL_VERBOSE,
3248 "AFSParseName Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
3249 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3250 AFSGlobalRoot->DirectoryCB,
3252 AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3254 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3256 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3260 *FileName = AFSPIOCtlName;
3262 try_return( ntStatus = STATUS_SUCCESS);
3265 else if( (pDirEntry = AFSGetSpecialShareNameEntry( &uniComponentName,
3266 &uniRemainingPath)) != NULL)
3269 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3270 AFS_TRACE_LEVEL_VERBOSE_2,
3271 "AFSParseName (%08lX) Returning root share name %wZ access\n",
3275 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3278 // Add in the full share name to pass back
3281 if( uniRemainingPath.Buffer != NULL)
3285 // This routine strips off the leading slash so add it back in
3288 uniRemainingPath.Buffer--;
3289 uniRemainingPath.Length += sizeof( WCHAR);
3290 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3293 // And the cell name
3296 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3297 uniRemainingPath.Length += uniComponentName.Length;
3298 uniRemainingPath.MaximumLength += uniComponentName.Length;
3300 uniComponentName = uniRemainingPath;
3305 *FileName = uniComponentName;
3307 *ParentDirectoryCB = pDirEntry;
3309 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3311 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
3313 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3314 AFS_TRACE_LEVEL_VERBOSE,
3315 "AFSParseName Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
3316 &pDirEntry->NameInformation.FileName,
3319 pDirEntry->OpenReferenceCount);
3321 try_return( ntStatus = STATUS_SUCCESS);
3325 // Determine the 'share' we are accessing
3328 ulCRC = AFSGenerateCRC( &uniComponentName,
3331 AFSAcquireShared( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3334 bReleaseTreeLock = TRUE;
3336 AFSLocateCaseSensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
3340 if( pDirEntry == NULL)
3343 ulCRC = AFSGenerateCRC( &uniComponentName,
3346 AFSLocateCaseInsensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
3350 if( pDirEntry == NULL)
3354 // OK, if this component is a valid short name then try
3355 // a lookup in the short name tree
3358 if( RtlIsNameLegalDOS8Dot3( &uniComponentName,
3363 AFSLocateShortNameDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.ShortNameTree,
3368 if( pDirEntry == NULL)
3372 // Check with the service whether it is a valid cell name
3375 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3377 bReleaseTreeLock = FALSE;
3379 ntStatus = AFSCheckCellName( AuthGroup,
3383 if( !NT_SUCCESS( ntStatus))
3385 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3388 uniRemainingPath.Length == 0 &&
3389 ntStatus == STATUS_OBJECT_PATH_NOT_FOUND)
3392 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
3395 try_return( ntStatus);
3401 if( bReleaseTreeLock)
3403 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3407 // Be sure we are starting from the correct volume
3410 if( pDirEntry->ObjectInformation->VolumeCB != AFSGlobalRoot)
3414 // We dropped the global root in the CheckCellName routine which is the
3415 // only way we can be here
3418 pVolumeCB = pDirEntry->ObjectInformation->VolumeCB;
3421 // In this case don't add back in the 'share' name since that is where we are
3422 // starting. Just put the leading slash back in
3425 if( uniRemainingPath.Buffer != NULL)
3428 uniRemainingPath.Buffer--;
3429 uniRemainingPath.Length += sizeof( WCHAR);
3430 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3432 if( uniRemainingPath.Length > sizeof( WCHAR))
3435 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3439 // Pass back the parent being the root of the volume
3442 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3448 // Pass back a root slash
3451 uniRemainingPath = uniComponentName;
3453 uniRemainingPath.Buffer--;
3454 uniRemainingPath.Length = sizeof( WCHAR);
3455 uniRemainingPath.MaximumLength = sizeof( WCHAR);
3458 // This is a root open so pass back no parent
3461 *ParentDirectoryCB = NULL;
3467 pVolumeCB = AFSGlobalRoot;
3470 // Add back in the 'share' portion of the name since we will parse it out on return
3473 if( uniRemainingPath.Buffer != NULL)
3477 // This routine strips off the leading slash so add it back in
3480 uniRemainingPath.Buffer--;
3481 uniRemainingPath.Length += sizeof( WCHAR);
3482 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3484 if( uniRemainingPath.Length > sizeof( WCHAR))
3487 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3491 // And the cell name
3494 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3495 uniRemainingPath.Length += uniComponentName.Length;
3496 uniRemainingPath.MaximumLength += uniComponentName.Length;
3501 uniRemainingPath = uniComponentName;
3505 // And the leading slash again ...
3508 uniRemainingPath.Buffer--;
3509 uniRemainingPath.Length += sizeof( WCHAR);
3510 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3512 InterlockedIncrement( &pVolumeCB->DirectoryCB->OpenReferenceCount);
3514 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3515 AFS_TRACE_LEVEL_VERBOSE,
3516 "AFSParseName Increment6 count on %wZ DE %p Ccb %p Cnt %d\n",
3517 &pVolumeCB->DirectoryCB->NameInformation.FileName,
3518 pVolumeCB->DirectoryCB,
3520 pVolumeCB->DirectoryCB->OpenReferenceCount);
3523 // Pass back the parent being the volume root
3526 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3530 // We only need the volume shared at this point
3533 AFSConvertToShared( pVolumeCB->VolumeLock);
3536 // Init our name array
3539 pNameArray = AFSInitNameArray( pVolumeCB->DirectoryCB,
3542 if( pNameArray == NULL)
3545 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3546 AFS_TRACE_LEVEL_VERBOSE,
3547 "AFSParseName (%08lX) Failed to initialize name array\n",
3550 AFSReleaseResource( pVolumeCB->VolumeLock);
3552 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3556 // Return the remaining portion as the file name
3559 *FileName = uniRemainingPath;
3561 *ParsedFileName = uniRemainingPath;
3563 *NameArray = pNameArray;
3565 *VolumeCB = pVolumeCB;
3568 // Increment our reference on the volume
3571 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
3573 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3574 AFS_TRACE_LEVEL_VERBOSE,
3575 "AFSParseName Increment2 count on global volume %08lX Cnt %d\n",
3577 pVolumeCB->VolumeReferenceCount);
3581 if( NT_SUCCESS( ntStatus))
3584 if( *ParentDirectoryCB != NULL)
3587 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3588 AFS_TRACE_LEVEL_VERBOSE,
3589 "AFSParseName Count on %wZ DE %p Ccb %p Cnt %d\n",
3590 &(*ParentDirectoryCB)->NameInformation.FileName,
3593 (*ParentDirectoryCB)->OpenReferenceCount);
3597 if( *VolumeCB != NULL)
3600 ASSERT( (*VolumeCB)->VolumeReferenceCount > 1);
3603 if( ntStatus != STATUS_SUCCESS)
3606 if( pNameArray != NULL)
3609 AFSFreeNameArray( pNameArray);
3618 AFSCheckCellName( IN GUID *AuthGroup,
3619 IN UNICODE_STRING *CellName,
3620 OUT AFSDirectoryCB **ShareDirEntry)
3623 NTSTATUS ntStatus = STATUS_SUCCESS;
3624 UNICODE_STRING uniName;
3626 AFSDirEnumEntry *pDirEnumEntry = NULL;
3627 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3628 AFSDirHdr *pDirHdr = &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr;
3629 AFSDirectoryCB *pDirNode = NULL;
3630 UNICODE_STRING uniDirName, uniTargetName;
3631 AFSVolumeCB *pVolumeCB = NULL;
3637 // Look for some default names we will not handle
3640 RtlInitUnicodeString( &uniName,
3643 if( RtlCompareUnicodeString( &uniName,
3648 try_return( ntStatus = STATUS_NO_SUCH_FILE);
3651 RtlInitUnicodeString( &uniName,
3654 if( RtlCompareUnicodeString( &uniName,
3659 try_return( ntStatus = STATUS_NO_SUCH_FILE);
3662 RtlInitUnicodeString( &uniName,
3665 if( RtlCompareUnicodeString( &uniName,
3670 try_return( ntStatus = STATUS_NO_SUCH_FILE);
3673 RtlInitUnicodeString( &uniName,
3676 if( RtlCompareUnicodeString( &uniName,
3681 try_return( ntStatus = STATUS_NO_SUCH_FILE);
3685 // OK, ask the CM about this component name
3688 stFileID = AFSGlobalRoot->ObjectInformation.FileId;
3690 ntStatus = AFSEvaluateTargetByName( AuthGroup,
3695 if( !NT_SUCCESS( ntStatus))
3698 try_return( ntStatus);
3702 // OK, we have a dir enum entry back so add it to the root node
3705 uniDirName = *CellName;
3707 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
3708 uniTargetName.MaximumLength = uniTargetName.Length;
3709 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
3712 // Is this entry a root volume entry?
3715 if( pDirEnumEntry->FileId.Cell != AFSGlobalRoot->ObjectInformation.FileId.Cell ||
3716 pDirEnumEntry->FileId.Volume != AFSGlobalRoot->ObjectInformation.FileId.Volume)
3720 // We have the global root on entry so drop it now
3723 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3726 // Build the root volume entry
3729 ntStatus = AFSBuildRootVolume( AuthGroup,
3730 &pDirEnumEntry->FileId,
3733 if( !NT_SUCCESS( ntStatus))
3737 // On failure this routine is expecting to hold the global root
3740 AFSAcquireShared( AFSGlobalRoot->VolumeLock,
3743 try_return( ntStatus);
3746 *ShareDirEntry = pVolumeCB->DirectoryCB;
3748 InterlockedIncrement( &pVolumeCB->DirectoryCB->OpenReferenceCount);
3750 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3751 AFS_TRACE_LEVEL_VERBOSE,
3752 "AFSCheckCellName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
3753 &pVolumeCB->DirectoryCB->NameInformation.FileName,
3754 pVolumeCB->DirectoryCB,
3756 pVolumeCB->DirectoryCB->OpenReferenceCount);
3758 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
3763 pDirNode = AFSInitDirEntry( &AFSGlobalRoot->ObjectInformation,
3767 (ULONG)InterlockedIncrement( &pDirHdr->ContentIndex));
3769 if( pDirNode == NULL)
3772 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3776 // Init the short name if we have one
3779 if( pDirEnumEntry->ShortNameLength > 0)
3782 pDirNode->NameInformation.ShortNameLength = pDirEnumEntry->ShortNameLength;
3784 RtlCopyMemory( pDirNode->NameInformation.ShortName,
3785 pDirEnumEntry->ShortName,
3786 pDirNode->NameInformation.ShortNameLength);
3789 AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3793 // Insert the node into the name tree
3796 ASSERT( ExIsResourceAcquiredExclusiveLite( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock));
3798 if( pDirHdr->CaseSensitiveTreeHead == NULL)
3801 pDirHdr->CaseSensitiveTreeHead = pDirNode;
3806 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( pDirHdr->CaseSensitiveTreeHead,
3810 AFSDeleteDirEntry( &AFSGlobalRoot->ObjectInformation,
3813 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3815 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3819 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
3821 if( pDirHdr->CaseInsensitiveTreeHead == NULL)
3824 pDirHdr->CaseInsensitiveTreeHead = pDirNode;
3826 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
3831 AFSInsertCaseInsensitiveDirEntry( pDirHdr->CaseInsensitiveTreeHead,
3835 if( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead == NULL)
3838 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead = pDirNode;
3843 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
3845 pDirNode->ListEntry.bLink = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail;
3848 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail = pDirNode;
3850 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
3852 InterlockedIncrement( &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeCount);
3854 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
3855 AFS_TRACE_LEVEL_VERBOSE,
3856 "AFSCheckCellName Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
3857 &pDirNode->NameInformation.FileName,
3858 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeCount,
3859 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3860 AFSGlobalRoot->ObjectInformation.FileId.Volume,
3861 AFSGlobalRoot->ObjectInformation.FileId.Vnode,
3862 AFSGlobalRoot->ObjectInformation.FileId.Unique);
3864 InterlockedIncrement( &pDirNode->OpenReferenceCount);
3866 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3867 AFS_TRACE_LEVEL_VERBOSE,
3868 "AFSCheckCellName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3869 &pDirNode->NameInformation.FileName,
3872 pDirNode->OpenReferenceCount);
3874 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3877 // Pass back the dir node
3880 *ShareDirEntry = pDirNode;
3885 if( pDirEnumEntry != NULL)
3888 AFSExFreePool( pDirEnumEntry);
3896 AFSBuildMountPointTarget( IN GUID *AuthGroup,
3897 IN AFSDirectoryCB *DirectoryCB,
3898 OUT AFSVolumeCB **TargetVolumeCB)
3901 NTSTATUS ntStatus = STATUS_SUCCESS;
3902 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
3903 AFSDirEnumEntry *pDirEntry = NULL;
3904 AFSDirectoryCB *pDirNode = NULL;
3905 UNICODE_STRING uniDirName, uniTargetName;
3906 ULONGLONG ullIndex = 0;
3907 AFSVolumeCB *pVolumeCB = NULL;
3908 AFSFileID stTargetFileID;
3914 // Loop on each entry, building the chain until we encounter the final target
3917 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3918 AFS_TRACE_LEVEL_VERBOSE_2,
3919 "AFSBuildMountPointTarget Building target directory for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3920 &DirectoryCB->NameInformation.FileName,
3921 DirectoryCB->ObjectInformation->FileId.Cell,
3922 DirectoryCB->ObjectInformation->FileId.Volume,
3923 DirectoryCB->ObjectInformation->FileId.Vnode,
3924 DirectoryCB->ObjectInformation->FileId.Unique);
3927 // Do we need to evaluate the node?
3930 //if( DirectoryCB->ObjectInformation->TargetFileId.Vnode == 0 &&
3931 // DirectoryCB->ObjectInformation->TargetFileId.Unique == 0)
3935 // Go evaluate the current target to get the target fid
3938 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3939 AFS_TRACE_LEVEL_VERBOSE_2,
3940 "AFSBuildMountPointTarget Evaluating target %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3941 &DirectoryCB->NameInformation.FileName,
3942 DirectoryCB->ObjectInformation->FileId.Cell,
3943 DirectoryCB->ObjectInformation->FileId.Volume,
3944 DirectoryCB->ObjectInformation->FileId.Vnode,
3945 DirectoryCB->ObjectInformation->FileId.Unique);
3947 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
3952 if( !NT_SUCCESS( ntStatus))
3955 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3956 AFS_TRACE_LEVEL_ERROR,
3957 "AFSBuildMountPointTarget Failed to evaluate target %wZ Status %08lX\n",
3958 &DirectoryCB->NameInformation.FileName,
3960 try_return( ntStatus);
3963 if( pDirEntry->TargetFileId.Vnode == 0 &&
3964 pDirEntry->TargetFileId.Unique == 0)
3967 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3968 AFS_TRACE_LEVEL_ERROR,
3969 "AFSBuildMountPointTarget Target %wZ FID %08lX-%08lX-%08lX-%08lX service returned zero FID\n",
3970 &DirectoryCB->NameInformation.FileName,
3971 DirectoryCB->ObjectInformation->FileId.Cell,
3972 DirectoryCB->ObjectInformation->FileId.Volume,
3973 DirectoryCB->ObjectInformation->FileId.Vnode,
3974 DirectoryCB->ObjectInformation->FileId.Unique);
3976 try_return( ntStatus = STATUS_ACCESS_DENIED);
3979 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
3982 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
3983 &DirectoryCB->Flags,
3984 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
3985 (USHORT)pDirEntry->TargetNameLength);
3987 if( !NT_SUCCESS( ntStatus))
3990 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
3992 try_return( ntStatus);
3995 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
3997 DirectoryCB->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
4000 stTargetFileID = DirectoryCB->ObjectInformation->TargetFileId;
4003 // Try to locate this FID. First the volume then the
4007 ullIndex = AFSCreateHighIndex( &stTargetFileID);
4009 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4010 AFS_TRACE_LEVEL_VERBOSE,
4011 "AFSBuildMountPointTarget Acquiring RDR VolumeTreeLock lock %08lX EXCL %08lX\n",
4012 &pDevExt->Specific.RDR.VolumeTreeLock,
4013 PsGetCurrentThread());
4015 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4018 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4019 AFS_TRACE_LEVEL_VERBOSE_2,
4020 "AFSBuildMountPointTarget Locating volume for target %I64X\n",
4023 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4025 (AFSBTreeEntry **)&pVolumeCB);
4028 // We can be processing a request for a target that is on a volume
4029 // we have never seen before.
4032 if( pVolumeCB == NULL)
4036 // Locking is held correctly in init routine
4039 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4042 // Go init the root of the volume
4045 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4046 AFS_TRACE_LEVEL_VERBOSE_2,
4047 "AFSBuildMountPointTarget Initializing root for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4048 &DirectoryCB->NameInformation.FileName,
4049 DirectoryCB->ObjectInformation->FileId.Cell,
4050 DirectoryCB->ObjectInformation->FileId.Volume,
4051 DirectoryCB->ObjectInformation->FileId.Vnode,
4052 DirectoryCB->ObjectInformation->FileId.Unique);
4054 ntStatus = AFSInitVolume( AuthGroup,
4058 if( !NT_SUCCESS( ntStatus))
4061 try_return( ntStatus);
4068 // Check if this volume has been deleted or taken offline
4071 if( BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
4074 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4076 try_return( ntStatus = STATUS_FILE_IS_OFFLINE);
4080 // Just to ensure that things don't get torn down AND we don't create a
4081 // deadlock with invalidation
4084 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
4086 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4088 AFSAcquireExcl( pVolumeCB->VolumeLock,
4091 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
4094 if( pVolumeCB->RootFcb == NULL)
4098 // Initialize the root fcb for this volume
4101 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4104 if( !NT_SUCCESS( ntStatus))
4107 AFSReleaseResource( pVolumeCB->VolumeLock);
4109 try_return( ntStatus);
4113 // Drop the lock acquired above
4116 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4119 AFSConvertToShared( pVolumeCB->VolumeLock);
4121 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4122 AFS_TRACE_LEVEL_VERBOSE_2,
4123 "AFSBuildMountPointTarget Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4124 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4125 pVolumeCB->ObjectInformation.FileId.Cell,
4126 pVolumeCB->ObjectInformation.FileId.Volume,
4127 pVolumeCB->ObjectInformation.FileId.Vnode,
4128 pVolumeCB->ObjectInformation.FileId.Unique);
4130 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
4132 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4133 AFS_TRACE_LEVEL_VERBOSE,
4134 "AFSBuildMountPointTarget Increment count on volume %08lX Cnt %d\n",
4136 pVolumeCB->VolumeReferenceCount);
4138 *TargetVolumeCB = pVolumeCB;
4145 AFSExFreePool( pDirEntry);
4153 AFSBuildRootVolume( IN GUID *AuthGroup,
4154 IN AFSFileID *FileId,
4155 OUT AFSVolumeCB **TargetVolumeCB)
4158 NTSTATUS ntStatus = STATUS_SUCCESS;
4159 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4160 AFSDirectoryCB *pDirNode = NULL;
4161 UNICODE_STRING uniDirName, uniTargetName;
4162 ULONGLONG ullIndex = 0;
4163 AFSVolumeCB *pVolumeCB = NULL;
4168 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4169 AFS_TRACE_LEVEL_VERBOSE_2,
4170 "AFSBuildRootVolume Building target volume for FID %08lX-%08lX-%08lX-%08lX\n",
4176 ullIndex = AFSCreateHighIndex( FileId);
4178 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4179 AFS_TRACE_LEVEL_VERBOSE,
4180 "AFSBuildRootVolume Acquiring RDR VolumeTreeLock lock %08lX EXCL %08lX\n",
4181 &pDevExt->Specific.RDR.VolumeTreeLock,
4182 PsGetCurrentThread());
4184 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4187 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4188 AFS_TRACE_LEVEL_VERBOSE_2,
4189 "AFSBuildRootVolume Locating volume for target %I64X\n",
4192 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4194 (AFSBTreeEntry **)&pVolumeCB);
4197 // We can be processing a request for a target that is on a volume
4198 // we have never seen before.
4201 if( pVolumeCB == NULL)
4205 // Locking is held correctly in init routine
4208 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4211 // Go init the root of the volume
4214 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4215 AFS_TRACE_LEVEL_VERBOSE_2,
4216 "AFSBuildRootVolume Initializing root for FID %08lX-%08lX-%08lX-%08lX\n",
4222 ntStatus = AFSInitVolume( AuthGroup,
4226 if( !NT_SUCCESS( ntStatus))
4229 try_return( ntStatus);
4236 // Just to ensure that things don't get torn down AND we don't create a
4237 // deadlock with invalidation
4240 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
4242 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4244 AFSAcquireExcl( pVolumeCB->VolumeLock,
4247 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
4251 if( pVolumeCB->RootFcb == NULL)
4255 // Initialize the root fcb for this volume
4258 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4261 if( !NT_SUCCESS( ntStatus))
4264 AFSReleaseResource( pVolumeCB->VolumeLock);
4266 try_return( ntStatus);
4270 // Drop the lock acquired above
4273 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4276 AFSConvertToShared( pVolumeCB->VolumeLock);
4278 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4279 AFS_TRACE_LEVEL_VERBOSE_2,
4280 "AFSBuildRootVolume Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4281 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4282 pVolumeCB->ObjectInformation.FileId.Cell,
4283 pVolumeCB->ObjectInformation.FileId.Volume,
4284 pVolumeCB->ObjectInformation.FileId.Vnode,
4285 pVolumeCB->ObjectInformation.FileId.Unique);
4287 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
4289 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4290 AFS_TRACE_LEVEL_VERBOSE,
4291 "AFSBuildRootVolume Increment count on volume %08lX Cnt %d\n",
4293 pVolumeCB->VolumeReferenceCount);
4295 *TargetVolumeCB = pVolumeCB;
4306 AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
4307 IN PFILE_OBJECT FileObject,
4308 IN UNICODE_STRING *RemainingPath,
4312 NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
4313 UNICODE_STRING uniReparseName;
4314 UNICODE_STRING uniMUPDeviceName;
4315 AFSDirEnumEntry *pDirEntry = NULL;
4321 // Build up the name to reparse
4324 RtlInitUnicodeString( &uniMUPDeviceName,
4327 uniReparseName.Length = 0;
4328 uniReparseName.Buffer = NULL;
4331 // Be sure we have a target name
4334 if( DirEntry->NameInformation.TargetName.Length == 0)
4337 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
4342 if( !NT_SUCCESS( ntStatus) ||
4343 pDirEntry->TargetNameLength == 0)
4346 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4347 AFS_TRACE_LEVEL_ERROR,
4348 "AFSProcessDFSLink EvaluateTargetByID failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4349 &DirEntry->NameInformation.FileName,
4350 DirEntry->ObjectInformation->FileId.Cell,
4351 DirEntry->ObjectInformation->FileId.Volume,
4352 DirEntry->ObjectInformation->FileId.Vnode,
4353 DirEntry->ObjectInformation->FileId.Unique,
4356 if( NT_SUCCESS( ntStatus))
4359 ntStatus = STATUS_ACCESS_DENIED;
4362 try_return( ntStatus);
4366 // Update the target name
4369 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
4372 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
4374 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4375 (USHORT)pDirEntry->TargetNameLength);
4377 if( !NT_SUCCESS( ntStatus))
4380 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4381 AFS_TRACE_LEVEL_ERROR,
4382 "AFSProcessDFSLink UpdateTargetName failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4383 &DirEntry->NameInformation.FileName,
4384 DirEntry->ObjectInformation->FileId.Cell,
4385 DirEntry->ObjectInformation->FileId.Volume,
4386 DirEntry->ObjectInformation->FileId.Vnode,
4387 DirEntry->ObjectInformation->FileId.Unique,
4390 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4392 try_return( ntStatus);
4395 AFSConvertToShared( &DirEntry->NonPaged->Lock);
4399 AFSAcquireShared( &DirEntry->NonPaged->Lock,
4403 uniReparseName.MaximumLength = uniMUPDeviceName.Length +
4405 DirEntry->NameInformation.TargetName.Length +
4408 if( RemainingPath != NULL &&
4409 RemainingPath->Length > 0)
4412 uniReparseName.MaximumLength += RemainingPath->Length;
4416 // Allocate the reparse buffer
4419 uniReparseName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4420 uniReparseName.MaximumLength,
4421 AFS_REPARSE_NAME_TAG);
4423 if( uniReparseName.Buffer == NULL)
4426 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4427 AFS_TRACE_LEVEL_ERROR,
4428 "AFSProcessDFSLink uniReparseName.Buffer == NULL Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4429 &DirEntry->NameInformation.FileName,
4430 DirEntry->ObjectInformation->FileId.Cell,
4431 DirEntry->ObjectInformation->FileId.Volume,
4432 DirEntry->ObjectInformation->FileId.Vnode,
4433 DirEntry->ObjectInformation->FileId.Unique,
4434 STATUS_INSUFFICIENT_RESOURCES);
4436 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4438 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4442 // Start building the name
4445 RtlCopyMemory( uniReparseName.Buffer,
4446 uniMUPDeviceName.Buffer,
4447 uniMUPDeviceName.Length);
4449 uniReparseName.Length = uniMUPDeviceName.Length;
4451 if( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\')
4454 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
4456 uniReparseName.Length += sizeof( WCHAR);
4459 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
4460 DirEntry->NameInformation.TargetName.Buffer,
4461 DirEntry->NameInformation.TargetName.Length);
4463 uniReparseName.Length += DirEntry->NameInformation.TargetName.Length;
4465 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4467 if( RemainingPath != NULL &&
4468 RemainingPath->Length > 0)
4471 if( uniReparseName.Buffer[ (uniReparseName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
4472 RemainingPath->Buffer[ 0] != L'\\')
4475 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
4477 uniReparseName.Length += sizeof( WCHAR);
4480 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
4481 RemainingPath->Buffer,
4482 RemainingPath->Length);
4484 uniReparseName.Length += RemainingPath->Length;
4488 // Update the name in the file object
4491 if( FileObject->FileName.Buffer != NULL)
4494 AFSExFreePool( FileObject->FileName.Buffer);
4497 FileObject->FileName = uniReparseName;
4499 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4500 AFS_TRACE_LEVEL_VERBOSE,
4501 "AFSProcessDFSLink Reparsing access to Fcb %wZ FID %08lX-%08lX-%08lX-%08lX to %wZ\n",
4502 &DirEntry->NameInformation.FileName,
4503 DirEntry->ObjectInformation->FileId.Cell,
4504 DirEntry->ObjectInformation->FileId.Volume,
4505 DirEntry->ObjectInformation->FileId.Vnode,
4506 DirEntry->ObjectInformation->FileId.Unique,
4510 // Return status reparse ...
4513 ntStatus = STATUS_REPARSE;
4520 AFSExFreePool( pDirEntry);