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,
157 STATUS_FILE_DELETED);
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,
174 STATUS_DELETE_PENDING);
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);
199 // Directory TreeLock should be exclusively held
202 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
205 ntStatus = AFSVerifyEntry( AuthGroup,
208 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
210 if( !NT_SUCCESS( ntStatus))
213 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
214 AFS_TRACE_LEVEL_ERROR,
215 "AFSLocateNameEntry (FO: %08lX) Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
217 &pDirEntry->NameInformation.FileName,
218 pCurrentObject->FileId.Cell,
219 pCurrentObject->FileId.Volume,
220 pCurrentObject->FileId.Vnode,
221 pCurrentObject->FileId.Unique,
224 try_return( ntStatus);
229 // Ensure the parent node has been evaluated, if not then go do it now
232 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) ||
233 pCurrentObject->FileType == AFS_FILE_TYPE_UNKNOWN)
236 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
237 AFS_TRACE_LEVEL_VERBOSE,
238 "AFSLocateNameEntry (FO: %08lX) Evaluating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
240 &pDirEntry->NameInformation.FileName,
241 pCurrentObject->FileId.Cell,
242 pCurrentObject->FileId.Volume,
243 pCurrentObject->FileId.Vnode,
244 pCurrentObject->FileId.Unique);
246 ntStatus = AFSEvaluateNode( AuthGroup,
249 if( !NT_SUCCESS( ntStatus))
252 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
253 AFS_TRACE_LEVEL_ERROR,
254 "AFSLocateNameEntry (FO: %08lX) Failed to evaluate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
256 &pDirEntry->NameInformation.FileName,
257 pCurrentObject->FileId.Cell,
258 pCurrentObject->FileId.Volume,
259 pCurrentObject->FileId.Vnode,
260 pCurrentObject->FileId.Unique,
263 try_return( ntStatus);
266 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
270 // If this is a mount point or symlink then go get the real directory node
273 switch( pCurrentObject->FileType)
276 case AFS_FILE_TYPE_SYMLINK:
279 UNICODE_STRING uniTempName;
280 WCHAR *pTmpBuffer = NULL;
284 // Check if the flag is set to NOT evaluate a symlink
285 // and we are done with the parsing
288 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL) &&
289 uniRemainingPath.Length == 0)
293 // Pass back the directory entries
296 *ParentDirectoryCB = pParentDirEntry;
298 *DirectoryCB = pDirEntry;
300 *VolumeCB = pCurrentVolume;
302 *RootPathName = uniFullPathName;
304 try_return( ntStatus);
307 AFSAcquireExcl( &pDirEntry->NonPaged->Lock,
310 if( pDirEntry->NameInformation.TargetName.Length == 0)
314 // We'll reset the DV to ensure we validate the metadata content
317 pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
319 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
321 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
322 AFS_TRACE_LEVEL_VERBOSE,
323 "AFSLocateNameEntry (FO: %08lX) Verifying symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
325 &pDirEntry->NameInformation.FileName,
326 pCurrentObject->FileId.Cell,
327 pCurrentObject->FileId.Volume,
328 pCurrentObject->FileId.Vnode,
329 pCurrentObject->FileId.Unique);
332 // Directory TreeLock should be exclusively held
335 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
338 ntStatus = AFSVerifyEntry( AuthGroup,
341 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
343 if( !NT_SUCCESS( ntStatus))
346 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
347 AFS_TRACE_LEVEL_ERROR,
348 "AFSLocateNameEntry (FO: %08lX) Failed to verify symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
350 &pDirEntry->NameInformation.FileName,
351 pCurrentObject->FileId.Cell,
352 pCurrentObject->FileId.Volume,
353 pCurrentObject->FileId.Vnode,
354 pCurrentObject->FileId.Unique,
357 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
359 try_return( ntStatus);
363 // If the type changed then reprocess this entry
366 if( pCurrentObject->FileType != AFS_FILE_TYPE_SYMLINK)
369 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
376 // If we were given a zero length target name then deny access to the entry
379 if( pDirEntry->NameInformation.TargetName.Length == 0)
382 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
384 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
385 AFS_TRACE_LEVEL_ERROR,
386 "AFSLocateNameEntry (FO: %08lX) Failed to retrieve target name for symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
388 &pDirEntry->NameInformation.FileName,
389 pCurrentObject->FileId.Cell,
390 pCurrentObject->FileId.Volume,
391 pCurrentObject->FileId.Vnode,
392 pCurrentObject->FileId.Unique,
395 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
397 try_return( ntStatus);
400 if( AFSIsRelativeName( &pDirEntry->NameInformation.TargetName))
403 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
404 AFS_TRACE_LEVEL_VERBOSE,
405 "AFSLocateNameEntry (FO: %08lX) Processing relative symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
407 &pDirEntry->NameInformation.TargetName,
408 &pDirEntry->NameInformation.FileName,
409 pCurrentObject->FileId.Cell,
410 pCurrentObject->FileId.Volume,
411 pCurrentObject->FileId.Vnode,
412 pCurrentObject->FileId.Unique);
415 // We'll substitute this name into the current process name
416 // starting at where we sit in the path
419 uniTempName.Length = 0;
420 uniTempName.MaximumLength = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer) +
421 pDirEntry->NameInformation.TargetName.Length +
423 uniRemainingPath.Length;
425 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
426 uniTempName.MaximumLength,
427 AFS_NAME_BUFFER_ONE_TAG);
429 if( uniTempName.Buffer == NULL)
432 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
434 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
438 // We have so first copy in the portion up to the component
442 RtlCopyMemory( uniTempName.Buffer,
443 uniFullPathName.Buffer,
444 (ULONG)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer));
446 uniTempName.Length = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer);
448 if( bAllocatedSymLinkBuffer ||
452 pTmpBuffer = uniFullPathName.Buffer;
455 bAllocatedSymLinkBuffer = TRUE;
458 // Have we parsed this name yet? Better have at least once ...
461 if( uniComponentName.Length == 0)
467 // Copy in the target name ...
470 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
471 pDirEntry->NameInformation.TargetName.Buffer,
472 pDirEntry->NameInformation.TargetName.Length);
474 uniPathName.Buffer = &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)];
476 uniPathName.Length += pDirEntry->NameInformation.TargetName.Length;
477 uniPathName.MaximumLength = uniTempName.MaximumLength;
479 uniTempName.Length += pDirEntry->NameInformation.TargetName.Length;
482 // And now any remaining portion of the name
485 if( uniRemainingPath.Length > 0)
488 if( uniRemainingPath.Buffer[ 0] != L'\\')
491 uniRemainingPath.Buffer--;
492 uniRemainingPath.Length += sizeof( WCHAR);
494 uniPathName.Length += sizeof( WCHAR);
497 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
498 uniRemainingPath.Buffer,
499 uniRemainingPath.Length);
501 uniTempName.Length += uniRemainingPath.Length;
504 uniFullPathName = uniTempName;
506 if( pTmpBuffer != NULL)
509 AFSExFreePool( pTmpBuffer);
512 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
515 // Dereference the current entry ..
518 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
520 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
521 AFS_TRACE_LEVEL_VERBOSE,
522 "AFSLocateNameEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
523 &pDirEntry->NameInformation.FileName,
526 pDirEntry->OpenReferenceCount);
529 // OK, need to back up one entry for the correct parent since the current
530 // entry we are on is the symlink itself
533 pDirEntry = AFSBackupEntry( pNameArray);
536 // Increment our reference on this dir entry
539 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
541 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
542 AFS_TRACE_LEVEL_VERBOSE,
543 "AFSLocateNameEntry Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
544 &pDirEntry->NameInformation.FileName,
547 pDirEntry->OpenReferenceCount);
549 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
552 pParentDirEntry = NULL;
557 pParentDirEntry = AFSGetParentEntry( pNameArray);
559 ASSERT( pParentDirEntry != pDirEntry);
565 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
566 AFS_TRACE_LEVEL_VERBOSE,
567 "AFSLocateNameEntry (FO: %08lX) Processing absolute symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
569 &pDirEntry->NameInformation.TargetName,
570 &pDirEntry->NameInformation.FileName,
571 pCurrentObject->FileId.Cell,
572 pCurrentObject->FileId.Volume,
573 pCurrentObject->FileId.Vnode,
574 pCurrentObject->FileId.Unique);
577 // We'll substitute this name into the current process name
578 // starting at where we sit in the path
581 uniTempName.Length = 0;
582 uniTempName.MaximumLength = pDirEntry->NameInformation.TargetName.Length +
584 uniRemainingPath.Length;
586 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
587 uniTempName.MaximumLength,
588 AFS_NAME_BUFFER_TWO_TAG);
590 if( uniTempName.Buffer == NULL)
593 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
595 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
598 if( bAllocatedSymLinkBuffer ||
602 pTmpBuffer = uniFullPathName.Buffer;
605 bAllocatedSymLinkBuffer = TRUE;
608 // Have we parsed this name yet? Better have at least once ...
611 if( uniComponentName.Length == 0)
617 // Copy in the target name ...
620 RtlCopyMemory( uniTempName.Buffer,
621 pDirEntry->NameInformation.TargetName.Buffer,
622 pDirEntry->NameInformation.TargetName.Length);
624 uniTempName.Length = pDirEntry->NameInformation.TargetName.Length;
627 // And now any remaining portion of the name
630 if( uniRemainingPath.Length > 0)
633 if( uniRemainingPath.Buffer[ 0] != L'\\')
636 uniRemainingPath.Buffer--;
637 uniRemainingPath.Length += sizeof( WCHAR);
640 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
641 uniRemainingPath.Buffer,
642 uniRemainingPath.Length);
644 uniTempName.Length += uniRemainingPath.Length;
647 uniFullPathName = uniTempName;
649 uniPathName = uniTempName;
651 if( pTmpBuffer != NULL)
654 AFSExFreePool( pTmpBuffer);
657 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
660 // If our current volume is not the global root then make it so ...
663 if( pCurrentVolume != AFSGlobalRoot)
666 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
667 AFS_TRACE_LEVEL_VERBOSE,
668 "AFSLocateNameEntry (FO: %08lX) Current volume not global, resetting for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
670 &pDirEntry->NameInformation.FileName,
671 pCurrentObject->FileId.Cell,
672 pCurrentObject->FileId.Volume,
673 pCurrentObject->FileId.Vnode,
674 pCurrentObject->FileId.Unique);
676 InterlockedDecrement( &pCurrentVolume->VolumeReferenceCount);
678 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
679 AFS_TRACE_LEVEL_VERBOSE,
680 "AFSLocateNameEntry Decrement count on volume %08lX Cnt %d\n",
682 pCurrentVolume->VolumeReferenceCount);
684 pCurrentVolume = AFSGlobalRoot;
686 InterlockedIncrement( &pCurrentVolume->VolumeReferenceCount);
688 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
689 AFS_TRACE_LEVEL_VERBOSE,
690 "AFSLocateNameEntry Increment count on volume %08lX Cnt %d\n",
692 pCurrentVolume->VolumeReferenceCount);
696 // Dereference our current dir entry
699 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
701 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
702 AFS_TRACE_LEVEL_VERBOSE,
703 "AFSLocateNameEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
704 &pDirEntry->NameInformation.FileName,
707 pDirEntry->OpenReferenceCount);
709 pDirEntry = pCurrentVolume->DirectoryCB;
712 // Reference the new dir entry
715 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
717 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
718 AFS_TRACE_LEVEL_VERBOSE,
719 "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
720 &pDirEntry->NameInformation.FileName,
723 pDirEntry->OpenReferenceCount);
726 // Reset the name array
727 // Persist the link count in the name array
730 lLinkCount = pNameArray->LinkCount;
732 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
733 AFS_TRACE_LEVEL_VERBOSE,
734 "AFSLocateNameEntry (FO: %08lX) Resetting name array for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
736 &pDirEntry->NameInformation.FileName,
737 pCurrentObject->FileId.Cell,
738 pCurrentObject->FileId.Volume,
739 pCurrentObject->FileId.Vnode,
740 pCurrentObject->FileId.Unique);
742 AFSResetNameArray( pNameArray,
745 pNameArray->LinkCount = lLinkCount;
748 // Process over the \\<Global root> portion of the name
751 FsRtlDissectName( uniPathName,
755 if( RtlCompareUnicodeString( &uniComponentName,
760 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
761 AFS_TRACE_LEVEL_ERROR,
762 "AFSLocateNameEntry Name %wZ contains invalid server name\n",
766 // The correct response would be STATUS_OBJECT_PATH_INVALID
767 // but that prevents cmd.exe from performing a recursive
768 // directory enumeration when opening a directory entry
769 // that represents a symlink to an invalid path is discovered.
771 try_return( ntStatus = STATUS_OBJECT_PATH_NOT_FOUND);
774 uniPathName = uniRemainingPath;
776 pParentDirEntry = NULL;
780 // Increment our link count
783 InterlockedIncrement( &pNameArray->LinkCount);
788 case AFS_FILE_TYPE_MOUNTPOINT:
792 // Check if the flag is set to NOT evaluate a mount point
793 // and we are done with the parsing
796 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL) &&
797 uniRemainingPath.Length == 0)
801 // Pass back the directory entries
804 *ParentDirectoryCB = pParentDirEntry;
806 *DirectoryCB = pDirEntry;
808 *VolumeCB = pCurrentVolume;
810 *RootPathName = uniFullPathName;
812 try_return( ntStatus);
815 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
816 AFS_TRACE_LEVEL_VERBOSE,
817 "AFSLocateNameEntry (FO: %08lX) Building MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
819 &pDirEntry->NameInformation.FileName,
820 pCurrentObject->FileId.Cell,
821 pCurrentObject->FileId.Volume,
822 pCurrentObject->FileId.Vnode,
823 pCurrentObject->FileId.Unique);
826 // Go retrieve the target entry for this node
827 // Release the current volume cb entry since we would
828 // have lock inversion in the following call
829 // Also decrement the ref count on the volume
832 ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
834 InterlockedDecrement( &pCurrentVolume->VolumeReferenceCount);
836 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
837 AFS_TRACE_LEVEL_VERBOSE,
838 "AFSLocateNameEntry Decrement2 count on volume %08lX Cnt %d\n",
840 pCurrentVolume->VolumeReferenceCount);
842 ntStatus = AFSBuildMountPointTarget( AuthGroup,
846 if( !NT_SUCCESS( ntStatus))
849 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
850 AFS_TRACE_LEVEL_ERROR,
851 "AFSLocateNameEntry (FO: %08lX) Failed to build MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
853 &pDirEntry->NameInformation.FileName,
854 pCurrentObject->FileId.Cell,
855 pCurrentObject->FileId.Volume,
856 pCurrentObject->FileId.Vnode,
857 pCurrentObject->FileId.Unique,
861 // We already decremented the current volume above
864 bReleaseCurrentVolume = FALSE;
866 try_return( ntStatus);
869 ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
872 // Replace the current name for the mp with the volume root of the target
875 AFSReplaceCurrentElement( pNameArray,
876 pCurrentVolume->DirectoryCB);
879 // We want to restart processing here on the new parent ...
880 // Deref and ref count the entries
883 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
885 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
886 AFS_TRACE_LEVEL_VERBOSE,
887 "AFSLocateNameEntry Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
888 &pDirEntry->NameInformation.FileName,
891 pDirEntry->OpenReferenceCount);
893 pDirEntry = pCurrentVolume->DirectoryCB;
895 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
897 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
898 AFS_TRACE_LEVEL_VERBOSE,
899 "AFSLocateNameEntry Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
900 &pDirEntry->NameInformation.FileName,
903 pDirEntry->OpenReferenceCount);
905 pParentDirEntry = NULL;
908 // Increment our link count
911 InterlockedIncrement( &pNameArray->LinkCount);
916 case AFS_FILE_TYPE_DFSLINK:
919 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL))
923 // Pass back the directory entries
926 *ParentDirectoryCB = pParentDirEntry;
928 *DirectoryCB = pDirEntry;
930 *VolumeCB = pCurrentVolume;
932 *RootPathName = uniFullPathName;
934 try_return( ntStatus);
938 // This is a DFS link so we need to update the file name and return STATUS_REPARSE to the
939 // system for it to reevaluate it
942 if( FileObject != NULL)
945 ntStatus = AFSProcessDFSLink( pDirEntry,
954 // This is where we have been re-entered from an NP evaluation call via the BuildBranch()
958 ntStatus = STATUS_INVALID_PARAMETER;
961 if( ntStatus != STATUS_SUCCESS &&
962 ntStatus != STATUS_REPARSE)
965 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
966 AFS_TRACE_LEVEL_ERROR,
967 "AFSLocateNameEntry (FO: %08lX) Failed to process DFSLink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
969 &pDirEntry->NameInformation.FileName,
970 pCurrentObject->FileId.Cell,
971 pCurrentObject->FileId.Volume,
972 pCurrentObject->FileId.Vnode,
973 pCurrentObject->FileId.Unique,
977 try_return( ntStatus);
980 case AFS_FILE_TYPE_UNKNOWN:
981 case AFS_FILE_TYPE_INVALID:
985 // Something was not processed ...
988 try_return( ntStatus = STATUS_ACCESS_DENIED);
991 } /* end of switch */
994 // If the parent is not initialized then do it now
997 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
998 !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1001 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1002 AFS_TRACE_LEVEL_VERBOSE,
1003 "AFSLocateNameEntry (FO: %08lX) Enumerating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1005 &pDirEntry->NameInformation.FileName,
1006 pCurrentObject->FileId.Cell,
1007 pCurrentObject->FileId.Volume,
1008 pCurrentObject->FileId.Vnode,
1009 pCurrentObject->FileId.Unique);
1011 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1014 if( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1017 ntStatus = AFSEnumerateDirectory( AuthGroup,
1021 if( !NT_SUCCESS( ntStatus))
1024 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1026 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1027 AFS_TRACE_LEVEL_ERROR,
1028 "AFSLocateNameEntry (FO: %08lX) Failed to enumerate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1030 &pDirEntry->NameInformation.FileName,
1031 pCurrentObject->FileId.Cell,
1032 pCurrentObject->FileId.Volume,
1033 pCurrentObject->FileId.Vnode,
1034 pCurrentObject->FileId.Unique,
1037 try_return( ntStatus);
1040 SetFlag( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1043 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1045 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1048 if( uniPathName.Length > 0)
1051 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1052 AFS_TRACE_LEVEL_ERROR,
1053 "AFSLocateNameEntry (FO: %08lX) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1055 &pDirEntry->NameInformation.FileName,
1056 pCurrentObject->FileId.Cell,
1057 pCurrentObject->FileId.Volume,
1058 pCurrentObject->FileId.Vnode,
1059 pCurrentObject->FileId.Unique);
1061 // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1062 // one of the components of the path is not a directory. However, returning
1063 // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1064 // Instead IIS insists on treating the target file as if it is a directory containing
1065 // a potential web.config file. NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1066 // AFS will follow suit.
1068 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1073 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1074 AFS_TRACE_LEVEL_VERBOSE,
1075 "AFSLocateNameEntry (FO: %08lX) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1077 &pDirEntry->NameInformation.FileName,
1078 pCurrentObject->FileId.Cell,
1079 pCurrentObject->FileId.Volume,
1080 pCurrentObject->FileId.Vnode,
1081 pCurrentObject->FileId.Unique);
1084 // Pass back the directory entries
1087 *ParentDirectoryCB = pParentDirEntry;
1089 *DirectoryCB = pDirEntry;
1091 *VolumeCB = pCurrentVolume;
1093 *RootPathName = uniFullPathName;
1096 try_return( ntStatus);
1100 // If we are at the end of the processing, set our returned information and get out
1103 if( uniPathName.Length == 0)
1106 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1107 AFS_TRACE_LEVEL_VERBOSE,
1108 "AFSLocateNameEntry (FO: %08lX) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1110 &pDirEntry->NameInformation.FileName,
1111 pCurrentObject->FileId.Cell,
1112 pCurrentObject->FileId.Volume,
1113 pCurrentObject->FileId.Vnode,
1114 pCurrentObject->FileId.Unique);
1117 // Pass back the directory entries
1120 *ParentDirectoryCB = pParentDirEntry;
1122 *DirectoryCB = pDirEntry;
1124 *VolumeCB = pCurrentVolume;
1126 *RootPathName = uniFullPathName;
1128 try_return( ntStatus);
1132 // We may have returned to the top of the while( TRUE)
1134 if( bSubstituteName &&
1135 uniSearchName.Buffer != NULL)
1138 AFSExFreePool( uniSearchName.Buffer);
1140 bSubstituteName = FALSE;
1142 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1143 uniSearchName.Buffer = NULL;
1146 ulSubstituteIndex = 1;
1148 ntStatus = STATUS_SUCCESS;
1151 // Get the next component name
1154 FsRtlDissectName( uniPathName,
1159 // Check for the . and .. in the path
1162 if( RtlCompareUnicodeString( &uniComponentName,
1167 uniPathName = uniRemainingPath;
1172 if( RtlCompareUnicodeString( &uniComponentName,
1177 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1178 AFS_TRACE_LEVEL_VERBOSE,
1179 "AFSLocateNameEntry (FO: %08lX) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1181 &pDirEntry->NameInformation.FileName,
1182 pCurrentObject->FileId.Cell,
1183 pCurrentObject->FileId.Volume,
1184 pCurrentObject->FileId.Vnode,
1185 pCurrentObject->FileId.Unique);
1188 // Need to back up one entry in the name array
1191 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
1193 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1194 AFS_TRACE_LEVEL_VERBOSE,
1195 "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1196 &pDirEntry->NameInformation.FileName,
1199 pDirEntry->OpenReferenceCount);
1201 pDirEntry = AFSBackupEntry( NameArray);
1203 if( pDirEntry == NULL)
1206 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1207 AFS_TRACE_LEVEL_ERROR,
1208 "AFSLocateNameEntry AFSBackupEntry failed\n");
1210 try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1213 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1215 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1218 pParentDirEntry = NULL;
1223 pParentDirEntry = AFSGetParentEntry( pNameArray);
1225 ASSERT( pParentDirEntry != pDirEntry);
1228 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1229 AFS_TRACE_LEVEL_VERBOSE,
1230 "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1231 &pDirEntry->NameInformation.FileName,
1234 pDirEntry->OpenReferenceCount);
1236 uniPathName = uniRemainingPath;
1242 // Update our pointers
1245 pParentDirEntry = pDirEntry;
1249 uniSearchName = uniComponentName;
1251 while( pDirEntry == NULL)
1255 // If the SearchName contains @SYS then we perform the substitution.
1256 // If there is no substitution we give up.
1259 if( !bSubstituteName &&
1260 FsRtlIsNameInExpression( &uniSysName,
1266 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1267 AFS_TRACE_LEVEL_VERBOSE_2,
1268 "AFSLocateNameEntry (FO: %08lX) Processing @SYS substitution for %wZ Index %08lX\n",
1273 ntStatus = AFSSubstituteSysName( &uniComponentName,
1277 if ( NT_SUCCESS( ntStatus))
1280 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1281 AFS_TRACE_LEVEL_VERBOSE_2,
1282 "AFSLocateNameEntry (FO: %08lX) Located substitution %wZ for %wZ Index %08lX\n",
1289 // Go reparse the name again
1292 bSubstituteName = TRUE;
1294 ulSubstituteIndex++; // For the next entry, if needed
1296 continue; // while( pDirEntry == NULL)
1301 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1302 AFS_TRACE_LEVEL_ERROR,
1303 "AFSLocateNameEntry (FO: %08lX) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1309 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1313 // Pass back the directory entries
1316 *ParentDirectoryCB = pParentDirEntry;
1318 *DirectoryCB = NULL;
1320 *VolumeCB = pCurrentVolume;
1322 if( ComponentName != NULL)
1325 *ComponentName = uniComponentName;
1328 *RootPathName = uniFullPathName;
1332 // We can't possibly have a pDirEntry since the lookup failed
1334 try_return( ntStatus);
1339 // Generate the CRC on the node and perform a case sensitive lookup
1342 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1343 AFS_TRACE_LEVEL_VERBOSE_2,
1344 "AFSLocateNameEntry (FO: %08lX) Searching for entry %wZ case sensitive\n",
1348 ulCRC = AFSGenerateCRC( &uniSearchName,
1351 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1354 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1358 if( pDirEntry == NULL)
1362 // Missed so perform a case insensitive lookup
1365 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1366 AFS_TRACE_LEVEL_VERBOSE_2,
1367 "AFSLocateNameEntry (FO: %08lX) Searching for entry %wZ case insensitive\n",
1371 ulCRC = AFSGenerateCRC( &uniSearchName,
1374 AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1378 if( pDirEntry == NULL)
1382 // OK, if this component is a valid short name then try
1383 // a lookup in the short name tree
1386 if( RtlIsNameLegalDOS8Dot3( &uniSearchName,
1391 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1392 AFS_TRACE_LEVEL_VERBOSE_2,
1393 "AFSLocateNameEntry (FO: %08lX) Searching for entry %wZ short name\n",
1397 AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1402 if( pDirEntry == NULL)
1406 // If we substituted a name then reset our search name and try again
1409 if( bSubstituteName)
1412 AFSExFreePool( uniSearchName.Buffer);
1414 uniSearchName = uniComponentName;
1416 bSubstituteName = FALSE;
1418 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1420 continue; // while( pDirEntry == NULL)
1423 if( uniRemainingPath.Length > 0)
1426 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1431 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1433 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1434 AFS_TRACE_LEVEL_VERBOSE,
1435 "AFSLocateNameEntry (FO: %08lX) Returning name not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1438 pCurrentObject->FileId.Cell,
1439 pCurrentObject->FileId.Volume,
1440 pCurrentObject->FileId.Vnode,
1441 pCurrentObject->FileId.Unique);
1444 // Pass back the directory entries
1447 *ParentDirectoryCB = pParentDirEntry;
1449 *DirectoryCB = NULL;
1451 *VolumeCB = pCurrentVolume;
1453 if( ComponentName != NULL)
1456 *ComponentName = uniComponentName;
1459 *RootPathName = uniFullPathName;
1462 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1465 // Node name not found so get out
1468 try_return( ntStatus); // while( pDirEntry == NULL)
1475 // Here we have a match on the case insensitive lookup for the name. If there
1476 // Is more than one link entry for this node then fail the lookup request
1479 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1480 pDirEntry->CaseInsensitiveList.fLink != NULL)
1483 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1485 try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1490 if( pDirEntry != NULL)
1494 // If the verify flag is set on the parent and the current entry is deleted
1495 // revalidate the parent and search again.
1498 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1499 BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1502 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1504 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1505 AFS_TRACE_LEVEL_VERBOSE,
1506 "AFSLocateNameEntry (FO: %08lX) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1508 &pParentDirEntry->NameInformation.FileName,
1509 pParentDirEntry->ObjectInformation->FileId.Cell,
1510 pParentDirEntry->ObjectInformation->FileId.Volume,
1511 pParentDirEntry->ObjectInformation->FileId.Vnode,
1512 pParentDirEntry->ObjectInformation->FileId.Unique);
1515 // Directory TreeLock should be exclusively held
1518 AFSAcquireExcl( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1521 ntStatus = AFSVerifyEntry( AuthGroup,
1524 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1526 if( !NT_SUCCESS( ntStatus))
1529 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1530 AFS_TRACE_LEVEL_ERROR,
1531 "AFSLocateNameEntry (FO: %08lX) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1533 &pParentDirEntry->NameInformation.FileName,
1534 pParentDirEntry->ObjectInformation->FileId.Cell,
1535 pParentDirEntry->ObjectInformation->FileId.Volume,
1536 pParentDirEntry->ObjectInformation->FileId.Vnode,
1537 pParentDirEntry->ObjectInformation->FileId.Unique,
1540 try_return( ntStatus);
1543 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1544 AFS_TRACE_LEVEL_VERBOSE,
1545 "AFSLocateNameEntry (FO: %08lX) Reprocessing component %wZ in parent %wZ\n",
1548 &pParentDirEntry->NameInformation.FileName);
1557 // Increment our dir entry ref count
1560 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
1562 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1563 AFS_TRACE_LEVEL_VERBOSE,
1564 "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1565 &pDirEntry->NameInformation.FileName,
1568 pDirEntry->OpenReferenceCount);
1571 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1573 } // End while( pDirEntry == NULL)
1576 // If we have a dirEntry for this component, perform some basic validation on it
1579 if( pDirEntry != NULL &&
1580 BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1583 pCurrentObject = pDirEntry->ObjectInformation;
1585 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1586 AFS_TRACE_LEVEL_ERROR,
1587 "AFSLocateNameEntry (FO: %08lX) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1589 &pDirEntry->NameInformation.FileName,
1590 pCurrentObject->FileId.Cell,
1591 pCurrentObject->FileId.Volume,
1592 pCurrentObject->FileId.Vnode,
1593 pCurrentObject->FileId.Unique);
1596 // This entry was deleted through the invalidation call back so perform cleanup
1600 ASSERT( pCurrentObject->ParentObjectInformation != NULL);
1602 AFSAcquireExcl( pCurrentObject->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1605 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1608 if( InterlockedDecrement( &pDirEntry->OpenReferenceCount) == 0)
1611 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1612 AFS_TRACE_LEVEL_VERBOSE,
1613 "AFSLocateNameEntry Deleting dir entry %08lX (%08lX) for %wZ\n",
1616 &pDirEntry->NameInformation.FileName);
1619 // Remove and delete the directory entry from the parent list
1622 AFSDeleteDirEntry( pCurrentObject->ParentObjectInformation,
1625 if( pCurrentObject->ObjectReferenceCount == 0)
1628 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
1631 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1632 AFS_TRACE_LEVEL_VERBOSE,
1633 "AFSLocateNameEntry Removing object %08lX from volume tree\n",
1636 AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
1637 &pCurrentObject->TreeEntry);
1639 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
1646 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1647 AFS_TRACE_LEVEL_VERBOSE,
1648 "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
1650 &pDirEntry->NameInformation.FileName);
1652 SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
1654 AFSRemoveNameEntry( pCurrentObject->ParentObjectInformation,
1658 AFSReleaseResource( pCurrentObject->ParentObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1660 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
1663 // We deleted the dir entry so check if there is any remaining portion
1664 // of the name to process.
1667 if( uniRemainingPath.Length > 0)
1669 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1674 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1676 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1677 AFS_TRACE_LEVEL_VERBOSE,
1678 "AFSLocateNameEntry (FO: %08lX) Returning name not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1681 pCurrentObject->FileId.Cell,
1682 pCurrentObject->FileId.Volume,
1683 pCurrentObject->FileId.Vnode,
1684 pCurrentObject->FileId.Unique);
1687 // Pass back the directory entries
1690 *ParentDirectoryCB = pParentDirEntry;
1692 *DirectoryCB = NULL;
1694 *VolumeCB = pCurrentVolume;
1696 if( ComponentName != NULL)
1699 *ComponentName = uniComponentName;
1702 *RootPathName = uniFullPathName;
1706 if( ntStatus != STATUS_SUCCESS)
1709 try_return( ntStatus);
1713 // Decrement the previous parent
1716 InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
1718 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1719 AFS_TRACE_LEVEL_VERBOSE,
1720 "AFSLocateNameEntry Decrement5 count on Parent %wZ DE %p Ccb %p Cnt %d\n",
1721 &pParentDirEntry->NameInformation.FileName,
1724 pParentDirEntry->OpenReferenceCount);
1727 // If we ended up substituting a name in the component then update
1728 // the full path and update the pointers
1731 if( bSubstituteName)
1734 BOOLEAN bRelativeOpen = FALSE;
1736 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1737 AFS_TRACE_LEVEL_VERBOSE_2,
1738 "AFSLocateNameEntry (FO: %08lX) Substituting %wZ into %wZ Index %08lX\n",
1744 if( FileObject != NULL &&
1745 FileObject->RelatedFileObject != NULL)
1748 bRelativeOpen = TRUE;
1752 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
1753 // and free the prior Buffer contents but only if the fourth
1754 // parameter is TRUE.
1757 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
1762 bAllocatedSymLinkBuffer ||
1765 if( !NT_SUCCESS( ntStatus))
1768 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1769 AFS_TRACE_LEVEL_ERROR,
1770 "AFSLocateNameEntry (FO: %08lX) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
1777 try_return( ntStatus);
1781 // We have substituted a name into the buffer so if we do this again for this
1782 // path, we need to free up the buffer we allocated.
1785 bSubstitutedName = TRUE;
1789 // Update the search parameters
1792 uniPathName = uniRemainingPath;
1795 // Check if the is a SymLink entry but has no Target FileID or Name. In this
1796 // case it might be a DFS Link so let's go and evaluate it to be sure
1799 if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
1800 pCurrentObject->TargetFileId.Vnode == 0 &&
1801 pCurrentObject->TargetFileId.Unique == 0 &&
1802 pDirEntry->NameInformation.TargetName.Length == 0)
1805 ntStatus = AFSValidateSymLink( AuthGroup,
1808 if( !NT_SUCCESS( ntStatus))
1811 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1812 AFS_TRACE_LEVEL_ERROR,
1813 "AFSLocateNameEntry (FO: %08lX) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1815 &pDirEntry->NameInformation.FileName,
1816 pCurrentObject->FileId.Cell,
1817 pCurrentObject->FileId.Volume,
1818 pCurrentObject->FileId.Vnode,
1819 pCurrentObject->FileId.Unique,
1822 try_return( ntStatus);
1827 // Update the name array
1830 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1831 AFS_TRACE_LEVEL_VERBOSE,
1832 "AFSLocateNameEntry (FO: %08lX) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1834 &pDirEntry->NameInformation.FileName,
1835 pCurrentObject->FileId.Cell,
1836 pCurrentObject->FileId.Volume,
1837 pCurrentObject->FileId.Vnode,
1838 pCurrentObject->FileId.Unique);
1840 ntStatus = AFSInsertNextElement( pNameArray,
1843 if( !NT_SUCCESS( ntStatus))
1846 try_return( ntStatus);
1852 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1853 AFS_TRACE_LEVEL_VERBOSE,
1854 "AFSLocateNameEntry (FO: %08lX) Completed processing %wZ Status %08lX\n",
1859 if( ( !NT_SUCCESS( ntStatus) &&
1860 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
1861 ntStatus == STATUS_REPARSE)
1864 if( pDirEntry != NULL)
1867 InterlockedDecrement( &pDirEntry->OpenReferenceCount);
1869 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1870 AFS_TRACE_LEVEL_VERBOSE,
1871 "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
1872 &pDirEntry->NameInformation.FileName,
1875 pDirEntry->OpenReferenceCount);
1877 else if( pParentDirEntry != NULL)
1880 InterlockedDecrement( &pParentDirEntry->OpenReferenceCount);
1882 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1883 AFS_TRACE_LEVEL_VERBOSE,
1884 "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
1885 &pParentDirEntry->NameInformation.FileName,
1888 pParentDirEntry->OpenReferenceCount);
1891 if( bReleaseCurrentVolume)
1894 ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
1896 InterlockedDecrement( &pCurrentVolume->VolumeReferenceCount);
1898 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1899 AFS_TRACE_LEVEL_VERBOSE,
1900 "AFSLocateNameEntry Decrement3 count on volume %08lX Cnt %d\n",
1902 pCurrentVolume->VolumeReferenceCount);
1905 if( RootPathName->Buffer != uniFullPathName.Buffer)
1908 AFSExFreePool( uniFullPathName.Buffer);
1914 if( *ParentDirectoryCB != NULL)
1917 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1918 AFS_TRACE_LEVEL_VERBOSE,
1919 "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
1920 &(*ParentDirectoryCB)->NameInformation.FileName,
1923 (*ParentDirectoryCB)->OpenReferenceCount);
1926 if( *DirectoryCB != NULL)
1929 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1930 AFS_TRACE_LEVEL_VERBOSE,
1931 "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
1932 &(*DirectoryCB)->NameInformation.FileName,
1935 (*DirectoryCB)->OpenReferenceCount);
1939 if( bSubstituteName &&
1940 uniSearchName.Buffer != NULL)
1943 AFSExFreePool( uniSearchName.Buffer);
1951 AFSCreateDirEntry( IN GUID *AuthGroup,
1952 IN AFSObjectInfoCB *ParentObjectInfo,
1953 IN AFSDirectoryCB *ParentDirCB,
1954 IN PUNICODE_STRING FileName,
1955 IN PUNICODE_STRING ComponentName,
1956 IN ULONG Attributes,
1957 IN OUT AFSDirectoryCB **DirEntry)
1960 NTSTATUS ntStatus = STATUS_SUCCESS;
1961 AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
1962 UNICODE_STRING uniShortName;
1963 LARGE_INTEGER liFileSize = {0,0};
1968 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1969 AFS_TRACE_LEVEL_VERBOSE_2,
1970 "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
1971 &ParentDirCB->NameInformation.FileName,
1972 ParentObjectInfo->FileId.Cell,
1973 ParentObjectInfo->FileId.Volume,
1974 ParentObjectInfo->FileId.Vnode,
1975 ParentObjectInfo->FileId.Unique,
1980 // OK, before inserting the node into the parent tree, issue
1981 // the request to the service for node creation
1982 // We will need to drop the lock on the parent node since the create
1983 // could cause a callback into the file system to invalidate it's cache
1986 ntStatus = AFSNotifyFileCreate( AuthGroup,
1994 // If the returned status is STATUS_REPARSE then the entry exists
1995 // and we raced, get out.
1997 if( ntStatus == STATUS_REPARSE)
2000 *DirEntry = pDirNode;
2002 try_return( ntStatus = STATUS_SUCCESS);
2005 if( !NT_SUCCESS( ntStatus))
2008 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2009 AFS_TRACE_LEVEL_ERROR,
2010 "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
2011 &ParentDirCB->NameInformation.FileName,
2012 ParentObjectInfo->FileId.Cell,
2013 ParentObjectInfo->FileId.Volume,
2014 ParentObjectInfo->FileId.Vnode,
2015 ParentObjectInfo->FileId.Unique,
2020 try_return( ntStatus);
2023 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2027 // Before attempting to insert the new entry, check if we need to validate the parent
2030 if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2033 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2034 AFS_TRACE_LEVEL_VERBOSE,
2035 "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2036 &ParentDirCB->NameInformation.FileName,
2037 ParentObjectInfo->FileId.Cell,
2038 ParentObjectInfo->FileId.Volume,
2039 ParentObjectInfo->FileId.Vnode,
2040 ParentObjectInfo->FileId.Unique);
2042 ntStatus = AFSVerifyEntry( AuthGroup,
2045 if( !NT_SUCCESS( ntStatus))
2048 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2049 AFS_TRACE_LEVEL_ERROR,
2050 "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2051 &ParentDirCB->NameInformation.FileName,
2052 ParentObjectInfo->FileId.Cell,
2053 ParentObjectInfo->FileId.Volume,
2054 ParentObjectInfo->FileId.Vnode,
2055 ParentObjectInfo->FileId.Unique,
2058 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2060 try_return( ntStatus);
2065 // Check for the entry in the event we raced with some other thread
2068 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2069 (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2072 if( pExistingDirNode != NULL)
2074 if (AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2075 &pExistingDirNode->ObjectInformation->FileId))
2078 AFSDeleteDirEntry( ParentObjectInfo,
2081 InterlockedIncrement( &pExistingDirNode->OpenReferenceCount);
2083 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2084 AFS_TRACE_LEVEL_VERBOSE,
2085 "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2086 &pExistingDirNode->NameInformation.FileName,
2088 pExistingDirNode->OpenReferenceCount);
2090 *DirEntry = pExistingDirNode;
2092 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2094 try_return( ntStatus = STATUS_SUCCESS);
2100 // Need to tear down this entry and rebuild it below
2103 if( pExistingDirNode->OpenReferenceCount == 0)
2106 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2107 AFS_TRACE_LEVEL_VERBOSE,
2108 "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2110 &pExistingDirNode->NameInformation.FileName,
2111 pExistingDirNode->ObjectInformation->FileId.Cell,
2112 pExistingDirNode->ObjectInformation->FileId.Volume,
2113 pExistingDirNode->ObjectInformation->FileId.Vnode,
2114 pExistingDirNode->ObjectInformation->FileId.Unique,
2115 pDirNode->ObjectInformation->FileId.Cell,
2116 pDirNode->ObjectInformation->FileId.Volume,
2117 pDirNode->ObjectInformation->FileId.Vnode,
2118 pDirNode->ObjectInformation->FileId.Unique);
2120 AFSDeleteDirEntry( ParentObjectInfo,
2126 SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2128 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2129 AFS_TRACE_LEVEL_VERBOSE,
2130 "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2132 &pExistingDirNode->NameInformation.FileName,
2133 pExistingDirNode->ObjectInformation->FileId.Cell,
2134 pExistingDirNode->ObjectInformation->FileId.Volume,
2135 pExistingDirNode->ObjectInformation->FileId.Vnode,
2136 pExistingDirNode->ObjectInformation->FileId.Unique,
2137 pDirNode->ObjectInformation->FileId.Cell,
2138 pDirNode->ObjectInformation->FileId.Volume,
2139 pDirNode->ObjectInformation->FileId.Vnode,
2140 pDirNode->ObjectInformation->FileId.Unique);
2142 AFSRemoveNameEntry( ParentObjectInfo,
2149 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2150 AFS_TRACE_LEVEL_VERBOSE_2,
2151 "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2152 &ParentDirCB->NameInformation.FileName,
2153 ParentObjectInfo->FileId.Cell,
2154 ParentObjectInfo->FileId.Volume,
2155 ParentObjectInfo->FileId.Vnode,
2156 ParentObjectInfo->FileId.Unique,
2160 // Insert the directory node
2163 AFSInsertDirectoryNode( ParentObjectInfo,
2167 InterlockedIncrement( &pDirNode->OpenReferenceCount);
2169 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2170 AFS_TRACE_LEVEL_VERBOSE,
2171 "AFSCreateDirEntry Increment2 count on %wZ DE %p Cnt %d\n",
2172 &pDirNode->NameInformation.FileName,
2174 pDirNode->OpenReferenceCount);
2177 // Pass back the dir entry
2180 *DirEntry = pDirNode;
2182 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2193 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2194 IN AFSDirectoryCB *DirEntry,
2195 IN BOOLEAN InsertInEnumList)
2201 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2204 // Insert the node into the directory node tree
2207 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2208 AFS_TRACE_LEVEL_VERBOSE,
2209 "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2211 &DirEntry->NameInformation.FileName);
2213 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2215 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2218 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2220 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2221 AFS_TRACE_LEVEL_VERBOSE,
2222 "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2224 &DirEntry->NameInformation.FileName);
2229 AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2232 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2233 AFS_TRACE_LEVEL_VERBOSE,
2234 "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2236 &DirEntry->NameInformation.FileName);
2239 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2242 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2244 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2246 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2247 AFS_TRACE_LEVEL_VERBOSE,
2248 "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2250 &DirEntry->NameInformation.FileName);
2255 AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2258 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2259 AFS_TRACE_LEVEL_VERBOSE,
2260 "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2262 &DirEntry->NameInformation.FileName);
2266 // Into the shortname tree
2269 if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2272 if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2275 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2277 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2278 AFS_TRACE_LEVEL_VERBOSE,
2279 "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2281 &DirEntry->NameInformation.FileName);
2283 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2288 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2291 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2292 AFS_TRACE_LEVEL_VERBOSE,
2293 "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2295 &DirEntry->NameInformation.FileName);
2299 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2301 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2302 AFS_TRACE_LEVEL_VERBOSE,
2303 "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2305 &DirEntry->NameInformation.FileName);
2310 if( InsertInEnumList)
2314 // And insert the node into the directory list
2317 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2318 AFS_TRACE_LEVEL_VERBOSE,
2319 "AFSInsertDirectoryNode Inserting entry %08lX %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2321 &DirEntry->NameInformation.FileName,
2322 DirEntry->ObjectInformation->FileId.Cell,
2323 DirEntry->ObjectInformation->FileId.Volume,
2324 DirEntry->ObjectInformation->FileId.Vnode,
2325 DirEntry->ObjectInformation->FileId.Unique);
2327 if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2330 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2335 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2337 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2340 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2342 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2344 InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2346 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2347 AFS_TRACE_LEVEL_VERBOSE,
2348 "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2349 &DirEntry->NameInformation.FileName,
2350 ParentObjectInfo->Specific.Directory.DirectoryNodeCount,
2351 ParentObjectInfo->FileId.Cell,
2352 ParentObjectInfo->FileId.Volume,
2353 ParentObjectInfo->FileId.Vnode,
2354 ParentObjectInfo->FileId.Unique);
2362 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2363 IN AFSDirectoryCB *DirEntry)
2366 NTSTATUS ntStatus = STATUS_SUCCESS;
2371 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2372 AFS_TRACE_LEVEL_VERBOSE,
2373 "AFSDeleteDirEntry Deleting dir entry in parent %08lX Entry %08lX %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2376 &DirEntry->NameInformation.FileName,
2377 DirEntry->ObjectInformation->FileId.Cell,
2378 DirEntry->ObjectInformation->FileId.Volume,
2379 DirEntry->ObjectInformation->FileId.Vnode,
2380 DirEntry->ObjectInformation->FileId.Unique);
2382 AFSRemoveDirNodeFromParent( ParentObjectInfo,
2387 // Free up the name buffer if it was reallocated
2390 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2393 AFSExFreePool( DirEntry->NameInformation.FileName.Buffer);
2396 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2399 AFSExFreePool( DirEntry->NameInformation.TargetName.Buffer);
2403 // Dereference the object for this dir entry
2406 ASSERT( DirEntry->ObjectInformation->ObjectReferenceCount > 0);
2408 if( InterlockedDecrement( &DirEntry->ObjectInformation->ObjectReferenceCount) == 0)
2410 SetFlag( DirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2413 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2414 AFS_TRACE_LEVEL_VERBOSE,
2415 "AFSDeleteDirEntry Decrement count on object %08lX Cnt %d\n",
2416 DirEntry->ObjectInformation,
2417 DirEntry->ObjectInformation->ObjectReferenceCount);
2419 ExDeleteResourceLite( &DirEntry->NonPaged->Lock);
2421 AFSExFreePool( DirEntry->NonPaged);
2424 // Free up the dir entry
2427 AFSExFreePool( DirEntry);
2434 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2435 IN AFSDirectoryCB *DirEntry,
2436 IN BOOLEAN RemoveFromEnumList)
2439 NTSTATUS ntStatus = STATUS_SUCCESS;
2445 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2447 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2448 AFS_TRACE_LEVEL_VERBOSE,
2449 "AFSRemoveDirNodeFromParent Removing DirEntry %08lX %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %08lX\n",
2451 &DirEntry->NameInformation.FileName,
2452 DirEntry->ObjectInformation->FileId.Cell,
2453 DirEntry->ObjectInformation->FileId.Volume,
2454 DirEntry->ObjectInformation->FileId.Vnode,
2455 DirEntry->ObjectInformation->FileId.Unique,
2458 if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2461 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2462 AFS_TRACE_LEVEL_VERBOSE,
2463 "AFSRemoveDirNodeFromParent Removing DirEntry %08lX name %wZ\n",
2465 &DirEntry->NameInformation.FileName);
2467 AFSRemoveNameEntry( ParentObjectInfo,
2473 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2474 AFS_TRACE_LEVEL_VERBOSE,
2475 "AFSRemoveDirNodeFromParent DE %p for %wZ NOT removing entry due to flag set\n",
2477 &DirEntry->NameInformation.FileName);
2481 if( RemoveFromEnumList &&
2482 BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST))
2486 // And remove the entry from the enumeration list
2489 if( DirEntry->ListEntry.fLink == NULL)
2492 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = (AFSDirectoryCB *)DirEntry->ListEntry.bLink;
2497 ((AFSDirectoryCB *)DirEntry->ListEntry.fLink)->ListEntry.bLink = DirEntry->ListEntry.bLink;
2500 if( DirEntry->ListEntry.bLink == NULL)
2503 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = (AFSDirectoryCB *)DirEntry->ListEntry.fLink;
2508 ((AFSDirectoryCB *)DirEntry->ListEntry.bLink)->ListEntry.fLink = DirEntry->ListEntry.fLink;
2511 ASSERT( ParentObjectInfo->Specific.Directory.DirectoryNodeCount > 0);
2513 InterlockedDecrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2515 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2517 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2518 AFS_TRACE_LEVEL_VERBOSE,
2519 "AFSRemoveDirNodeFromParent Removing entry %wZ Dec Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2520 &DirEntry->NameInformation.FileName,
2521 ParentObjectInfo->Specific.Directory.DirectoryNodeCount,
2522 ParentObjectInfo->FileId.Cell,
2523 ParentObjectInfo->FileId.Volume,
2524 ParentObjectInfo->FileId.Vnode,
2525 ParentObjectInfo->FileId.Unique);
2527 DirEntry->ListEntry.fLink = NULL;
2528 DirEntry->ListEntry.bLink = NULL;
2536 AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
2537 IN OUT PUNICODE_STRING TargetFileName)
2540 NTSTATUS ntStatus = STATUS_SUCCESS;
2541 UNICODE_STRING uniFileName;
2547 // We will process backwards from the end of the name looking
2548 // for the first \ we encounter
2551 uniFileName.Length = FileName->Length;
2552 uniFileName.MaximumLength = FileName->MaximumLength;
2554 uniFileName.Buffer = FileName->Buffer;
2559 if( uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
2563 // Subtract one more character off of the filename if it is not the root
2566 if( uniFileName.Length > sizeof( WCHAR))
2569 uniFileName.Length -= sizeof( WCHAR);
2573 // Now build up the target name
2576 TargetFileName->Length = FileName->Length - uniFileName.Length;
2579 // If we are not on the root then fixup the name
2582 if( uniFileName.Length > sizeof( WCHAR))
2585 TargetFileName->Length -= sizeof( WCHAR);
2587 TargetFileName->Buffer = &uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) + 1];
2592 TargetFileName->Buffer = &uniFileName.Buffer[ uniFileName.Length/sizeof( WCHAR)];
2596 // Fixup the passed back filename length
2599 FileName->Length = uniFileName.Length;
2601 TargetFileName->MaximumLength = TargetFileName->Length;
2606 uniFileName.Length -= sizeof( WCHAR);
2614 AFSParseName( IN PIRP Irp,
2616 OUT PUNICODE_STRING FileName,
2617 OUT PUNICODE_STRING ParsedFileName,
2618 OUT PUNICODE_STRING RootFileName,
2619 OUT ULONG *ParseFlags,
2620 OUT AFSVolumeCB **VolumeCB,
2621 OUT AFSDirectoryCB **ParentDirectoryCB,
2622 OUT AFSNameArrayHdr **NameArray)
2625 NTSTATUS ntStatus = STATUS_SUCCESS;
2626 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2627 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2628 UNICODE_STRING uniFullName, uniComponentName, uniRemainingPath;
2630 AFSDirectoryCB *pDirEntry = NULL, *pShareDirEntry = NULL, *pTargetDirEntry = NULL;
2631 USHORT usIndex = 0, usDriveIndex = 0;
2632 AFSCcb *pRelatedCcb = NULL;
2633 AFSNameArrayHdr *pNameArray = NULL, *pRelatedNameArray = NULL;
2634 USHORT usComponentIndex = 0;
2635 USHORT usComponentLength = 0;
2636 AFSVolumeCB *pVolumeCB = NULL;
2637 AFSFcb *pRelatedFcb = NULL;
2638 BOOLEAN bReleaseTreeLock = FALSE;
2639 BOOLEAN bIsAllShare = FALSE;
2645 // Indicate we are opening a root ...
2648 *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
2650 if( pIrpSp->FileObject->RelatedFileObject != NULL)
2653 pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
2655 pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
2657 pRelatedNameArray = pRelatedCcb->NameArray;
2659 uniFullName = pIrpSp->FileObject->FileName;
2661 ASSERT( pRelatedFcb != NULL);
2664 // No wild cards in the name
2667 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2668 AFS_TRACE_LEVEL_VERBOSE_2,
2669 "AFSParseName (%08lX) Relative open for %wZ FID %08lX-%08lX-%08lX-%08lX component %wZ\n",
2671 &pRelatedCcb->DirectoryCB->NameInformation.FileName,
2672 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Cell,
2673 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Volume,
2674 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
2675 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Unique,
2678 if( FsRtlDoesNameContainWildCards( &uniFullName))
2681 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2682 AFS_TRACE_LEVEL_ERROR,
2683 "AFSParseName (%08lX) Component %wZ contains wild cards\n",
2687 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
2690 pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
2692 pDirEntry = pRelatedCcb->DirectoryCB;
2694 *FileName = pIrpSp->FileObject->FileName;
2697 // Grab the root node while checking state
2700 AFSAcquireShared( pVolumeCB->VolumeLock,
2703 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
2704 BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
2708 // The volume has been taken off line so fail the access
2711 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2712 AFS_TRACE_LEVEL_ERROR,
2713 "AFSParseName (%08lX) Volume %08lX:%08lX OFFLINE/INVALID\n",
2715 pVolumeCB->ObjectInformation.FileId.Cell,
2716 pVolumeCB->ObjectInformation.FileId.Volume);
2718 AFSReleaseResource( pVolumeCB->VolumeLock);
2720 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
2723 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
2726 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2727 AFS_TRACE_LEVEL_VERBOSE,
2728 "AFSParseName (%08lX) Verifying root of volume %08lX:%08lX\n",
2730 pVolumeCB->ObjectInformation.FileId.Cell,
2731 pVolumeCB->ObjectInformation.FileId.Volume);
2733 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
2736 if( !NT_SUCCESS( ntStatus))
2739 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2740 AFS_TRACE_LEVEL_ERROR,
2741 "AFSParseName (%08lX) Failed verification of root Status %08lX\n",
2745 AFSReleaseResource( pVolumeCB->VolumeLock);
2747 try_return( ntStatus);
2751 AFSReleaseResource( pVolumeCB->VolumeLock);
2753 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
2756 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2757 AFS_TRACE_LEVEL_VERBOSE,
2758 "AFSParseName (%08lX) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2760 &pDirEntry->NameInformation.FileName,
2761 pDirEntry->ObjectInformation->FileId.Cell,
2762 pDirEntry->ObjectInformation->FileId.Volume,
2763 pDirEntry->ObjectInformation->FileId.Vnode,
2764 pDirEntry->ObjectInformation->FileId.Unique);
2767 // Directory TreeLock should be exclusively held
2770 AFSAcquireExcl( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
2773 ntStatus = AFSVerifyEntry( AuthGroup,
2776 AFSReleaseResource( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2778 if( !NT_SUCCESS( ntStatus))
2781 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2782 AFS_TRACE_LEVEL_VERBOSE,
2783 "AFSParseName (%08lX) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2785 &pDirEntry->NameInformation.FileName,
2786 pDirEntry->ObjectInformation->FileId.Cell,
2787 pDirEntry->ObjectInformation->FileId.Volume,
2788 pDirEntry->ObjectInformation->FileId.Vnode,
2789 pDirEntry->ObjectInformation->FileId.Unique,
2792 try_return( ntStatus);
2797 // Create our full path name buffer
2800 uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length +
2802 pIrpSp->FileObject->FileName.Length +
2805 uniFullName.Length = 0;
2807 uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2808 uniFullName.MaximumLength,
2809 AFS_NAME_BUFFER_THREE_TAG);
2811 if( uniFullName.Buffer == NULL)
2814 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2815 AFS_TRACE_LEVEL_ERROR,
2816 "AFSParseName (%08lX) Failed to allocate full name buffer\n",
2819 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2822 RtlZeroMemory( uniFullName.Buffer,
2823 uniFullName.MaximumLength);
2825 RtlCopyMemory( uniFullName.Buffer,
2826 pRelatedCcb->FullFileName.Buffer,
2827 pRelatedCcb->FullFileName.Length);
2829 uniFullName.Length = pRelatedCcb->FullFileName.Length;
2831 usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
2833 usComponentLength = pIrpSp->FileObject->FileName.Length;
2835 if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
2836 pIrpSp->FileObject->FileName.Length > 0 &&
2837 pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
2838 pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
2841 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
2843 uniFullName.Length += sizeof( WCHAR);
2845 usComponentLength += sizeof( WCHAR);
2848 if( pIrpSp->FileObject->FileName.Length > 0)
2851 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
2852 pIrpSp->FileObject->FileName.Buffer,
2853 pIr
\epSp->FileObject->FileName.Length);
2855 uniFullName.Length += pIrpSp->FileObject->FileName.Length;
2858 *RootFileName = uniFullName;
2861 // We populate up to the current parent
2864 if( pRelatedNameArray == NULL)
2868 // Init and populate our name array
2871 pNameArray = AFSInitNameArray( NULL,
2874 if( pNameArray == NULL)
2877 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2878 AFS_TRACE_LEVEL_VERBOSE,
2879 "AFSParseName (%08lX) Failed to initialize name array\n",
2882 AFSExFreePool( uniFullName.Buffer);
2884 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2887 ntStatus = AFSPopulateNameArray( pNameArray,
2889 pRelatedCcb->DirectoryCB);
2895 // Init and populate our name array
2898 pNameArray = AFSInitNameArray( NULL,
2899 pRelatedNameArray->MaxElementCount);
2901 if( pNameArray == NULL)
2904 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2905 AFS_TRACE_LEVEL_VERBOSE,
2906 "AFSParseName (%08lX) Failed to initialize name array\n",
2909 AFSExFreePool( uniFullName.Buffer);
2911 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2914 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
2916 pRelatedCcb->DirectoryCB);
2919 if( !NT_SUCCESS( ntStatus))
2922 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2923 AFS_TRACE_LEVEL_VERBOSE,
2924 "AFSParseName (%08lX) Failed to populate name array\n",
2927 AFSExFreePool( uniFullName.Buffer);
2929 try_return( ntStatus);
2932 ParsedFileName->Length = usComponentLength;
2933 ParsedFileName->MaximumLength = uniFullName.MaximumLength;
2935 ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
2938 // Indicate to caller that RootFileName must be freed
2941 SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
2943 *NameArray = pNameArray;
2945 *VolumeCB = pVolumeCB;
2948 // Increment our volume reference count
2951 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2953 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2954 AFS_TRACE_LEVEL_VERBOSE,
2955 "AFSParseName Increment count on volume %08lX Cnt %d\n",
2957 pVolumeCB->VolumeReferenceCount);
2959 *ParentDirectoryCB = pDirEntry;
2961 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
2963 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2964 AFS_TRACE_LEVEL_VERBOSE,
2965 "AFSParseName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
2966 &pDirEntry->NameInformation.FileName,
2969 pDirEntry->OpenReferenceCount);
2971 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2972 AFS_TRACE_LEVEL_VERBOSE_2,
2973 "AFSParseName (%08lX) Returning full name %wZ\n",
2977 try_return( ntStatus);
2981 // No wild cards in the name
2984 uniFullName = pIrpSp->FileObject->FileName;
2986 if( FsRtlDoesNameContainWildCards( &uniFullName) ||
2987 uniFullName.Length < AFSServerName.Length)
2990 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2991 AFS_TRACE_LEVEL_ERROR,
2992 "AFSParseName (%08lX) Name %wZ contains wild cards or too short\n",
2996 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3000 // The name is a fully qualified name. Parse out the server/share names and
3001 // point to the root qualified name
3002 // First thing is to locate the server name
3005 FsRtlDissectName( uniFullName,
3009 uniFullName = uniRemainingPath;
3012 // This component is the server name we are serving
3015 if( RtlCompareUnicodeString( &uniComponentName,
3021 // Drive letter based name?
3024 uniFullName = pIrpSp->FileObject->FileName;
3026 while( usIndex < uniFullName.Length/sizeof( WCHAR))
3029 if( uniFullName.Buffer[ usIndex] == L':')
3032 uniFullName.Buffer = &uniFullName.Buffer[ usIndex + 2];
3034 uniFullName.Length -= (usIndex + 2) * sizeof( WCHAR);
3036 usDriveIndex = usIndex - 1;
3045 // Do we have the right server name now?
3048 FsRtlDissectName( uniFullName,
3052 uniFullName = uniRemainingPath;
3055 // This component is the server name we are serving
3058 if( RtlCompareUnicodeString( &uniComponentName,
3063 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3064 AFS_TRACE_LEVEL_ERROR,
3065 "AFSParseName (%08lX) Name %wZ does not have server name\n",
3067 &pIrpSp->FileObject->FileName);
3069 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3073 // Validate this drive letter is actively mapped
3076 if( usDriveIndex > 0 &&
3077 !AFSIsDriveMapped( pIrpSp->FileObject->FileName.Buffer[ usDriveIndex]))
3080 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3081 AFS_TRACE_LEVEL_ERROR,
3082 "AFSParseName (%08lX) Name %wZ contains invalid drive mapping\n",
3084 &pIrpSp->FileObject->FileName);
3086 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3090 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3091 AFS_TRACE_LEVEL_VERBOSE_2,
3092 "AFSParseName (%08lX) Processing full name %wZ\n",
3096 if( uniFullName.Length > 0 &&
3097 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] == L'\\')
3100 uniFullName.Length -= sizeof( WCHAR);
3104 // Be sure we are online and ready to go
3107 AFSAcquireShared( AFSGlobalRoot->VolumeLock,
3110 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3111 BooleanFlagOn( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3115 // The volume has been taken off line so fail the access
3118 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3119 AFS_TRACE_LEVEL_ERROR,
3120 "AFSParseName (%08lX) Volume %08lX:%08lX OFFLINE/INVALID\n",
3122 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3123 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3125 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3127 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3130 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3133 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3134 AFS_TRACE_LEVEL_VERBOSE,
3135 "AFSParseName (%08lX) Verifying root of volume %08lX:%08lX\n",
3137 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3138 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3140 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3143 if( !NT_SUCCESS( ntStatus))
3146 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3147 AFS_TRACE_LEVEL_ERROR,
3148 "AFSParseName (%08lX) Failed verification of root Status %08lX\n",
3152 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3154 try_return( ntStatus);
3158 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3160 if( !BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3163 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3164 AFS_TRACE_LEVEL_VERBOSE,
3165 "AFSParseName (%08lX) Enumerating global root of volume %08lX:%08lX\n",
3167 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3168 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3170 ntStatus = AFSEnumerateGlobalRoot( AuthGroup);
3172 if( !NT_SUCCESS( ntStatus))
3175 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3176 AFS_TRACE_LEVEL_ERROR,
3177 "AFSParseName (%08lX) Failed enumeraiton of root Status %08lX\n",
3181 try_return( ntStatus);
3186 // Check for the \\Server access and return it as though it where \\Server\Globalroot
3189 if( uniRemainingPath.Buffer == NULL ||
3190 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3191 uniRemainingPath.Buffer[ 0] == L'\\'))
3194 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3195 AFS_TRACE_LEVEL_VERBOSE_2,
3196 "AFSParseName (%08lX) Returning global root access\n",
3199 InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3201 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3202 AFS_TRACE_LEVEL_VERBOSE,
3203 "AFSParseName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3204 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3205 AFSGlobalRoot->DirectoryCB,
3207 AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3211 FileName->Length = 0;
3212 FileName->MaximumLength = 0;
3213 FileName->Buffer = NULL;
3215 try_return( ntStatus = STATUS_SUCCESS);
3218 *RootFileName = uniFullName;
3221 // Include the starting \ in the root name
3224 if( RootFileName->Buffer[ 0] != L'\\')
3226 RootFileName->Buffer--;
3227 RootFileName->Length += sizeof( WCHAR);
3228 RootFileName->MaximumLength += sizeof( WCHAR);
3232 // Get the 'share' name
3235 FsRtlDissectName( uniFullName,
3240 // If this is the ALL access then perform some additional processing
3243 if( RtlCompareUnicodeString( &uniComponentName,
3251 // If there is nothing else then get out
3254 if( uniRemainingPath.Buffer == NULL ||
3255 uniRemainingPath.Length == 0 ||
3256 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3257 uniRemainingPath.Buffer[ 0] == L'\\'))
3260 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3261 AFS_TRACE_LEVEL_VERBOSE_2,
3262 "AFSParseName (%08lX) Returning global root access\n",
3265 InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3267 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3268 AFS_TRACE_LEVEL_VERBOSE,
3269 "AFSParseName Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
3270 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3271 AFSGlobalRoot->DirectoryCB,
3273 AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3277 FileName->Length = 0;
3278 FileName->MaximumLength = 0;
3279 FileName->Buffer = NULL;
3281 try_return( ntStatus = STATUS_SUCCESS);
3285 // Process the name again to strip off the ALL portion
3288 uniFullName = uniRemainingPath;
3290 FsRtlDissectName( uniFullName,
3295 // Check for the PIOCtl name
3298 if( RtlCompareUnicodeString( &uniComponentName,
3303 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3304 AFS_TRACE_LEVEL_VERBOSE_2,
3305 "AFSParseName (%08lX) Returning root PIOCtl access\n",
3308 InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3310 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3311 AFS_TRACE_LEVEL_VERBOSE,
3312 "AFSParseName Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
3313 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3314 AFSGlobalRoot->DirectoryCB,
3316 AFSGlobalRoot->DirectoryCB->OpenReferenceCount);
3318 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3322 *FileName = AFSPIOCtlName;
3324 try_return( ntStatus = STATUS_SUCCESS);
3327 else if( (pDirEntry = AFSGetSpecialShareNameEntry( &uniComponentName,
3328 &uniRemainingPath)) != NULL)
3331 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3332 AFS_TRACE_LEVEL_VERBOSE_2,
3333 "AFSParseName (%08lX) Returning root share name %wZ access\n",
3338 // Add in the full share name to pass back
3341 if( uniRemainingPath.Buffer != NULL)
3345 // This routine strips off the leading slash so add it back in
3348 uniRemainingPath.Buffer--;
3349 uniRemainingPath.Length += sizeof( WCHAR);
3350 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3353 // And the cell name
3356 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3357 uniRemainingPath.Length += uniComponentName.Length;
3358 uniRemainingPath.MaximumLength += uniComponentName.Length;
3360 uniComponentName = uniRemainingPath;
3365 *FileName = uniComponentName;
3367 *ParentDirectoryCB = pDirEntry;
3369 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3371 InterlockedIncrement( &pDirEntry->OpenReferenceCount);
3373 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3374 AFS_TRACE_LEVEL_VERBOSE,
3375 "AFSParseName Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
3376 &pDirEntry->NameInformation.FileName,
3379 pDirEntry->OpenReferenceCount);
3381 try_return( ntStatus = STATUS_SUCCESS);
3385 // Determine the 'share' we are accessing
3388 ulCRC = AFSGenerateCRC( &uniComponentName,
3391 AFSAcquireShared( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3394 bReleaseTreeLock = TRUE;
3396 AFSLocateCaseSensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
3400 if( pDirEntry == NULL)
3403 ulCRC = AFSGenerateCRC( &uniComponentName,
3406 AFSLocateCaseInsensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
3410 if( pDirEntry == NULL)
3414 // OK, if this component is a valid short name then try
3415 // a lookup in the short name tree
3418 if( RtlIsNameLegalDOS8Dot3( &uniComponentName,
3423 AFSLocateShortNameDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.ShortNameTree,
3428 if( pDirEntry == NULL)
3432 // Check with the service whether it is a valid cell name
3435 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3437 bReleaseTreeLock = FALSE;
3439 ntStatus = AFSCheckCellName( AuthGroup,
3443 if( !NT_SUCCESS( ntStatus))
3447 uniRemainingPath.Length == 0 &&
3448 ntStatus == STATUS_OBJECT_PATH_NOT_FOUND)
3451 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
3454 try_return( ntStatus);
3460 if( bReleaseTreeLock)
3462 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3466 // Be sure we are starting from the correct volume
3469 if( pDirEntry->ObjectInformation->VolumeCB != AFSGlobalRoot)
3473 // We dropped the global root in the CheckCellName routine which is the
3474 // only way we can be here
3477 pVolumeCB = pDirEntry->ObjectInformation->VolumeCB;
3480 // In this case don't add back in the 'share' name since that is where we are
3481 // starting. Just put the leading slash back in
3484 if( uniRemainingPath.Buffer != NULL)
3487 uniRemainingPath.Buffer--;
3488 uniRemainingPath.Length += sizeof( WCHAR);
3489 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3491 if( uniRemainingPath.Length > sizeof( WCHAR))
3494 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3498 // Pass back the parent being the root of the volume
3501 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3507 // Pass back a root slash
3510 uniRemainingPath = uniComponentName;
3512 uniRemainingPath.Buffer--;
3513 uniRemainingPath.Length = sizeof( WCHAR);
3514 uniRemainingPath.MaximumLength = sizeof( WCHAR);
3517 // This is a root open so pass back no parent
3520 *ParentDirectoryCB = NULL;
3526 pVolumeCB = AFSGlobalRoot;
3529 // Add back in the 'share' portion of the name since we will parse it out on return
3532 if( uniRemainingPath.Buffer != NULL)
3536 // This routine strips off the leading slash so add it back in
3539 uniRemainingPath.Buffer--;
3540 uniRemainingPath.Length += sizeof( WCHAR);
3541 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3543 if( uniRemainingPath.Length > sizeof( WCHAR))
3546 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3550 // And the cell name
3553 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3554 uniRemainingPath.Length += uniComponentName.Length;
3555 uniRemainingPath.MaximumLength += uniComponentName.Length;
3560 uniRemainingPath = uniComponentName;
3564 // And the leading slash again ...
3567 uniRemainingPath.Buffer--;
3568 uniRemainingPath.Length += sizeof( WCHAR);
3569 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3571 InterlockedIncrement( &pVolumeCB->DirectoryCB->OpenReferenceCount);
3573 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3574 AFS_TRACE_LEVEL_VERBOSE,
3575 "AFSParseName Increment6 count on %wZ DE %p Ccb %p Cnt %d\n",
3576 &pVolumeCB->DirectoryCB->NameInformation.FileName,
3577 pVolumeCB->DirectoryCB,
3579 pVolumeCB->DirectoryCB->OpenReferenceCount);
3582 // Pass back the parent being the volume root
3585 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3589 // Init our name array
3592 pNameArray = AFSInitNameArray( pVolumeCB->DirectoryCB,
3595 if( pNameArray == NULL)
3598 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3599 AFS_TRACE_LEVEL_VERBOSE,
3600 "AFSParseName (%08lX) Failed to initialize name array\n",
3603 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3607 // Return the remaining portion as the file name
3610 *FileName = uniRemainingPath;
3612 *ParsedFileName = uniRemainingPath;
3614 *NameArray = pNameArray;
3616 *VolumeCB = pVolumeCB;
3619 // Increment our reference on the volume
3622 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
3624 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3625 AFS_TRACE_LEVEL_VERBOSE,
3626 "AFSParseName Increment2 count on global volume %08lX Cnt %d\n",
3628 pVolumeCB->VolumeReferenceCount);
3632 if( NT_SUCCESS( ntStatus))
3635 if( *ParentDirectoryCB != NULL)
3638 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3639 AFS_TRACE_LEVEL_VERBOSE,
3640 "AFSParseName Count on %wZ DE %p Ccb %p Cnt %d\n",
3641 &(*ParentDirectoryCB)->NameInformation.FileName,
3644 (*ParentDirectoryCB)->OpenReferenceCount);
3648 if( *VolumeCB != NULL)
3650 ASSERT( (*VolumeCB)->VolumeReferenceCount > 1);
3653 if( ntStatus != STATUS_SUCCESS)
3656 if( pNameArray != NULL)
3659 AFSFreeNameArray( pNameArray);
3668 AFSCheckCellName( IN GUID *AuthGroup,
3669 IN UNICODE_STRING *CellName,
3670 OUT AFSDirectoryCB **ShareDirEntry)
3673 NTSTATUS ntStatus = STATUS_SUCCESS;
3674 UNICODE_STRING uniName;
3675 AFSDirEnumEntry *pDirEnumEntry = NULL;
3676 AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3677 AFSDirHdr *pDirHdr = &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr;
3678 AFSDirectoryCB *pDirNode = NULL;
3679 UNICODE_STRING uniDirName, uniTargetName;
3680 AFSVolumeCB *pVolumeCB = NULL;
3686 // Look for some default names we will not handle
3689 RtlInitUnicodeString( &uniName,
3692 if( RtlCompareUnicodeString( &uniName,
3697 try_return( ntStatus = STATUS_NO_SUCH_FILE);
3700 RtlInitUnicodeString( &uniName,
3703 if( RtlCompareUnicodeString( &uniName,
3708 try_return( ntStatus = STATUS_NO_SUCH_FILE);
3711 RtlInitUnicodeString( &uniName,
3714 if( RtlCompareUnicodeString( &uniName,
3719 try_return( ntStatus = STATUS_NO_SUCH_FILE);
3722 RtlInitUnicodeString( &uniName,
3725 if( RtlCompareUnicodeString( &uniName,
3730 try_return( ntStatus = STATUS_NO_SUCH_FILE);
3734 // OK, ask the CM about this component name
3737 ntStatus = AFSEvaluateTargetByName( AuthGroup,
3738 &AFSGlobalRoot->ObjectInformation,
3742 if( !NT_SUCCESS( ntStatus))
3745 try_return( ntStatus);
3749 // OK, we have a dir enum entry back so add it to the root node
3752 uniDirName = *CellName;
3754 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
3755 uniTargetName.MaximumLength = uniTargetName.Length;
3756 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
3759 // Is this entry a root volume entry?
3762 if( pDirEnumEntry->FileId.Cell != AFSGlobalRoot->ObjectInformation.FileId.Cell ||
3763 pDirEnumEntry->FileId.Volume != AFSGlobalRoot->ObjectInformation.FileId.Volume)
3767 // Build the root volume entry
3770 ntStatus = AFSBuildRootVolume( AuthGroup,
3771 &pDirEnumEntry->FileId,
3774 if( !NT_SUCCESS( ntStatus))
3776 try_return( ntStatus);
3779 *ShareDirEntry = pVolumeCB->DirectoryCB;
3781 InterlockedIncrement( &pVolumeCB->DirectoryCB->OpenReferenceCount);
3783 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3784 AFS_TRACE_LEVEL_VERBOSE,
3785 "AFSCheckCellName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
3786 &pVolumeCB->DirectoryCB->NameInformation.FileName,
3787 pVolumeCB->DirectoryCB,
3789 pVolumeCB->DirectoryCB->OpenReferenceCount);
3791 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
3796 pDirNode = AFSInitDirEntry( &AFSGlobalRoot->ObjectInformation,
3800 (ULONG)InterlockedIncrement( &pDirHdr->ContentIndex));
3802 if( pDirNode == NULL)
3805 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3809 // Init the short name if we have one
3812 if( pDirEnumEntry->ShortNameLength > 0)
3815 pDirNode->NameInformation.ShortNameLength = pDirEnumEntry->ShortNameLength;
3817 RtlCopyMemory( pDirNode->NameInformation.ShortName,
3818 pDirEnumEntry->ShortName,
3819 pDirNode->NameInformation.ShortNameLength);
3822 AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3826 // Insert the node into the name tree
3829 ASSERT( ExIsResourceAcquiredExclusiveLite( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock));
3831 if( pDirHdr->CaseSensitiveTreeHead == NULL)
3834 pDirHdr->CaseSensitiveTreeHead = pDirNode;
3839 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( pDirHdr->CaseSensitiveTreeHead,
3843 AFSDeleteDirEntry( &AFSGlobalRoot->ObjectInformation,
3846 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3848 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3852 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
3854 if( pDirHdr->CaseInsensitiveTreeHead == NULL)
3857 pDirHdr->CaseInsensitiveTreeHead = pDirNode;
3859 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
3864 AFSInsertCaseInsensitiveDirEntry( pDirHdr->CaseInsensitiveTreeHead,
3868 if( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead == NULL)
3871 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead = pDirNode;
3876 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
3878 pDirNode->ListEntry.bLink = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail;
3881 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail = pDirNode;
3883 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
3885 InterlockedIncrement( &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeCount);
3887 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
3888 AFS_TRACE_LEVEL_VERBOSE,
3889 "AFSCheckCellName Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
3890 &pDirNode->NameInformation.FileName,
3891 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeCount,
3892 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3893 AFSGlobalRoot->ObjectInformation.FileId.Volume,
3894 AFSGlobalRoot->ObjectInformation.FileId.Vnode,
3895 AFSGlobalRoot->ObjectInformation.FileId.Unique);
3897 InterlockedIncrement( &pDirNode->OpenReferenceCount);
3899 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3900 AFS_TRACE_LEVEL_VERBOSE,
3901 "AFSCheckCellName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3902 &pDirNode->NameInformation.FileName,
3905 pDirNode->OpenReferenceCount);
3907 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3910 // Pass back the dir node
3913 *ShareDirEntry = pDirNode;
3918 if( pDirEnumEntry != NULL)
3921 AFSExFreePool( pDirEnumEntry);
3929 AFSBuildMountPointTarget( IN GUID *AuthGroup,
3930 IN AFSDirectoryCB *DirectoryCB,
3931 OUT AFSVolumeCB **TargetVolumeCB)
3934 NTSTATUS ntStatus = STATUS_SUCCESS;
3935 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
3936 AFSDirEnumEntry *pDirEntry = NULL;
3937 AFSDirectoryCB *pDirNode = NULL;
3938 UNICODE_STRING uniDirName, uniTargetName;
3939 ULONGLONG ullIndex = 0;
3940 AFSVolumeCB *pVolumeCB = NULL;
3941 AFSFileID stTargetFileID;
3947 // Loop on each entry, building the chain until we encounter the final target
3950 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3951 AFS_TRACE_LEVEL_VERBOSE_2,
3952 "AFSBuildMountPointTarget Building target directory for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3953 &DirectoryCB->NameInformation.FileName,
3954 DirectoryCB->ObjectInformation->FileId.Cell,
3955 DirectoryCB->ObjectInformation->FileId.Volume,
3956 DirectoryCB->ObjectInformation->FileId.Vnode,
3957 DirectoryCB->ObjectInformation->FileId.Unique);
3960 // Do we need to evaluate the node?
3963 //if( DirectoryCB->ObjectInformation->TargetFileId.Vnode == 0 &&
3964 // DirectoryCB->ObjectInformation->TargetFileId.Unique == 0)
3968 // Go evaluate the current target to get the target fid
3971 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3972 AFS_TRACE_LEVEL_VERBOSE_2,
3973 "AFSBuildMountPointTarget Evaluating target %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3974 &DirectoryCB->NameInformation.FileName,
3975 DirectoryCB->ObjectInformation->FileId.Cell,
3976 DirectoryCB->ObjectInformation->FileId.Volume,
3977 DirectoryCB->ObjectInformation->FileId.Vnode,
3978 DirectoryCB->ObjectInformation->FileId.Unique);
3980 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
3985 if( !NT_SUCCESS( ntStatus))
3988 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3989 AFS_TRACE_LEVEL_ERROR,
3990 "AFSBuildMountPointTarget Failed to evaluate target %wZ Status %08lX\n",
3991 &DirectoryCB->NameInformation.FileName,
3993 try_return( ntStatus);
3996 if( pDirEntry->TargetFileId.Vnode == 0 &&
3997 pDirEntry->TargetFileId.Unique == 0)
4000 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4001 AFS_TRACE_LEVEL_ERROR,
4002 "AFSBuildMountPointTarget Target %wZ FID %08lX-%08lX-%08lX-%08lX service returned zero FID\n",
4003 &DirectoryCB->NameInformation.FileName,
4004 DirectoryCB->ObjectInformation->FileId.Cell,
4005 DirectoryCB->ObjectInformation->FileId.Volume,
4006 DirectoryCB->ObjectInformation->FileId.Vnode,
4007 DirectoryCB->ObjectInformation->FileId.Unique);
4009 try_return( ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED);
4012 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
4015 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
4016 &DirectoryCB->Flags,
4017 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4018 (USHORT)pDirEntry->TargetNameLength);
4020 if( !NT_SUCCESS( ntStatus))
4023 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4025 try_return( ntStatus);
4028 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4030 DirectoryCB->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
4033 stTargetFileID = DirectoryCB->ObjectInformation->TargetFileId;
4036 // Try to locate this FID. First the volume then the
4040 ullIndex = AFSCreateHighIndex( &stTargetFileID);
4042 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4043 AFS_TRACE_LEVEL_VERBOSE,
4044 "AFSBuildMountPointTarget Acquiring RDR VolumeTreeLock lock %08lX EXCL %08lX\n",
4045 &pDevExt->Specific.RDR.VolumeTreeLock,
4046 PsGetCurrentThread());
4048 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4051 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4052 AFS_TRACE_LEVEL_VERBOSE_2,
4053 "AFSBuildMountPointTarget Locating volume for target %I64X\n",
4056 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4058 (AFSBTreeEntry **)&pVolumeCB);
4061 // We can be processing a request for a target that is on a volume
4062 // we have never seen before.
4065 if( pVolumeCB == NULL)
4069 // Locking is held correctly in init routine
4072 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4075 // Go init the root of the volume
4078 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4079 AFS_TRACE_LEVEL_VERBOSE_2,
4080 "AFSBuildMountPointTarget Initializing root for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4081 &DirectoryCB->NameInformation.FileName,
4082 DirectoryCB->ObjectInformation->FileId.Cell,
4083 DirectoryCB->ObjectInformation->FileId.Volume,
4084 DirectoryCB->ObjectInformation->FileId.Vnode,
4085 DirectoryCB->ObjectInformation->FileId.Unique);
4087 ntStatus = AFSInitVolume( AuthGroup,
4091 if( !NT_SUCCESS( ntStatus))
4094 try_return( ntStatus);
4101 // Check if this volume has been deleted or taken offline
4104 if( BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
4107 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4109 try_return( ntStatus = STATUS_FILE_IS_OFFLINE);
4113 // Just to ensure that things don't get torn down AND we don't create a
4114 // deadlock with invalidation
4117 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
4119 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4121 AFSAcquireExcl( pVolumeCB->VolumeLock,
4124 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
4127 if( pVolumeCB->RootFcb == NULL)
4131 // Initialize the root fcb for this volume
4134 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4137 if( !NT_SUCCESS( ntStatus))
4140 AFSReleaseResource( pVolumeCB->VolumeLock);
4142 try_return( ntStatus);
4146 // Drop the lock acquired above
4149 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4152 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4153 AFS_TRACE_LEVEL_VERBOSE_2,
4154 "AFSBuildMountPointTarget Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4155 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4156 pVolumeCB->ObjectInformation.FileId.Cell,
4157 pVolumeCB->ObjectInformation.FileId.Volume,
4158 pVolumeCB->ObjectInformation.FileId.Vnode,
4159 pVolumeCB->ObjectInformation.FileId.Unique);
4161 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
4163 AFSReleaseResource( pVolumeCB->VolumeLock);
4165 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4166 AFS_TRACE_LEVEL_VERBOSE,
4167 "AFSBuildMountPointTarget Increment count on volume %08lX Cnt %d\n",
4169 pVolumeCB->VolumeReferenceCount);
4171 *TargetVolumeCB = pVolumeCB;
4178 AFSExFreePool( pDirEntry);
4186 AFSBuildRootVolume( IN GUID *AuthGroup,
4187 IN AFSFileID *FileId,
4188 OUT AFSVolumeCB **TargetVolumeCB)
4191 NTSTATUS ntStatus = STATUS_SUCCESS;
4192 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4193 AFSDirectoryCB *pDirNode = NULL;
4194 UNICODE_STRING uniDirName, uniTargetName;
4195 ULONGLONG ullIndex = 0;
4196 AFSVolumeCB *pVolumeCB = NULL;
4201 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4202 AFS_TRACE_LEVEL_VERBOSE_2,
4203 "AFSBuildRootVolume Building target volume for FID %08lX-%08lX-%08lX-%08lX\n",
4209 ullIndex = AFSCreateHighIndex( FileId);
4211 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4212 AFS_TRACE_LEVEL_VERBOSE,
4213 "AFSBuildRootVolume Acquiring RDR VolumeTreeLock lock %08lX EXCL %08lX\n",
4214 &pDevExt->Specific.RDR.VolumeTreeLock,
4215 PsGetCurrentThread());
4217 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4220 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4221 AFS_TRACE_LEVEL_VERBOSE_2,
4222 "AFSBuildRootVolume Locating volume for target %I64X\n",
4225 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4227 (AFSBTreeEntry **)&pVolumeCB);
4230 // We can be processing a request for a target that is on a volume
4231 // we have never seen before.
4234 if( pVolumeCB == NULL)
4238 // Locking is held correctly in init routine
4241 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4244 // Go init the root of the volume
4247 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4248 AFS_TRACE_LEVEL_VERBOSE_2,
4249 "AFSBuildRootVolume Initializing root for FID %08lX-%08lX-%08lX-%08lX\n",
4255 ntStatus = AFSInitVolume( AuthGroup,
4259 if( !NT_SUCCESS( ntStatus))
4262 try_return( ntStatus);
4269 // Just to ensure that things don't get torn down AND we don't create a
4270 // deadlock with invalidation
4273 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
4275 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4277 AFSAcquireExcl( pVolumeCB->VolumeLock,
4280 InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
4284 if( pVolumeCB->RootFcb == NULL)
4288 // Initialize the root fcb for this volume
4291 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4294 if( !NT_SUCCESS( ntStatus))
4297 AFSReleaseResource( pVolumeCB->VolumeLock);
4299 try_return( ntStatus);
4303 // Drop the lock acquired above
4306 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4309 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4310 AFS_TRACE_LEVEL_VERBOSE_2,
4311 "AFSBuildRootVolume Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4312 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4313 pVolumeCB->ObjectInformation.FileId.Cell,
4314 pVolumeCB->ObjectInformation.FileId.Volume,
4315 pVolumeCB->ObjectInformation.FileId.Vnode,
4316 pVolumeCB->ObjectInformation.FileId.Unique);
4318 InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
4320 AFSReleaseResource( pVolumeCB->VolumeLock);
4322 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4323 AFS_TRACE_LEVEL_VERBOSE,
4324 "AFSBuildRootVolume Increment count on volume %08lX Cnt %d\n",
4326 pVolumeCB->VolumeReferenceCount);
4328 *TargetVolumeCB = pVolumeCB;
4339 AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
4340 IN PFILE_OBJECT FileObject,
4341 IN UNICODE_STRING *RemainingPath,
4345 NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
4346 UNICODE_STRING uniReparseName;
4347 UNICODE_STRING uniMUPDeviceName;
4348 AFSDirEnumEntry *pDirEntry = NULL;
4354 // Build up the name to reparse
4357 RtlInitUnicodeString( &uniMUPDeviceName,
4360 uniReparseName.Length = 0;
4361 uniReparseName.Buffer = NULL;
4364 // Be sure we have a target name
4367 if( DirEntry->NameInformation.TargetName.Length == 0)
4370 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
4375 if( !NT_SUCCESS( ntStatus) ||
4376 pDirEntry->TargetNameLength == 0)
4379 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4380 AFS_TRACE_LEVEL_ERROR,
4381 "AFSProcessDFSLink EvaluateTargetByID failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4382 &DirEntry->NameInformation.FileName,
4383 DirEntry->ObjectInformation->FileId.Cell,
4384 DirEntry->ObjectInformation->FileId.Volume,
4385 DirEntry->ObjectInformation->FileId.Vnode,
4386 DirEntry->ObjectInformation->FileId.Unique,
4389 if( NT_SUCCESS( ntStatus))
4392 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
4395 try_return( ntStatus);
4399 // Update the target name
4402 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
4405 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
4407 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4408 (USHORT)pDirEntry->TargetNameLength);
4410 if( !NT_SUCCESS( ntStatus))
4413 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4414 AFS_TRACE_LEVEL_ERROR,
4415 "AFSProcessDFSLink UpdateTargetName failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4416 &DirEntry->NameInformation.FileName,
4417 DirEntry->ObjectInformation->FileId.Cell,
4418 DirEntry->ObjectInformation->FileId.Volume,
4419 DirEntry->ObjectInformation->FileId.Vnode,
4420 DirEntry->ObjectInformation->FileId.Unique,
4423 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4425 try_return( ntStatus);
4428 AFSConvertToShared( &DirEntry->NonPaged->Lock);
4432 AFSAcquireShared( &DirEntry->NonPaged->Lock,
4436 uniReparseName.MaximumLength = uniMUPDeviceName.Length +
4438 DirEntry->NameInformation.TargetName.Length +
4441 if( RemainingPath != NULL &&
4442 RemainingPath->Length > 0)
4445 uniReparseName.MaximumLength += RemainingPath->Length;
4449 // Allocate the reparse buffer
4452 uniReparseName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4453 uniReparseName.MaximumLength,
4454 AFS_REPARSE_NAME_TAG);
4456 if( uniReparseName.Buffer == NULL)
4459 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4460 AFS_TRACE_LEVEL_ERROR,
4461 "AFSProcessDFSLink uniReparseName.Buffer == NULL Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4462 &DirEntry->NameInformation.FileName,
4463 DirEntry->ObjectInformation->FileId.Cell,
4464 DirEntry->ObjectInformation->FileId.Volume,
4465 DirEntry->ObjectInformation->FileId.Vnode,
4466 DirEntry->ObjectInformation->FileId.Unique,
4467 STATUS_INSUFFICIENT_RESOURCES);
4469 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4471 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4475 // Start building the name
4478 RtlCopyMemory( uniReparseName.Buffer,
4479 uniMUPDeviceName.Buffer,
4480 uniMUPDeviceName.Length);
4482 uniReparseName.Length = uniMUPDeviceName.Length;
4484 if( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\')
4487 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
4489 uniReparseName.Length += sizeof( WCHAR);
4492 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
4493 DirEntry->NameInformation.TargetName.Buffer,
4494 DirEntry->NameInformation.TargetName.Length);
4496 uniReparseName.Length += DirEntry->NameInformation.TargetName.Length;
4498 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4500 if( RemainingPath != NULL &&
4501 RemainingPath->Length > 0)
4504 if( uniReparseName.Buffer[ (uniReparseName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
4505 RemainingPath->Buffer[ 0] != L'\\')
4508 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
4510 uniReparseName.Length += sizeof( WCHAR);
4513 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
4514 RemainingPath->Buffer,
4515 RemainingPath->Length);
4517 uniReparseName.Length += RemainingPath->Length;
4521 // Update the name in the file object
4524 if( FileObject->FileName.Buffer != NULL)
4527 AFSExFreePool( FileObject->FileName.Buffer);
4530 FileObject->FileName = uniReparseName;
4532 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4533 AFS_TRACE_LEVEL_VERBOSE,
4534 "AFSProcessDFSLink Reparsing access to Fcb %wZ FID %08lX-%08lX-%08lX-%08lX to %wZ\n",
4535 &DirEntry->NameInformation.FileName,
4536 DirEntry->ObjectInformation->FileId.Cell,
4537 DirEntry->ObjectInformation->FileId.Volume,
4538 DirEntry->ObjectInformation->FileId.Vnode,
4539 DirEntry->ObjectInformation->FileId.Unique,
4543 // Return status reparse ...
4546 ntStatus = STATUS_REPARSE;
4553 AFSExFreePool( pDirEntry);