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,
944 // This is where we have been re-entered from an NP evaluation call via the BuildBranch()
948 ntStatus = STATUS_INVALID_PARAMETER;
951 if( ntStatus != STATUS_SUCCESS &&
952 ntStatus != STATUS_REPARSE)
955 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
956 AFS_TRACE_LEVEL_ERROR,
957 "AFSLocateNameEntry (FO: %08lX) Failed to process DFSLink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
959 &pDirEntry->NameInformation.FileName,
960 pCurrentObject->FileId.Cell,
961 pCurrentObject->FileId.Volume,
962 pCurrentObject->FileId.Vnode,
963 pCurrentObject->FileId.Unique,
967 try_return( ntStatus);
970 case AFS_FILE_TYPE_UNKNOWN:
971 case AFS_FILE_TYPE_INVALID:
975 // Something was not processed ...
978 try_return( ntStatus = STATUS_ACCESS_DENIED);
981 } /* end of switch */
984 // If the parent is not initialized then do it now
987 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
988 !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
991 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
992 AFS_TRACE_LEVEL_VERBOSE,
993 "AFSLocateNameEntry (FO: %08lX) Enumerating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
995 &pDirEntry->NameInformation.FileName,
996 pCurrentObject->FileId.Cell,
997 pCurrentObject->FileId.Volume,
998 pCurrentObject->FileId.Vnode,
999 pCurrentObject->FileId.Unique);
1001 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1004 if( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1007 ntStatus = AFSEnumerateDirectory( AuthGroup,
1011 if( !NT_SUCCESS( ntStatus))
1014 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1016 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1017 AFS_TRACE_LEVEL_ERROR,
1018 "AFSLocateNameEntry (FO: %08lX) Failed to enumerate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1020 &pDirEntry->NameInformation.FileName,
1021 pCurrentObject->FileId.Cell,
1022 pCurrentObject->FileId.Volume,
1023 pCurrentObject->FileId.Vnode,
1024 pCurrentObject->FileId.Unique,
1027 try_return( ntStatus);
1030 SetFlag( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1033 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1035 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1038 if( uniPathName.Length > 0)
1041 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1042 AFS_TRACE_LEVEL_ERROR,
1043 "AFSLocateNameEntry (FO: %08lX) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1045 &pDirEntry->NameInformation.FileName,
1046 pCurrentObject->FileId.Cell,
1047 pCurrentObject->FileId.Volume,
1048 pCurrentObject->FileId.Vnode,
1049 pCurrentObject->FileId.Unique);
1051 // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1052 // one of the components of the path is not a directory. However, returning
1053 // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1054 // Instead IIS insists on treating the target file as if it is a directory containing
1055 // a potential web.config file. NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1056 // AFS will follow suit.
1058 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1063 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1064 AFS_TRACE_LEVEL_VERBOSE,
1065 "AFSLocateNameEntry (FO: %08lX) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1067 &pDirEntry->NameInformation.FileName,
1068 pCurrentObject->FileId.Cell,
1069 pCurrentObject->FileId.Volume,
1070 pCurrentObject->FileId.Vnode,
1071 pCurrentObject->FileId.Unique);
1074 // Pass back the directory entries
1077 *ParentDirectoryCB = pParentDirEntry;
1079 *DirectoryCB = pDirEntry;
1081 *VolumeCB = pCurrentVolume;
1083 *RootPathName = uniFullPathName;
1086 try_return( ntStatus);
1090 // If we are at the end of the processing, set our returned information and get out
1093 if( uniPathName.Length == 0)
1096 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1097 AFS_TRACE_LEVEL_VERBOSE,
1098 "AFSLocateNameEntry (FO: %08lX) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1100 &pDirEntry->NameInformation.FileName,
1101 pCurrentObject->FileId.Cell,
1102 pCurrentObject->FileId.Volume,
1103 pCurrentObject->FileId.Vnode,
1104 pCurrentObject->FileId.Unique);
1107 // Pass back the directory entries
1110 *ParentDirectoryCB = pParentDirEntry;
1112 *DirectoryCB = pDirEntry;
1114 *VolumeCB = pCurrentVolume;
1116 *RootPathName = uniFullPathName;
1118 try_return( ntStatus);
1122 // We may have returned to the top of the while( TRUE)
1124 if( bSubstituteName &&
1125 uniSearchName.Buffer != NULL)
1128 AFSExFreePool( uniSearchName.Buffer);
1130 bSubstituteName = FALSE;
1132 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1133 uniSearchName.Buffer = NULL;
1136 ulSubstituteIndex = 1;
1138 ntStatus = STATUS_SUCCESS;
1141 // Get the next component name
1144 FsRtlDissectName( uniPathName,
1149 // Check for the . and .. in the path
1152 if( RtlCompareUnicodeString( &uniComponentName,
1157 uniPathName = uniRemainingPath;
1162 if( RtlCompareUnicodeString( &uniComponentName,
1167 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1168 AFS_TRACE_LEVEL_VERBOSE,
1169 "AFSLocateNameEntry (FO: %08lX) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1171 &pDirEntry->NameInformation.FileName,
1172 pCurrentObject->FileId.Cell,
1173 pCurrentObject->FileId.Volume,
1174 pCurrentObject->FileId.Vnode,
1175 pCurrentObject->FileId.Unique);
1178 // Need to back up one entry in the name array
1181 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
1183 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1184 AFS_TRACE_LEVEL_VERBOSE,
1185 "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1186 &pDirEntry->NameInformation.FileName,
1189 pDirEntry->OpenReferenceCount);
1191 pDirEntry = AFSBackupEntry( NameArray);
1193 if( pDirEntry == NULL)
1196 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1197 AFS_TRACE_LEVEL_ERROR,
1198 "AFSLocateNameEntry AFSBackupEntry failed\n");
1200 try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1203 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1205 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1208 pParentDirEntry = NULL;
1213 pParentDirEntry = AFSGetParentEntry( pNameArray);
1215 ASSERT( pParentDirEntry != pDirEntry);
1218 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1219 AFS_TRACE_LEVEL_VERBOSE,
1220 "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1221 &pDirEntry->NameInformation.FileName,
1224 pDirEntry->OpenReferenceCount);
1226 uniPathName = uniRemainingPath;
1232 // Update our pointers
1235 pParentDirEntry = pDirEntry;
1239 uniSearchName = uniComponentName;
1241 while( pDirEntry == NULL)
1245 // If the SearchName contains @SYS then we perform the substitution.
1246 // If there is no substitution we give up.
1249 if( !bSubstituteName &&
1250 FsRtlIsNameInExpression( &uniSysName,
1256 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1257 AFS_TRACE_LEVEL_VERBOSE_2,
1258 "AFSLocateNameEntry (FO: %08lX) Processing @SYS substitution for %wZ Index %08lX\n",
1263 ntStatus = AFSSubstituteSysName( &uniComponentName,
1267 if ( NT_SUCCESS( ntStatus))
1270 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1271 AFS_TRACE_LEVEL_VERBOSE_2,
1272 "AFSLocateNameEntry (FO: %08lX) Located substitution %wZ for %wZ Index %08lX\n",
1279 // Go reparse the name again
1282 bSubstituteName = TRUE;
1284 ulSubstituteIndex++; // For the next entry, if needed
1286 continue; // while( pDirEntry == NULL)
1291 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1292 AFS_TRACE_LEVEL_ERROR,
1293 "AFSLocateNameEntry (FO: %08lX) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1299 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1303 // Pass back the directory entries
1306 *ParentDirectoryCB = pParentDirEntry;
1308 *DirectoryCB = NULL;
1310 *VolumeCB = pCurrentVolume;
1312 if( ComponentName != NULL)
1315 *ComponentName = uniComponentName;
1318 *RootPathName = uniFullPathName;
1322 // We can't possibly have a pDirEntry since the lookup failed
1324 try_return( ntStatus);
1329 // Generate the CRC on the node and perform a case sensitive lookup
1332 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1333 AFS_TRACE_LEVEL_VERBOSE_2,
1334 "AFSLocateNameEntry (FO: %08lX) Searching for entry %wZ case sensitive\n",
1338 ulCRC = AFSGenerateCRC( &uniSearchName,
1341 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1344 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1348 if( pDirEntry == NULL)
1352 // Missed so perform a case insensitive lookup
1355 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1356 AFS_TRACE_LEVEL_VERBOSE_2,
1357 "AFSLocateNameEntry (FO: %08lX) Searching for entry %wZ case insensitive\n",
1361 ulCRC = AFSGenerateCRC( &uniSearchName,
1364 AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1368 if( pDirEntry == NULL)
1372 // OK, if this component is a valid short name then try
1373 // a lookup in the short name tree
1376 if( RtlIsNameLegalDOS8Dot3( &uniSearchName,
1381 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1382 AFS_TRACE_LEVEL_VERBOSE_2,
1383 "AFSLocateNameEntry (FO: %08lX) Searching for entry %wZ short name\n",
1387 AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1392 if( pDirEntry == NULL)
1396 // If we substituted a name then reset our search name and try again
1399 if( bSubstituteName)
1402 AFSExFreePool( uniSearchName.Buffer);
1404 uniSearchName = uniComponentName;
1406 bSubstituteName = FALSE;
1408 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1410 continue; // while( pDirEntry == NULL)
1413 if( uniRemainingPath.Length > 0)
1416 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1421 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1423 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1424 AFS_TRACE_LEVEL_VERBOSE,
1425 "AFSLocateNameEntry (FO: %08lX) Returning name not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1428 pCurrentObject->FileId.Cell,
1429 pCurrentObject->FileId.Volume,
1430 pCurrentObject->FileId.Vnode,
1431 pCurrentObject->FileId.Unique);
1434 // Pass back the directory entries
1437 *ParentDirectoryCB = pParentDirEntry;
1439 *DirectoryCB = NULL;
1441 *VolumeCB = pCurrentVolume;
1443 if( ComponentName != NULL)
1446 *ComponentName = uniComponentName;
1449 *RootPathName = uniFullPathName;
1452 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1455 // Node name not found so get out
1458 try_return( ntStatus); // while( pDirEntry == NULL)
1465 // Here we have a match on the case insensitive lookup for the name. If there
1466 // Is more than one link entry for this node then fail the lookup request
1469 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1470 pDirEntry->CaseInsensitiveList.fLink != NULL)
1473 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1475 try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1480 if( pDirEntry != NULL)
1484 // If the verify flag is set on the parent and the current entry is deleted
1485 // revalidate the parent and search again.
1488 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1489 BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1492 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1494 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1495 AFS_TRACE_LEVEL_VERBOSE,
1496 "AFSLocateNameEntry (FO: %08lX) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1498 &pParentDirEntry->NameInformation.FileName,
1499 pParentDirEntry->ObjectInformation->FileId.Cell,
1500 pParentDirEntry->ObjectInformation->FileId.Volume,
1501 pParentDirEntry->ObjectInformation->FileId.Vnode,
1502 pParentDirEntry->ObjectInformation->FileId.Unique);
1504 ntStatus = AFSVerifyEntry( AuthGroup,
1507 if( !NT_SUCCESS( ntStatus))
1510 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1511 AFS_TRACE_LEVEL_ERROR,
1512 "AFSLocateNameEntry (FO: %08lX) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1514 &pParentDirEntry->NameInformation.FileName,
1515 pParentDirEntry->ObjectInformation->FileId.Cell,
1516 pParentDirEntry->ObjectInformation->FileId.Volume,
1517 pParentDirEntry->ObjectInformation->FileId.Vnode,
1518 pParentDirEntry->ObjectInformation->FileId.Unique,
1521 try_return( ntStatus);
1524 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1525 AFS_TRACE_LEVEL_VERBOSE,
1526 "AFSLocateNameEntry (FO: %08lX) Reprocessing component %wZ in parent %wZ\n",
1529 &pParentDirEntry->NameInformation.FileName);
1538 // Increment our dir entry ref count
1541 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1543 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1544 AFS_TRACE_LEVEL_VERBOSE,
1545 "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1546 &pDirEntry->NameInformation.FileName,
1549 pDirEntry->OpenReferenceCount);
1552 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1554 } // End while( pDirEntry == NULL)
1557 // If we have a dirEntry for this component, perform some basic validation on it
1560 if( pDirEntry != NULL &&
1561 BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1564 pCurrentObject = pDirEntry->ObjectInformation;
1566 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1567 AFS_TRACE_LEVEL_ERROR,
1568 "AFSLocateNameEntry (FO: %08lX) Deleted parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1570 &pDirEntry->NameInformation.FileName,
1571 pCurrentObject->FileId.Cell,
1572 pCurrentObject->FileId.Volume,
1573 pCurrentObject->FileId.Vnode,
1574 pCurrentObject->FileId.Unique);
1577 // This entry was deleted through the invalidation call back so perform cleanup
1581 ASSERT( pCurrentObject->ParentObjectInformation != NULL);
1583 AFSAcquireExcl( pCurrentObject->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1586 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1589 if( InterlockedDecrement( &pDirEntry->OpenReferenceCount) == 0)
1592 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1593 AFS_TRACE_LEVEL_VERBOSE,
1594 "AFSLocateNameEntry Deleting dir entry %08lX (%08lX) for %wZ\n",
1597 &pDirEntry->NameInformation.FileName);
1600 // Remove and delete the directory entry from the parent list
1603 AFSDeleteDirEntry( pCurrentObject->ParentObjectInformation,
1606 if( pCurrentObject->ObjectReferenceCount == 0)
1609 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
1612 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1613 AFS_TRACE_LEVEL_VERBOSE,
1614 "AFSLocateNameEntry Removing object %08lX from volume tree\n",
1617 AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
1618 &pCurrentObject->TreeEntry);
1620 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
1627 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1628 AFS_TRACE_LEVEL_VERBOSE,
1629 "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
1631 &pDirEntry->NameInformation.FileName);
1633 SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
1635 AFSRemoveNameEntry( pCurrentObject->ParentObjectInformation,
1639 AFSReleaseResource( pCurrentObject->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1641 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
1644 // We deleted the dir entry so check if there is any remaining portion
1645 // of the name to process.
1648 if( uniRemainingPath.Length > 0)
1650 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1655 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1657 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1658 AFS_TRACE_LEVEL_VERBOSE,
1659 "AFSLocateNameEntry (FO: %08lX) Returning name not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1662 pCurrentObject->FileId.Cell,
1663 pCurrentObject->FileId.Volume,
1664 pCurrentObject->FileId.Vnode,
1665 pCurrentObject->FileId.Unique);
1668 // Pass back the directory entries
1671 *ParentDirectoryCB = pParentDirEntry;
1673 *DirectoryCB = NULL;
1675 *VolumeCB = pCurrentVolume;
1677 if( ComponentName != NULL)
1680 *ComponentName = uniComponentName;
1683 *RootPathName = uniFullPathName;
1687 if( ntStatus != STATUS_SUCCESS)
1690 try_return( ntStatus);
1694 // Decrement the previous parent
1697 InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
1699 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1700 AFS_TRACE_LEVEL_VERBOSE,
1701 "AFSLocateNameEntry Decrement5 count on Parent %wZ DE %p Ccb %p Cnt %d\n",
1702 &pParentDirEntry->NameInformation.FileName,
1705 pParentDirEntry->OpenReferenceCount);
1708 // If we ended up substituting a name in the component then update
1709 // the full path and update the pointers
1712 if( bSubstituteName)
1715 BOOLEAN bRelativeOpen = FALSE;
1717 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1718 AFS_TRACE_LEVEL_VERBOSE_2,
1719 "AFSLocateNameEntry (FO: %08lX) Substituting %wZ into %wZ Index %08lX\n",
1725 if( FileObject != NULL &&
1726 FileObject->RelatedFileObject != NULL)
1729 bRelativeOpen = TRUE;
1733 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
1734 // and free the prior Buffer contents but only if the fourth
1735 // parameter is TRUE.
1738 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
1743 bAllocatedSymLinkBuffer ||
1746 if( !NT_SUCCESS( ntStatus))
1749 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1750 AFS_TRACE_LEVEL_ERROR,
1751 "AFSLocateNameEntry (FO: %08lX) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
1758 try_return( ntStatus);
1762 // We have substituted a name into the buffer so if we do this again for this
1763 // path, we need to free up the buffer we allocated.
1766 bSubstitutedName = TRUE;
1770 // Update the search parameters
1773 uniPathName = uniRemainingPath;
1776 // Check if the is a SymLink entry but has no Target FileID or Name. In this
1777 // case it might be a DFS Link so let's go and evaluate it to be sure
1780 if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
1781 pCurrentObject->TargetFileId.Vnode == 0 &&
1782 pCurrentObject->TargetFileId.Unique == 0 &&
1783 pDirEntry->NameInformation.TargetName.Length == 0)
1786 ntStatus = AFSValidateSymLink( AuthGroup,
1789 if( !NT_SUCCESS( ntStatus))
1792 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1793 AFS_TRACE_LEVEL_ERROR,
1794 "AFSLocateNameEntry (FO: %08lX) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1796 &pDirEntry->NameInformation.FileName,
1797 pCurrentObject->FileId.Cell,
1798 pCurrentObject->FileId.Volume,
1799 pCurrentObject->FileId.Vnode,
1800 pCurrentObject->FileId.Unique,
1803 try_return( ntStatus);
1808 // Update the name array
1811 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1812 AFS_TRACE_LEVEL_VERBOSE,
1813 "AFSLocateNameEntry (FO: %08lX) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1815 &pDirEntry->NameInformation.FileName,
1816 pCurrentObject->FileId.Cell,
1817 pCurrentObject->FileId.Volume,
1818 pCurrentObject->FileId.Vnode,
1819 pCurrentObject->FileId.Unique);
1821 ntStatus = AFSInsertNextElement( pNameArray,
1824 if( !NT_SUCCESS( ntStatus))
1827 try_return( ntStatus);
1833 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1834 AFS_TRACE_LEVEL_VERBOSE,
1835 "AFSLocateNameEntry (FO: %08lX) Completed processing %wZ Status %08lX\n",
1840 if( ( !NT_SUCCESS( ntStatus) &&
1841 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
1842 ntStatus == STATUS_REPARSE)
1845 if( pDirEntry != NULL)
1848 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
1850 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1851 AFS_TRACE_LEVEL_VERBOSE,
1852 "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
1853 &pDirEntry->NameInformation.FileName,
1856 pDirEntry->OpenReferenceCount);
1858 else if( pParentDirEntry != NULL)
1861 InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
1863 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1864 AFS_TRACE_LEVEL_VERBOSE,
1865 "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
1866 &pParentDirEntry->NameInformation.FileName,
1869 pParentDirEntry->OpenReferenceCount);
1872 if( bReleaseCurrentVolume)
1875 ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
1877 ASSERT( ExIsResourceAcquiredLite( pCurrentVolume->VolumeLock));
1879 InterlockedDecrement( &pCurrentVolume->VolumeReferenceCount);
1881 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1882 AFS_TRACE_LEVEL_VERBOSE,
1883 "AFSLocateNameEntry Decrement3 count on volume %08lX Cnt %d\n",
1885 pCurrentVolume->VolumeReferenceCount);
1887 AFSReleaseResource( pCurrentVolume->VolumeLock);
1890 if( RootPathName->Buffer != uniFullPathName.Buffer)
1893 AFSExFreePool( uniFullPathName.Buffer);
1899 if( *ParentDirectoryCB != NULL)
1902 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1903 AFS_TRACE_LEVEL_VERBOSE,
1904 "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
1905 &(*ParentDirectoryCB)->NameInformation.FileName,
1908 (*ParentDirectoryCB)->OpenReferenceCount);
1911 if( *DirectoryCB != NULL)
1914 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1915 AFS_TRACE_LEVEL_VERBOSE,
1916 "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
1917 &(*DirectoryCB)->NameInformation.FileName,
1920 (*DirectoryCB)->OpenReferenceCount);
1924 if( bSubstituteName &&
1925 uniSearchName.Buffer != NULL)
1928 AFSExFreePool( uniSearchName.Buffer);
1936 AFSCreateDirEntry( IN GUID *AuthGroup,
1937 IN AFSObjectInfoCB *ParentObjectInfo,
1938 IN AFSDirectoryCB *ParentDirCB,
1939 IN PUNICODE_STRING FileName,
1940 IN PUNICODE_STRING ComponentName,
1941 IN ULONG Attributes,
1942 IN OUT AFSDirectoryCB **DirEntry)
1945 NTSTATUS ntStatus = STATUS_SUCCESS;
1946 AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
1947 UNICODE_STRING uniShortName;
1948 LARGE_INTEGER liFileSize = {0,0};
1953 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1954 AFS_TRACE_LEVEL_VERBOSE_2,
1955 "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
1956 &ParentDirCB->NameInformation.FileName,
1957 ParentObjectInfo->FileId.Cell,
1958 ParentObjectInfo->FileId.Volume,
1959 ParentObjectInfo->FileId.Vnode,
1960 ParentObjectInfo->FileId.Unique,
1965 // OK, before inserting the node into the parent tree, issue
1966 // the request to the service for node creation
1967 // We will need to drop the lock on the parent node since the create
1968 // could cause a callback into the file system to invalidate it's cache
1971 ntStatus = AFSNotifyFileCreate( AuthGroup,
1979 // If the returned status is STATUS_REPARSE then the entry exists
1980 // and we raced, get out.
1982 if( ntStatus == STATUS_REPARSE)
1985 *DirEntry = pDirNode;
1987 try_return( ntStatus = STATUS_SUCCESS);
1990 if( !NT_SUCCESS( ntStatus))
1993 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1994 AFS_TRACE_LEVEL_ERROR,
1995 "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
1996 &ParentDirCB->NameInformation.FileName,
1997 ParentObjectInfo->FileId.Cell,
1998 ParentObjectInfo->FileId.Volume,
1999 ParentObjectInfo->FileId.Vnode,
2000 ParentObjectInfo->FileId.Unique,
2005 try_return( ntStatus);
2008 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2012 // Before attempting to insert the new entry, check if we need to validate the parent
2015 if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2018 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2019 AFS_TRACE_LEVEL_VERBOSE,
2020 "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2021 &ParentDirCB->NameInformation.FileName,
2022 ParentObjectInfo->FileId.Cell,
2023 ParentObjectInfo->FileId.Volume,
2024 ParentObjectInfo->FileId.Vnode,
2025 ParentObjectInfo->FileId.Unique);
2027 ntStatus = AFSVerifyEntry( AuthGroup,
2030 if( !NT_SUCCESS( ntStatus))
2033 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2034 AFS_TRACE_LEVEL_ERROR,
2035 "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2036 &ParentDirCB->NameInformation.FileName,
2037 ParentObjectInfo->FileId.Cell,
2038 ParentObjectInfo->FileId.Volume,
2039 ParentObjectInfo->FileId.Vnode,
2040 ParentObjectInfo->FileId.Unique,
2043 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2045 try_return( ntStatus);
2050 // Check for the entry in the event we raced with some other thread
2053 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2054 (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2057 if( pExistingDirNode != NULL)
2060 AFSDeleteDirEntry( ParentObjectInfo,
2063 InterlockedIncrement( &pExistingDirNode->OpenReferenceCount);
2065 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2066 AFS_TRACE_LEVEL_VERBOSE,
2067 "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2068 &pExistingDirNode->NameInformation.FileName,
2070 pExistingDirNode->OpenReferenceCount);
2072 *DirEntry = pExistingDirNode;
2074 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2076 try_return( ntStatus = STATUS_SUCCESS);
2079 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2080 AFS_TRACE_LEVEL_VERBOSE_2,
2081 "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2082 &ParentDirCB->NameInformation.FileName,
2083 ParentObjectInfo->FileId.Cell,
2084 ParentObjectInfo->FileId.Volume,
2085 ParentObjectInfo->FileId.Vnode,
2086 ParentObjectInfo->FileId.Unique,
2090 // Insert the directory node
2093 AFSInsertDirectoryNode( ParentObjectInfo,
2097 InterlockedIncrement( &pDirNode->OpenReferenceCount);
2099 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2100 AFS_TRACE_LEVEL_VERBOSE,
2101 "AFSCreateDirEntry Increment2 count on %wZ DE %p Cnt %d\n",
2102 &pDirNode->NameInformation.FileName,
2104 pDirNode->OpenReferenceCount);
2107 // Pass back the dir entry
2110 *DirEntry = pDirNode;
2112 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2123 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2124 IN AFSDirectoryCB *DirEntry,
2125 IN BOOLEAN InsertInEnumList)
2131 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2134 // Insert the node into the directory node tree
2137 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2138 AFS_TRACE_LEVEL_VERBOSE,
2139 "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2141 &DirEntry->NameInformation.FileName);
2143 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2145 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2148 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2150 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2151 AFS_TRACE_LEVEL_VERBOSE,
2152 "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2154 &DirEntry->NameInformation.FileName);
2159 AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2162 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2163 AFS_TRACE_LEVEL_VERBOSE,
2164 "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2166 &DirEntry->NameInformation.FileName);
2169 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2172 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2174 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2176 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2177 AFS_TRACE_LEVEL_VERBOSE,
2178 "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2180 &DirEntry->NameInformation.FileName);
2185 AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2188 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2189 AFS_TRACE_LEVEL_VERBOSE,
2190 "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2192 &DirEntry->NameInformation.FileName);
2196 // Into the shortname tree
2199 if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2202 if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2205 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2207 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2208 AFS_TRACE_LEVEL_VERBOSE,
2209 "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2211 &DirEntry->NameInformation.FileName);
2213 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2218 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2221 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2222 AFS_TRACE_LEVEL_VERBOSE,
2223 "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2225 &DirEntry->NameInformation.FileName);
2229 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2231 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2232 AFS_TRACE_LEVEL_VERBOSE,
2233 "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2235 &DirEntry->NameInformation.FileName);
2240 if( InsertInEnumList)
2244 // And insert the node into the directory list
2247 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2248 AFS_TRACE_LEVEL_VERBOSE,
2249 "AFSInsertDirectoryNode Inserting entry %08lX %wZ FID %08lX-%08lX-%08lX-%08lXStatus %08lX\n",
2251 &DirEntry->NameInformation.FileName,
2252 DirEntry->ObjectInformation->FileId.Cell,
2253 DirEntry->ObjectInformation->FileId.Volume,
2254 DirEntry->ObjectInformation->FileId.Vnode,
2255 DirEntry->ObjectInformation->FileId.Unique);
2257 if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2260 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2265 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2267 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2270 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2272 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2274 InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2276 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2277 AFS_TRACE_LEVEL_VERBOSE,
2278 "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2279 &DirEntry->NameInformation.FileName,
2280 ParentObjectInfo->Specific.Directory.DirectoryNodeCount,
2281 ParentObjectInfo->FileId.Cell,
2282 ParentObjectInfo->FileId.Volume,
2283 ParentObjectInfo->FileId.Vnode,
2284 ParentObjectInfo->FileId.Unique);
2292 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2293 IN AFSDirectoryCB *DirEntry)
2296 NTSTATUS ntStatus = STATUS_SUCCESS;
2301 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2302 AFS_TRACE_LEVEL_VERBOSE,
2303 "AFSDeleteDirEntry Deleting dir entry in parent %08lX Entry %08lX %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2306 &DirEntry->NameInformation.FileName,
2307 DirEntry->ObjectInformation->FileId.Cell,
2308 DirEntry->ObjectInformation->FileId.Volume,
2309 DirEntry->ObjectInformation->FileId.Vnode,
2310 DirEntry->ObjectInformation->FileId.Unique);
2312 AFSRemoveDirNodeFromParent( ParentObjectInfo,
2317 // Free up the name buffer if it was reallocated
2320 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2323 AFSExFreePool( DirEntry->NameInformation.FileName.Buffer);
2326 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2329 AFSExFreePool( DirEntry->NameInformation.TargetName.Buffer);
2333 // Dereference the object for this dir entry
2336 ASSERT( DirEntry->ObjectInformation->ObjectReferenceCount > 0);
2338 if( InterlockedDecrement( &DirEntry->ObjectInformation->ObjectReferenceCount) == 0)
2340 SetFlag( DirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2343 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2344 AFS_TRACE_LEVEL_VERBOSE,
2345 "AFSDeleteDirEntry Decrement count on object %08lX Cnt %d\n",
2346 DirEntry->ObjectInformation,
2347 DirEntry->ObjectInformation->ObjectReferenceCount);
2349 ExDeleteResourceLite( &DirEntry->NonPaged->Lock);
2351 AFSExFreePool( DirEntry->NonPaged);
2354 // Free up the dir entry
2357 AFSExFreePool( DirEntry);
2364 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2365 IN AFSDirectoryCB *DirEntry,
2366 IN BOOLEAN RemoveFromEnumList)
2369 NTSTATUS ntStatus = STATUS_SUCCESS;
2375 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2377 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2378 AFS_TRACE_LEVEL_VERBOSE,
2379 "AFSRemoveDirNodeFromParent Removing DirEntry %08lX %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %08lX\n",
2381 &DirEntry->NameInformation.FileName,
2382 DirEntry->ObjectInformation->FileId.Cell,
2383 DirEntry->ObjectInformation->FileId.Volume,
2384 DirEntry->ObjectInformation->FileId.Vnode,
2385 DirEntry->ObjectInformation->FileId.Unique,
2388 if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2391 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2392 AFS_TRACE_LEVEL_VERBOSE,
2393 "AFSRemoveDirNodeFromParent Removing DirEntry %08lX name %wZ\n",
2395 &DirEntry->NameInformation.FileName);
2397 AFSRemoveNameEntry( ParentObjectInfo,
2403 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2404 AFS_TRACE_LEVEL_VERBOSE,
2405 "AFSRemoveDirNodeFromParent DE %p for %wZ NOT removing entry due to flag set\n",
2407 &DirEntry->NameInformation.FileName);
2411 if( RemoveFromEnumList &&
2412 BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST))
2416 // And remove the entry from the enumeration list
2419 if( DirEntry->ListEntry.fLink == NULL)
2422 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = (AFSDirectoryCB *)DirEntry->ListEntry.bLink;
2427 ((AFSDirectoryCB *)DirEntry->ListEntry.fLink)->ListEntry.bLink = DirEntry->ListEntry.bLink;
2430 if( DirEntry->ListEntry.bLink == NULL)
2433 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = (AFSDirectoryCB *)DirEntry->ListEntry.fLink;
2438 ((AFSDirectoryCB *)DirEntry->ListEntry.bLink)->ListEntry.fLink = DirEntry->ListEntry.fLink;
2441 ASSERT( ParentObjectInfo->Specific.Directory.DirectoryNodeCount > 0);
2443 InterlockedDecrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2445 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2447 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2448 AFS_TRACE_LEVEL_VERBOSE,
2449 "AFSRemoveDirNodeFromParent Removing entry %wZ Dec Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2450 &DirEntry->NameInformation.FileName,
2451 ParentObjectInfo->Specific.Directory.DirectoryNodeCount,
2452 ParentObjectInfo->FileId.Cell,
2453 ParentObjectInfo->FileId.Volume,
2454 ParentObjectInfo->FileId.Vnode,
2455 ParentObjectInfo->FileId.Unique);
2457 DirEntry->ListEntry.fLink = NULL;
2458 DirEntry->ListEntry.bLink = NULL;
2466 AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
2467 IN OUT PUNICODE_STRING TargetFileName)
2470 NTSTATUS ntStatus = STATUS_SUCCESS;
2471 UNICODE_STRING uniFileName;
2477 // We will process backwards from the end of the name looking
2478 // for the first \ we encounter
2481 uniFileName.Length = FileName->Length;
2482 uniFileName.MaximumLength = FileName->MaximumLength;
2484 uniFileName.Buffer = FileName->Buffer;
2489 if( uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
2493 // Subtract one more character off of the filename if it is not the root
2496 if( uniFileName.Length > sizeof( WCHAR))
2499 uniFileName.Length -= sizeof( WCHAR);
2503 // Now build up the target name
2506 TargetFileName->Length = FileName->Length - uniFileName.Length;
2509 // If we are not on the root then fixup the name
2512 if( uniFileName.Length > sizeof( WCHAR))
2515 TargetFileName->Length -= sizeof( WCHAR);
2517 TargetFileName->Buffer = &uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) + 1];
2522 TargetFileName->Buffer = &uniFileName.Buffer[ uniFileName.Length/sizeof( WCHAR)];
2526 // Fixup the passed back filename length
2529 FileName->Length = uniFileName.Length;
2531 TargetFileName->MaximumLength = TargetFileName->Length;
2536 uniFileName.Length -= sizeof( WCHAR);
2544 AFSParseName( IN PIRP Irp,
2546 OUT PUNICODE_STRING FileName,
2547 OUT PUNICODE_STRING ParsedFileName,
2548 OUT PUNICODE_STRING RootFileName,
2549 OUT ULONG *ParseFlags,
2550 OUT AFSVolumeCB **VolumeCB,
2551 OUT AFSDirectoryCB **ParentDirectoryCB,
2552 OUT AFSNameArrayHdr **NameArray)
2555 NTSTATUS ntStatus = STATUS_SUCCESS;
2556 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2557 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2558 UNICODE_STRING uniFullName, uniComponentName, uniRemainingPath;
2560 AFSDirectoryCB *pDirEntry = NULL, *pShareDirEntry = NULL, *pTargetDirEntry = NULL;
2561 USHORT usIndex = 0, usDriveIndex = 0;
2562 AFSCcb *pRelatedCcb = NULL;
2563 AFSNameArrayHdr *pNameArray = NULL, *pRelatedNameArray = NULL;
2564 USHORT usComponentIndex = 0;
2565 USHORT usComponentLength = 0;
2566 AFSVolumeCB *pVolumeCB = NULL;
2567 AFSFcb *pRelatedFcb = NULL;
2568 BOOLEAN bReleaseTreeLock = FALSE;
2569 BOOLEAN bIsAllShare = FALSE;
2575 // Indicate we are opening a root ...
2578 *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
2580 if( pIrpSp->FileObject->RelatedFileObject != NULL)
2583 pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
2585 pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
2587 pRelatedNameArray = pRelatedCcb->NameArray;
2589 uniFullName = pIrpSp->FileObject->FileName;
2591 ASSERT( pRelatedFcb != NULL);
2594 // No wild cards in the name
2597 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2598 AFS_TRACE_LEVEL_VERBOSE_2,
2599 "AFSParseName (%08lX) Relative open for %wZ FID %08lX-%08lX-%08lX-%08lX component %wZ\n",
2601 &pRelatedCcb->DirectoryCB->NameInformation.FileName,
2602 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Cell,
2603 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Volume,
2604 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
2605 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Unique,
2608 if( FsRtlDoesNameContainWildCards( &uniFullName))
2611 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2612 AFS_TRACE_LEVEL_ERROR,
2613 "AFSParseName (%08lX) Component %wZ contains wild cards\n",
2617 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
2620 pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
2622 pDirEntry = pRelatedCcb->DirectoryCB;
2624 *FileName = pIrpSp->FileObject->FileName;
2627 // Grab the root node exclusive before returning
2630 AFSAcquireExcl( pVolumeCB->VolumeLock,
2633 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
2634 BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
2638 // The volume has been taken off line so fail the access
2641 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2642 AFS_TRACE_LEVEL_ERROR,
2643 "AFSParseName (%08lX) Volume %08lX:%08lX OFFLINE/INVALID\n",
2645 pVolumeCB->ObjectInformation.FileId.Cell,
2646 pVolumeCB->ObjectInformation.FileId.Volume);
2648 AFSReleaseResource( pVolumeCB->VolumeLock);
2650 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
2653 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
2656 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2657 AFS_TRACE_LEVEL_VERBOSE,
2658 "AFSParseName (%08lX) Verifying root of volume %08lX:%08lX\n",
2660 pVolumeCB->ObjectInformation.FileId.Cell,
2661 pVolumeCB->ObjectInformation.FileId.Volume);
2663 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
2666 if( !NT_SUCCESS( ntStatus))
2669 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2670 AFS_TRACE_LEVEL_ERROR,
2671 "AFSParseName (%08lX) Failed verification of root Status %08lX\n",
2675 AFSReleaseResource( pVolumeCB->VolumeLock);
2677 try_return( ntStatus);
2681 AFSConvertToShared( pVolumeCB->VolumeLock);
2683 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
2686 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2687 AFS_TRACE_LEVEL_VERBOSE,
2688 "AFSParseName (%08lX) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2690 &pDirEntry->NameInformation.FileName,
2691 pDirEntry->ObjectInformation->FileId.Cell,
2692 pDirEntry->ObjectInformation->FileId.Volume,
2693 pDirEntry->ObjectInformation->FileId.Vnode,
2694 pDirEntry->ObjectInformation->FileId.Unique);
2696 ntStatus = AFSVerifyEntry( AuthGroup,
2699 if( !NT_SUCCESS( ntStatus))
2702 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2703 AFS_TRACE_LEVEL_VERBOSE,
2704 "AFSParseName (%08lX) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2706 &pDirEntry->NameInformation.FileName,
2707 pDirEntry->ObjectInformation->FileId.Cell,
2708 pDirEntry->ObjectInformation->FileId.Volume,
2709 pDirEntry->ObjectInformation->FileId.Vnode,
2710 pDirEntry->ObjectInformation->FileId.Unique,
2713 AFSReleaseResource( pVolumeCB->VolumeLock);
2715 try_return( ntStatus);
2720 // Create our full path name buffer
2723 uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length +
2725 pIrpSp->FileObject->FileName.Length +
2728 uniFullName.Length = 0;
2730 uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2731 uniFullName.MaximumLength,
2732 AFS_NAME_BUFFER_THREE_TAG);
2734 if( uniFullName.Buffer == NULL)
2737 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2738 AFS_TRACE_LEVEL_ERROR,
2739 "AFSParseName (%08lX) Failed to allocate full name buffer\n",
2742 AFSReleaseResource( pVolumeCB->VolumeLock);
2744 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2747 RtlZeroMemory( uniFullName.Buffer,
2748 uniFullName.MaximumLength);
2750 RtlCopyMemory( uniFullName.Buffer,
2751 pRelatedCcb->FullFileName.Buffer,
2752 pRelatedCcb->FullFileName.Length);
2754 uniFullName.Length = pRelatedCcb->FullFileName.Length;
2756 usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
2758 usComponentLength = pIrpSp->FileObject->FileName.Length;
2760 if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
2761 pIrpSp->FileObject->FileName.Length > 0 &&
2762 pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
2763 pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
2766 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
2768 uniFullName.Length += sizeof( WCHAR);
2770 usComponentLength += sizeof( WCHAR);
2773 if( pIrpSp->FileObject->FileName.Length > 0)
2776 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
2777 pIrpSp->FileObject->FileName.Buffer,
2778 pIr
\epSp->FileObject->FileName.Length);
2780 uniFullName.Length += pIrpSp->FileObject->FileName.Length;
2783 *RootFileName = uniFullName;
2786 // We populate up to the current parent
2789 if( pRelatedNameArray == NULL)
2793 // Init and populate our name array
2796 pNameArray = AFSInitNameArray( NULL,
2799 if( pNameArray == NULL)
2802 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2803 AFS_TRACE_LEVEL_VERBOSE,
2804 "AFSParseName (%08lX) Failed to initialize name array\n",
2807 AFSExFreePool( uniFullName.Buffer);
2809 AFSReleaseResource( pVolumeCB->VolumeLock);
2811 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2814 ntStatus = AFSPopulateNameArray( pNameArray,
2816 pRelatedCcb->DirectoryCB);
2822 // Init and populate our name array
2825 pNameArray = AFSInitNameArray( NULL,
2826 pRelatedNameArray->MaxElementCount);
2828 if( pNameArray == NULL)
2831 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2832 AFS_TRACE_LEVEL_VERBOSE,
2833 "AFSParseName (%08lX) Failed to initialize name array\n",
2836 AFSExFreePool( uniFullName.Buffer);
2838 AFSReleaseResource( pVolumeCB->VolumeLock);
2840 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2843 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
2845 pRelatedCcb->DirectoryCB);
2848 if( !NT_SUCCESS( ntStatus))
2851 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2852 AFS_TRACE_LEVEL_VERBOSE,
2853 "AFSParseName (%08lX) Failed to populate name array\n",
2856 AFSExFreePool( uniFullName.Buffer);
2858 AFSReleaseResource( pVolumeCB->VolumeLock);
2860 try_return( ntStatus);
2863 ParsedFileName->Length = usComponentLength;
2864 ParsedFileName->MaximumLength = uniFullName.MaximumLength;
2866 ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
2869 // Indicate to caller that RootFileName must be freed
2872 SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
2874 *NameArray = pNameArray;
2876 *VolumeCB = pVolumeCB;
2879 // Increment our volume reference count
2882 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2884 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2885 AFS_TRACE_LEVEL_VERBOSE,
2886 "AFSParseName Increment count on volume %08lX Cnt %d\n",
2888 pVolumeCB->VolumeReferenceCount);
2890 *ParentDirectoryCB = pDirEntry;
2892 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
2894 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2895 AFS_TRACE_LEVEL_VERBOSE,
2896 "AFSParseName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
2897 &pDirEntry->NameInformation.FileName,
2900 pDirEntry->OpenReferenceCount);
2902 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2903 AFS_TRACE_LEVEL_VERBOSE_2,
2904 "AFSParseName (%08lX) Returning full name %wZ\n",
2908 try_return( ntStatus);
2912 // No wild cards in the name
2915 uniFullName = pIrpSp->FileObject->FileName;
2917 if( FsRtlDoesNameContainWildCards( &uniFullName) ||
2918 uniFullName.Length < AFSServerName.Length)
2921 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2922 AFS_TRACE_LEVEL_ERROR,
2923 "AFSParseName (%08lX) Name %wZ contains wild cards or too short\n",
2927 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
2931 // The name is a fully qualified name. Parse out the server/share names and
2932 // point to the root qualified name
2933 // First thing is to locate the server name
2936 FsRtlDissectName( uniFullName,
2940 uniFullName = uniRemainingPath;
2943 // This component is the server name we are serving
2946 if( RtlCompareUnicodeString( &uniComponentName,
2952 // Drive letter based name?
2955 uniFullName = pIrpSp->FileObject->FileName;
2957 while( usIndex < uniFullName.Length/sizeof( WCHAR))
2960 if( uniFullName.Buffer[ usIndex] == L':')
2963 uniFullName.Buffer = &uniFullName.Buffer[ usIndex + 2];
2965 uniFullName.Length -= (usIndex + 2) * sizeof( WCHAR);
2967 usDriveIndex = usIndex - 1;
2976 // Do we have the right server name now?
2979 FsRtlDissectName( uniFullName,
2983 uniFullName = uniRemainingPath;
2986 // This component is the server name we are serving
2989 if( RtlCompareUnicodeString( &uniComponentName,
2994 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2995 AFS_TRACE_LEVEL_ERROR,
2996 "AFSParseName (%08lX) Name %wZ does not have server name\n",
2998 &pIrpSp->FileObject->FileName);
3000 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3004 // Validate this drive letter is actively mapped
3007 if( usDriveIndex > 0 &&
3008 !AFSIsDriveMapped( pIrpSp->FileObject->FileName.Buffer[ usDriveIndex]))
3011 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3012 AFS_TRACE_LEVEL_ERROR,
3013 "AFSParseName (%08lX) Name %wZ contains invalid drive mapping\n",
3015 &pIrpSp->FileObject->FileName);
3017 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3021 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3022 AFS_TRACE_LEVEL_VERBOSE_2,
3023 "AFSParseName (%08lX) Processing full name %wZ\n",
3027 if( uniFullName.Length > 0 &&
3028 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] == L'\\')
3031 uniFullName.Length -= sizeof( WCHAR);
3035 // Be sure we are online and ready to go
3038 AFSAcquireExcl( AFSGlobalRoot->VolumeLock,
3041 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3042 BooleanFlagOn( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3046 // The volume has been taken off line so fail the access
3049 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3050 AFS_TRACE_LEVEL_ERROR,
3051 "AFSParseName (%08lX) Volume %08lX:%08lX OFFLINE/INVALID\n",
3053 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3054 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3056 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3058 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3061 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3064 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3065 AFS_TRACE_LEVEL_VERBOSE,
3066 "AFSParseName (%08lX) Verifying root of volume %08lX:%08lX\n",
3068 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3069 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3071 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3074 if( !NT_SUCCESS( ntStatus))
3077 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3078 AFS_TRACE_LEVEL_ERROR,
3079 "AFSParseName (%08lX) Failed verification of root Status %08lX\n",
3083 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3085 try_return( ntStatus);
3089 if( !BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3092 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3093 AFS_TRACE_LEVEL_VERBOSE,
3094 "AFSParseName (%08lX) Enumerating global root of volume %08lX:%08lX\n",
3096 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3097 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3099 ntStatus = AFSEnumerateGlobalRoot( AuthGroup);
3101 if( !NT_SUCCESS( ntStatus))
3104 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3105 AFS_TRACE_LEVEL_ERROR,
3106 "AFSParseName (%08lX) Failed enumeraiton of root Status %08lX\n",
3110 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3112 try_return( ntStatus);
3117 // Check for the \\Server access and return it as though it where \\Server\Globalroot
3120 if( uniRemainingPath.Buffer == NULL ||
3121 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3122 uniRemainingPath.Buffer[ 0] == L'\\'))
3125 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3126 AFS_TRACE_LEVEL_VERBOSE_2,
3127 "AFSParseName (%08lX) Returning global root access\n",
3130 InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3132 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3133 AFS_TRACE_LEVEL_VERBOSE,
3134 "AFSParseName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3135 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3136 AFSGlobalRoot->DirectoryCB,
3138 AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3140 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3144 FileName->Length = 0;
3145 FileName->MaximumLength = 0;
3146 FileName->Buffer = NULL;
3148 try_return( ntStatus = STATUS_SUCCESS);
3151 *RootFileName = uniFullName;
3154 // Include the starting \ in the root name
3157 if( RootFileName->Buffer[ 0] != L'\\')
3159 RootFileName->Buffer--;
3160 RootFileName->Length += sizeof( WCHAR);
3161 RootFileName->MaximumLength += sizeof( WCHAR);
3165 // Get the 'share' name
3168 FsRtlDissectName( uniFullName,
3173 // If this is the ALL access then perform some additional processing
3176 if( RtlCompareUnicodeString( &uniComponentName,
3184 // If there is nothing else then get out
3187 if( uniRemainingPath.Buffer == NULL ||
3188 uniRemainingPath.Length == 0 ||
3189 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3190 uniRemainingPath.Buffer[ 0] == L'\\'))
3193 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3194 AFS_TRACE_LEVEL_VERBOSE_2,
3195 "AFSParseName (%08lX) Returning global root access\n",
3198 InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3200 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3201 AFS_TRACE_LEVEL_VERBOSE,
3202 "AFSParseName Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
3203 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3204 AFSGlobalRoot->DirectoryCB,
3206 AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3208 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3212 FileName->Length = 0;
3213 FileName->MaximumLength = 0;
3214 FileName->Buffer = NULL;
3216 try_return( ntStatus = STATUS_SUCCESS);
3220 // Process the name again to strip off the ALL portion
3223 uniFullName = uniRemainingPath;
3225 FsRtlDissectName( uniFullName,
3230 // Check for the PIOCtl name
3233 if( RtlCompareUnicodeString( &uniComponentName,
3238 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3239 AFS_TRACE_LEVEL_VERBOSE_2,
3240 "AFSParseName (%08lX) Returning root PIOCtl access\n",
3243 InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3245 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3246 AFS_TRACE_LEVEL_VERBOSE,
3247 "AFSParseName Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
3248 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3249 AFSGlobalRoot->DirectoryCB,
3251 AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3253 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3255 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3259 *FileName = AFSPIOCtlName;
3261 try_return( ntStatus = STATUS_SUCCESS);
3264 else if( (pDirEntry = AFSGetSpecialShareNameEntry( &uniComponentName,
3265 &uniRemainingPath)) != NULL)
3268 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3269 AFS_TRACE_LEVEL_VERBOSE_2,
3270 "AFSParseName (%08lX) Returning root share name %wZ access\n",
3274 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3277 // Add in the full share name to pass back
3280 if( uniRemainingPath.Buffer != NULL)
3284 // This routine strips off the leading slash so add it back in
3287 uniRemainingPath.Buffer--;
3288 uniRemainingPath.Length += sizeof( WCHAR);
3289 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3292 // And the cell name
3295 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3296 uniRemainingPath.Length += uniComponentName.Length;
3297 uniRemainingPath.MaximumLength += uniComponentName.Length;
3299 uniComponentName = uniRemainingPath;
3304 *FileName = uniComponentName;
3306 *ParentDirectoryCB = pDirEntry;
3308 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3310 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
3312 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3313 AFS_TRACE_LEVEL_VERBOSE,
3314 "AFSParseName Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
3315 &pDirEntry->NameInformation.FileName,
3318 pDirEntry->OpenReferenceCount);
3320 try_return( ntStatus = STATUS_SUCCESS);
3324 // Determine the 'share' we are accessing
3327 ulCRC = AFSGenerateCRC( &uniComponentName,
3330 AFSAcquireShared( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3333 bReleaseTreeLock = TRUE;
3335 AFSLocateCaseSensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
3339 if( pDirEntry == NULL)
3342 ulCRC = AFSGenerateCRC( &uniComponentName,
3345 AFSLocateCaseInsensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
3349 if( pDirEntry == NULL)
3353 // OK, if this component is a valid short name then try
3354 // a lookup in the short name tree
3357 if( RtlIsNameLegalDOS8Dot3( &uniComponentName,
3362 AFSLocateShortNameDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.ShortNameTree,
3367 if( pDirEntry == NULL)
3371 // Check with the service whether it is a valid cell name
3374 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3376 bReleaseTreeLock = FALSE;
3378 ntStatus = AFSCheckCellName( AuthGroup,
3382 if( !NT_SUCCESS( ntStatus))
3384 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3387 uniRemainingPath.Length == 0 &&
3388 ntStatus == STATUS_OBJECT_PATH_NOT_FOUND)
3391 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
3394 try_return( ntStatus);
3400 if( bReleaseTreeLock)
3402 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3406 // Be sure we are starting from the correct volume
3409 if( pDirEntry->ObjectInformation->VolumeCB != AFSGlobalRoot)
3413 // We dropped the global root in the CheckCellName routine which is the
3414 // only way we can be here
3417 pVolumeCB = pDirEntry->ObjectInformation->VolumeCB;
3420 // In this case don't add back in the 'share' name since that is where we are
3421 // starting. Just put the leading slash back in
3424 if( uniRemainingPath.Buffer != NULL)
3427 uniRemainingPath.Buffer--;
3428 uniRemainingPath.Length += sizeof( WCHAR);
3429 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3431 if( uniRemainingPath.Length > sizeof( WCHAR))
3434 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3438 // Pass back the parent being the root of the volume
3441 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3447 // Pass back a root slash
3450 uniRemainingPath = uniComponentName;
3452 uniRemainingPath.Buffer--;
3453 uniRemainingPath.Length = sizeof( WCHAR);
3454 uniRemainingPath.MaximumLength = sizeof( WCHAR);
3457 // This is a root open so pass back no parent
3460 *ParentDirectoryCB = NULL;
3466 pVolumeCB = AFSGlobalRoot;
3469 // Add back in the 'share' portion of the name since we will parse it out on return
3472 if( uniRemainingPath.Buffer != NULL)
3476 // This routine strips off the leading slash so add it back in
3479 uniRemainingPath.Buffer--;
3480 uniRemainingPath.Length += sizeof( WCHAR);
3481 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3483 if( uniRemainingPath.Length > sizeof( WCHAR))
3486 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3490 // And the cell name
3493 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3494 uniRemainingPath.Length += uniComponentName.Length;
3495 uniRemainingPath.MaximumLength += uniComponentName.Length;
3500 uniRemainingPath = uniComponentName;
3504 // And the leading slash again ...
3507 uniRemainingPath.Buffer--;
3508 uniRemainingPath.Length += sizeof( WCHAR);
3509 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3511 InterlockedIncrement( &pVolumeCB->DirectoryCB->OpenReferenceCount);
3513 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3514 AFS_TRACE_LEVEL_VERBOSE,
3515 "AFSParseName Increment6 count on %wZ DE %p Ccb %p Cnt %d\n",
3516 &pVolumeCB->DirectoryCB->NameInformation.FileName,
3517 pVolumeCB->DirectoryCB,
3519 pVolumeCB->DirectoryCB->OpenReferenceCount);
3522 // Pass back the parent being the volume root
3525 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3529 // We only need the volume shared at this point
3532 AFSConvertToShared( pVolumeCB->VolumeLock);
3535 // Init our name array
3538 pNameArray = AFSInitNameArray( pVolumeCB->DirectoryCB,
3541 if( pNameArray == NULL)
3544 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3545 AFS_TRACE_LEVEL_VERBOSE,
3546 "AFSParseName (%08lX) Failed to initialize name array\n",
3549 AFSReleaseResource( pVolumeCB->VolumeLock);
3551 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3555 // Return the remaining portion as the file name
3558 *FileName = uniRemainingPath;
3560 *ParsedFileName = uniRemainingPath;
3562 *NameArray = pNameArray;
3564 *VolumeCB = pVolumeCB;
3567 // Increment our reference on the volume
3570 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
3572 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3573 AFS_TRACE_LEVEL_VERBOSE,
3574 "AFSParseName Increment2 count on global volume %08lX Cnt %d\n",
3576 pVolumeCB->VolumeReferenceCount);
3580 if( NT_SUCCESS( ntStatus))
3583 if( *ParentDirectoryCB != NULL)
3586 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3587 AFS_TRACE_LEVEL_VERBOSE,
3588 "AFSParseName Count on %wZ DE %p Ccb %p Cnt %d\n",
3589 &(*ParentDirectoryCB)->NameInformation.FileName,
3592 (*ParentDirectoryCB)->OpenReferenceCount);
3596 if( *VolumeCB != NULL)
3599 ASSERT( (*VolumeCB)->VolumeReferenceCount > 1);
3602 if( ntStatus != STATUS_SUCCESS)
3605 if( pNameArray != NULL)
3608 AFSFreeNameArray( pNameArray);
3617 AFSCheckCellName( IN GUID *AuthGroup,
3618 IN UNICODE_STRING *CellName,
3619 OUT AFSDirectoryCB **ShareDirEntry)
3622 NTSTATUS ntStatus = STATUS_SUCCESS;
3623 UNICODE_STRING uniName;
3625 AFSDirEnumEntry *pDirEnumEntry = NULL;
3626 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3627 AFSDirHdr *pDirHdr = &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr;
3628 AFSDirectoryCB *pDirNode = NULL;
3629 UNICODE_STRING uniDirName, uniTargetName;
3630 AFSVolumeCB *pVolumeCB = NULL;
3636 // Look for some default names we will not handle
3639 RtlInitUnicodeString( &uniName,
3642 if( RtlCompareUnicodeString( &uniName,
3647 try_return( ntStatus = STATUS_NO_SUCH_FILE);
3650 RtlInitUnicodeString( &uniName,
3653 if( RtlCompareUnicodeString( &uniName,
3658 try_return( ntStatus = STATUS_NO_SUCH_FILE);
3661 RtlInitUnicodeString( &uniName,
3664 if( RtlCompareUnicodeString( &uniName,
3669 try_return( ntStatus = STATUS_NO_SUCH_FILE);
3672 RtlInitUnicodeString( &uniName,
3675 if( RtlCompareUnicodeString( &uniName,
3680 try_return( ntStatus = STATUS_NO_SUCH_FILE);
3684 // OK, ask the CM about this component name
3687 stFileID = AFSGlobalRoot->ObjectInformation.FileId;
3689 ntStatus = AFSEvaluateTargetByName( AuthGroup,
3694 if( !NT_SUCCESS( ntStatus))
3697 try_return( ntStatus);
3701 // OK, we have a dir enum entry back so add it to the root node
3704 uniDirName = *CellName;
3706 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
3707 uniTargetName.MaximumLength = uniTargetName.Length;
3708 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
3711 // Is this entry a root volume entry?
3714 if( pDirEnumEntry->FileId.Cell != AFSGlobalRoot->ObjectInformation.FileId.Cell ||
3715 pDirEnumEntry->FileId.Volume != AFSGlobalRoot->ObjectInformation.FileId.Volume)
3719 // We have the global root on entry so drop it now
3722 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3725 // Build the root volume entry
3728 ntStatus = AFSBuildRootVolume( AuthGroup,
3729 &pDirEnumEntry->FileId,
3732 if( !NT_SUCCESS( ntStatus))
3736 // On failure this routine is expecting to hold the global root
3739 AFSAcquireShared( AFSGlobalRoot->VolumeLock,
3742 try_return( ntStatus);
3745 *ShareDirEntry = pVolumeCB->DirectoryCB;
3747 InterlockedIncrement( &pVolumeCB->DirectoryCB->OpenReferenceCount);
3749 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3750 AFS_TRACE_LEVEL_VERBOSE,
3751 "AFSCheckCellName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
3752 &pVolumeCB->DirectoryCB->NameInformation.FileName,
3753 pVolumeCB->DirectoryCB,
3755 pVolumeCB->DirectoryCB->OpenReferenceCount);
3757 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
3762 pDirNode = AFSInitDirEntry( &AFSGlobalRoot->ObjectInformation,
3766 (ULONG)InterlockedIncrement( &pDirHdr->ContentIndex));
3768 if( pDirNode == NULL)
3771 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3775 // Init the short name if we have one
3778 if( pDirEnumEntry->ShortNameLength > 0)
3781 pDirNode->NameInformation.ShortNameLength = pDirEnumEntry->ShortNameLength;
3783 RtlCopyMemory( pDirNode->NameInformation.ShortName,
3784 pDirEnumEntry->ShortName,
3785 pDirNode->NameInformation.ShortNameLength);
3788 AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3792 // Insert the node into the name tree
3795 ASSERT( ExIsResourceAcquiredExclusiveLite( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock));
3797 if( pDirHdr->CaseSensitiveTreeHead == NULL)
3800 pDirHdr->CaseSensitiveTreeHead = pDirNode;
3805 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( pDirHdr->CaseSensitiveTreeHead,
3809 AFSDeleteDirEntry( &AFSGlobalRoot->ObjectInformation,
3812 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3814 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3818 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
3820 if( pDirHdr->CaseInsensitiveTreeHead == NULL)
3823 pDirHdr->CaseInsensitiveTreeHead = pDirNode;
3825 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
3830 AFSInsertCaseInsensitiveDirEntry( pDirHdr->CaseInsensitiveTreeHead,
3834 if( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead == NULL)
3837 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead = pDirNode;
3842 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
3844 pDirNode->ListEntry.bLink = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail;
3847 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail = pDirNode;
3849 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
3851 InterlockedIncrement( &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeCount);
3853 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
3854 AFS_TRACE_LEVEL_VERBOSE,
3855 "AFSCheckCellName Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
3856 &pDirNode->NameInformation.FileName,
3857 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeCount,
3858 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3859 AFSGlobalRoot->ObjectInformation.FileId.Volume,
3860 AFSGlobalRoot->ObjectInformation.FileId.Vnode,
3861 AFSGlobalRoot->ObjectInformation.FileId.Unique);
3863 InterlockedIncrement( &pDirNode->OpenReferenceCount);
3865 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3866 AFS_TRACE_LEVEL_VERBOSE,
3867 "AFSCheckCellName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3868 &pDirNode->NameInformation.FileName,
3871 pDirNode->OpenReferenceCount);
3873 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3876 // Pass back the dir node
3879 *ShareDirEntry = pDirNode;
3884 if( pDirEnumEntry != NULL)
3887 AFSExFreePool( pDirEnumEntry);
3895 AFSBuildMountPointTarget( IN GUID *AuthGroup,
3896 IN AFSDirectoryCB *DirectoryCB,
3897 OUT AFSVolumeCB **TargetVolumeCB)
3900 NTSTATUS ntStatus = STATUS_SUCCESS;
3901 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
3902 AFSDirEnumEntry *pDirEntry = NULL;
3903 AFSDirectoryCB *pDirNode = NULL;
3904 UNICODE_STRING uniDirName, uniTargetName;
3905 ULONGLONG ullIndex = 0;
3906 AFSVolumeCB *pVolumeCB = NULL;
3907 AFSFileID stTargetFileID;
3913 // Loop on each entry, building the chain until we encounter the final target
3916 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3917 AFS_TRACE_LEVEL_VERBOSE_2,
3918 "AFSBuildMountPointTarget Building target directory for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3919 &DirectoryCB->NameInformation.FileName,
3920 DirectoryCB->ObjectInformation->FileId.Cell,
3921 DirectoryCB->ObjectInformation->FileId.Volume,
3922 DirectoryCB->ObjectInformation->FileId.Vnode,
3923 DirectoryCB->ObjectInformation->FileId.Unique);
3926 // Do we need to evaluate the node?
3929 //if( DirectoryCB->ObjectInformation->TargetFileId.Vnode == 0 &&
3930 // DirectoryCB->ObjectInformation->TargetFileId.Unique == 0)
3934 // Go evaluate the current target to get the target fid
3937 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3938 AFS_TRACE_LEVEL_VERBOSE_2,
3939 "AFSBuildMountPointTarget Evaluating target %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3940 &DirectoryCB->NameInformation.FileName,
3941 DirectoryCB->ObjectInformation->FileId.Cell,
3942 DirectoryCB->ObjectInformation->FileId.Volume,
3943 DirectoryCB->ObjectInformation->FileId.Vnode,
3944 DirectoryCB->ObjectInformation->FileId.Unique);
3946 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
3951 if( !NT_SUCCESS( ntStatus))
3954 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3955 AFS_TRACE_LEVEL_ERROR,
3956 "AFSBuildMountPointTarget Failed to evaluate target %wZ Status %08lX\n",
3957 &DirectoryCB->NameInformation.FileName,
3959 try_return( ntStatus);
3962 if( pDirEntry->TargetFileId.Vnode == 0 &&
3963 pDirEntry->TargetFileId.Unique == 0)
3966 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3967 AFS_TRACE_LEVEL_ERROR,
3968 "AFSBuildMountPointTarget Target %wZ FID %08lX-%08lX-%08lX-%08lX service returned zero FID\n",
3969 &DirectoryCB->NameInformation.FileName,
3970 DirectoryCB->ObjectInformation->FileId.Cell,
3971 DirectoryCB->ObjectInformation->FileId.Volume,
3972 DirectoryCB->ObjectInformation->FileId.Vnode,
3973 DirectoryCB->ObjectInformation->FileId.Unique);
3975 try_return( ntStatus = STATUS_ACCESS_DENIED);
3978 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
3981 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
3982 &DirectoryCB->Flags,
3983 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
3984 (USHORT)pDirEntry->TargetNameLength);
3986 if( !NT_SUCCESS( ntStatus))
3989 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
3991 try_return( ntStatus);
3994 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
3996 DirectoryCB->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
3999 stTargetFileID = DirectoryCB->ObjectInformation->TargetFileId;
4002 // Try to locate this FID. First the volume then the
4006 ullIndex = AFSCreateHighIndex( &stTargetFileID);
4008 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4009 AFS_TRACE_LEVEL_VERBOSE,
4010 "AFSBuildMountPointTarget Acquiring RDR VolumeTreeLock lock %08lX EXCL %08lX\n",
4011 &pDevExt->Specific.RDR.VolumeTreeLock,
4012 PsGetCurrentThread());
4014 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4017 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4018 AFS_TRACE_LEVEL_VERBOSE_2,
4019 "AFSBuildMountPointTarget Locating volume for target %I64X\n",
4022 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4024 (AFSBTreeEntry **)&pVolumeCB);
4027 // We can be processing a request for a target that is on a volume
4028 // we have never seen before.
4031 if( pVolumeCB == NULL)
4035 // Locking is held correctly in init routine
4038 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4041 // Go init the root of the volume
4044 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4045 AFS_TRACE_LEVEL_VERBOSE_2,
4046 "AFSBuildMountPointTarget Initializing root for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4047 &DirectoryCB->NameInformation.FileName,
4048 DirectoryCB->ObjectInformation->FileId.Cell,
4049 DirectoryCB->ObjectInformation->FileId.Volume,
4050 DirectoryCB->ObjectInformation->FileId.Vnode,
4051 DirectoryCB->ObjectInformation->FileId.Unique);
4053 ntStatus = AFSInitVolume( AuthGroup,
4057 if( !NT_SUCCESS( ntStatus))
4060 try_return( ntStatus);
4067 // Check if this volume has been deleted or taken offline
4070 if( BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
4073 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4075 try_return( ntStatus = STATUS_FILE_IS_OFFLINE);
4079 // Just to ensure that things don't get torn down AND we don't create a
4080 // deadlock with invalidation
4083 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
4085 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4087 AFSAcquireExcl( pVolumeCB->VolumeLock,
4090 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
4093 if( pVolumeCB->RootFcb == NULL)
4097 // Initialize the root fcb for this volume
4100 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4103 if( !NT_SUCCESS( ntStatus))
4106 AFSReleaseResource( pVolumeCB->VolumeLock);
4108 try_return( ntStatus);
4112 // Drop the lock acquired above
4115 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4118 AFSConvertToShared( pVolumeCB->VolumeLock);
4120 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4121 AFS_TRACE_LEVEL_VERBOSE_2,
4122 "AFSBuildMountPointTarget Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4123 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4124 pVolumeCB->ObjectInformation.FileId.Cell,
4125 pVolumeCB->ObjectInformation.FileId.Volume,
4126 pVolumeCB->ObjectInformation.FileId.Vnode,
4127 pVolumeCB->ObjectInformation.FileId.Unique);
4129 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
4131 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4132 AFS_TRACE_LEVEL_VERBOSE,
4133 "AFSBuildMountPointTarget Increment count on volume %08lX Cnt %d\n",
4135 pVolumeCB->VolumeReferenceCount);
4137 *TargetVolumeCB = pVolumeCB;
4144 AFSExFreePool( pDirEntry);
4152 AFSBuildRootVolume( IN GUID *AuthGroup,
4153 IN AFSFileID *FileId,
4154 OUT AFSVolumeCB **TargetVolumeCB)
4157 NTSTATUS ntStatus = STATUS_SUCCESS;
4158 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4159 AFSDirectoryCB *pDirNode = NULL;
4160 UNICODE_STRING uniDirName, uniTargetName;
4161 ULONGLONG ullIndex = 0;
4162 AFSVolumeCB *pVolumeCB = NULL;
4167 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4168 AFS_TRACE_LEVEL_VERBOSE_2,
4169 "AFSBuildRootVolume Building target volume for FID %08lX-%08lX-%08lX-%08lX\n",
4175 ullIndex = AFSCreateHighIndex( FileId);
4177 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4178 AFS_TRACE_LEVEL_VERBOSE,
4179 "AFSBuildRootVolume Acquiring RDR VolumeTreeLock lock %08lX EXCL %08lX\n",
4180 &pDevExt->Specific.RDR.VolumeTreeLock,
4181 PsGetCurrentThread());
4183 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4186 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4187 AFS_TRACE_LEVEL_VERBOSE_2,
4188 "AFSBuildRootVolume Locating volume for target %I64X\n",
4191 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4193 (AFSBTreeEntry **)&pVolumeCB);
4196 // We can be processing a request for a target that is on a volume
4197 // we have never seen before.
4200 if( pVolumeCB == NULL)
4204 // Locking is held correctly in init routine
4207 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4210 // Go init the root of the volume
4213 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4214 AFS_TRACE_LEVEL_VERBOSE_2,
4215 "AFSBuildRootVolume Initializing root for FID %08lX-%08lX-%08lX-%08lX\n",
4221 ntStatus = AFSInitVolume( AuthGroup,
4225 if( !NT_SUCCESS( ntStatus))
4228 try_return( ntStatus);
4235 // Just to ensure that things don't get torn down AND we don't create a
4236 // deadlock with invalidation
4239 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
4241 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4243 AFSAcquireExcl( pVolumeCB->VolumeLock,
4246 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
4250 if( pVolumeCB->RootFcb == NULL)
4254 // Initialize the root fcb for this volume
4257 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4260 if( !NT_SUCCESS( ntStatus))
4263 AFSReleaseResource( pVolumeCB->VolumeLock);
4265 try_return( ntStatus);
4269 // Drop the lock acquired above
4272 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4275 AFSConvertToShared( pVolumeCB->VolumeLock);
4277 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4278 AFS_TRACE_LEVEL_VERBOSE_2,
4279 "AFSBuildRootVolume Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4280 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4281 pVolumeCB->ObjectInformation.FileId.Cell,
4282 pVolumeCB->ObjectInformation.FileId.Volume,
4283 pVolumeCB->ObjectInformation.FileId.Vnode,
4284 pVolumeCB->ObjectInformation.FileId.Unique);
4286 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
4288 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4289 AFS_TRACE_LEVEL_VERBOSE,
4290 "AFSBuildRootVolume Increment count on volume %08lX Cnt %d\n",
4292 pVolumeCB->VolumeReferenceCount);
4294 *TargetVolumeCB = pVolumeCB;
4305 AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
4306 IN PFILE_OBJECT FileObject,
4307 IN UNICODE_STRING *RemainingPath)
4310 NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
4311 UNICODE_STRING uniReparseName;
4312 UNICODE_STRING uniMUPDeviceName;
4313 AFSDirEnumEntry *pDirEntry = NULL;
4314 GUID *pAuthGroup = NULL;
4320 // Build up the name to reparse
4323 RtlInitUnicodeString( &uniMUPDeviceName,
4326 uniReparseName.Length = 0;
4327 uniReparseName.Buffer = NULL;
4330 // Be sure we have a target name
4333 if( DirEntry->NameInformation.TargetName.Length == 0)
4336 if( DirEntry->ObjectInformation->Fcb != NULL)
4338 pAuthGroup = &DirEntry->ObjectInformation->Fcb->AuthGroup;
4341 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
4346 if( !NT_SUCCESS( ntStatus) ||
4347 pDirEntry->TargetNameLength == 0)
4350 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4351 AFS_TRACE_LEVEL_ERROR,
4352 "AFSProcessDFSLink EvaluateTargetByID failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4353 &DirEntry->NameInformation.FileName,
4354 DirEntry->ObjectInformation->FileId.Cell,
4355 DirEntry->ObjectInformation->FileId.Volume,
4356 DirEntry->ObjectInformation->FileId.Vnode,
4357 DirEntry->ObjectInformation->FileId.Unique,
4360 if( NT_SUCCESS( ntStatus))
4363 ntStatus = STATUS_ACCESS_DENIED;
4366 try_return( ntStatus);
4370 // Update the target name
4373 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
4376 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
4378 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4379 (USHORT)pDirEntry->TargetNameLength);
4381 if( !NT_SUCCESS( ntStatus))
4384 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4385 AFS_TRACE_LEVEL_ERROR,
4386 "AFSProcessDFSLink UpdateTargetName failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4387 &DirEntry->NameInformation.FileName,
4388 DirEntry->ObjectInformation->FileId.Cell,
4389 DirEntry->ObjectInformation->FileId.Volume,
4390 DirEntry->ObjectInformation->FileId.Vnode,
4391 DirEntry->ObjectInformation->FileId.Unique,
4394 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4396 try_return( ntStatus);
4399 AFSConvertToShared( &DirEntry->NonPaged->Lock);
4403 AFSAcquireShared( &DirEntry->NonPaged->Lock,
4407 uniReparseName.MaximumLength = uniMUPDeviceName.Length +
4409 DirEntry->NameInformation.TargetName.Length +
4412 if( RemainingPath != NULL &&
4413 RemainingPath->Length > 0)
4416 uniReparseName.MaximumLength += RemainingPath->Length;
4420 // Allocate the reparse buffer
4423 uniReparseName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4424 uniReparseName.MaximumLength,
4425 AFS_REPARSE_NAME_TAG);
4427 if( uniReparseName.Buffer == NULL)
4430 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4431 AFS_TRACE_LEVEL_ERROR,
4432 "AFSProcessDFSLink uniReparseName.Buffer == NULL Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4433 &DirEntry->NameInformation.FileName,
4434 DirEntry->ObjectInformation->FileId.Cell,
4435 DirEntry->ObjectInformation->FileId.Volume,
4436 DirEntry->ObjectInformation->FileId.Vnode,
4437 DirEntry->ObjectInformation->FileId.Unique,
4438 STATUS_INSUFFICIENT_RESOURCES);
4440 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4442 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4446 // Start building the name
4449 RtlCopyMemory( uniReparseName.Buffer,
4450 uniMUPDeviceName.Buffer,
4451 uniMUPDeviceName.Length);
4453 uniReparseName.Length = uniMUPDeviceName.Length;
4455 if( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\')
4458 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
4460 uniReparseName.Length += sizeof( WCHAR);
4463 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
4464 DirEntry->NameInformation.TargetName.Buffer,
4465 DirEntry->NameInformation.TargetName.Length);
4467 uniReparseName.Length += DirEntry->NameInformation.TargetName.Length;
4469 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4471 if( RemainingPath != NULL &&
4472 RemainingPath->Length > 0)
4475 if( uniReparseName.Buffer[ (uniReparseName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
4476 RemainingPath->Buffer[ 0] != L'\\')
4479 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
4481 uniReparseName.Length += sizeof( WCHAR);
4484 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
4485 RemainingPath->Buffer,
4486 RemainingPath->Length);
4488 uniReparseName.Length += RemainingPath->Length;
4492 // Update the name in the file object
4495 if( FileObject->FileName.Buffer != NULL)
4498 AFSExFreePool( FileObject->FileName.Buffer);
4501 FileObject->FileName = uniReparseName;
4503 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4504 AFS_TRACE_LEVEL_VERBOSE,
4505 "AFSProcessDFSLink Reparsing access to Fcb %wZ FID %08lX-%08lX-%08lX-%08lX to %wZ\n",
4506 &DirEntry->NameInformation.FileName,
4507 DirEntry->ObjectInformation->FileId.Cell,
4508 DirEntry->ObjectInformation->FileId.Volume,
4509 DirEntry->ObjectInformation->FileId.Vnode,
4510 DirEntry->ObjectInformation->FileId.Unique,
4514 // Return status reparse ...
4517 ntStatus = STATUS_REPARSE;
4524 AFSExFreePool( pDirEntry);