2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSNameSupport.cpp
39 #include "AFSCommon.h"
44 // On entry, *VolumeCB must have a held ReferenceCount provided by
45 // the caller which will not be released. On successful exit, *OutVolumeCB
46 // will be assigned the new current volume with a held ReferenceCount.
48 // On entry, *ParentDirectoryCB must have a held DirOpenReferenceCount
49 // provided by the caller. This reference will not be released.
50 // On exit, if OutParentDirectoryCB is set, it will have a new reference.
52 // On exit, if OutDirectoryCB is set, it will have a reference.
56 AFSLocateNameEntry( IN GUID *AuthGroup,
57 IN PFILE_OBJECT FileObject,
58 IN OUT UNICODE_STRING *RootPathName,
59 IN UNICODE_STRING *ParsedPathName,
60 IN AFSNameArrayHdr *NameArray,
62 IN AFSVolumeCB *VolumeCB,
63 IN AFSDirectoryCB *ParentDirectoryCB,
64 OUT AFSVolumeCB **OutVolumeCB,
65 OUT LONG *OutVolumeReferenceReason,
66 OUT AFSDirectoryCB **OutParentDirectoryCB,
67 OUT AFSDirectoryCB **OutDirectoryCB,
68 OUT PUNICODE_STRING ComponentName)
71 NTSTATUS ntStatus = STATUS_SUCCESS;
72 UNICODE_STRING uniPathName, uniComponentName, uniRemainingPath, uniSearchName, uniFullPathName;
74 AFSDirectoryCB *pDirEntry = NULL, *pParentDirEntry = NULL;
75 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
76 UNICODE_STRING uniSysName;
77 ULONG ulSubstituteIndex = 0;
78 BOOLEAN bSubstituteName = FALSE;
79 AFSNameArrayHdr *pNameArray = NameArray;
80 BOOLEAN bAllocatedSymLinkBuffer = FALSE;
81 UNICODE_STRING uniRelativeName, uniNoOpName;
82 AFSObjectInfoCB *pCurrentObject = NULL;
83 AFSObjectInfoCB *pParentObjectInfo = NULL;
84 AFSVolumeCB *pCurrentVolume = NULL;
85 AFSVolumeCB *pTargetVolume = NULL;
86 BOOLEAN bReleaseCurrentVolume = FALSE;
87 LONG VolumeReferenceReason;
88 BOOLEAN bSubstitutedName = FALSE;
94 ASSERT( *OutVolumeCB != VolumeCB);
96 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
97 AFS_TRACE_LEVEL_VERBOSE_2,
98 "AFSLocateNameEntry (FO: %p) Processing full name %wZ\n",
102 RtlInitUnicodeString( &uniSysName,
105 RtlInitUnicodeString( &uniRelativeName,
108 RtlInitUnicodeString( &uniNoOpName,
112 // Cleanup some parameters
115 if( ComponentName != NULL)
118 ComponentName->Length = 0;
119 ComponentName->MaximumLength = 0;
120 ComponentName->Buffer = NULL;
124 // We will parse through the filename, locating the directory nodes until we encounter a cache miss
125 // Starting at the root node
128 pParentDirEntry = NULL;
130 pDirEntry = ParentDirectoryCB;
133 // Increment our reference on this dir entry
136 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
138 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
139 AFS_TRACE_LEVEL_VERBOSE,
140 "AFSLocateNameEntry Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
141 &pDirEntry->NameInformation.FileName,
146 pCurrentVolume = VolumeCB;
148 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
150 lCount = AFSVolumeIncrement( pCurrentVolume,
151 VolumeReferenceReason);
153 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
154 AFS_TRACE_LEVEL_VERBOSE,
155 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
157 VolumeReferenceReason,
160 bReleaseCurrentVolume = TRUE;
162 uniPathName = *ParsedPathName;
164 uniFullPathName = *RootPathName;
166 uniComponentName.Length = uniComponentName.MaximumLength = 0;
167 uniComponentName.Buffer = NULL;
169 uniRemainingPath.Length = uniRemainingPath.MaximumLength = 0;
170 uniRemainingPath.Buffer = NULL;
172 uniSearchName.Length = uniSearchName.MaximumLength = 0;
173 uniSearchName.Buffer = NULL;
178 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
180 ASSERT( pDirEntry->DirOpenReferenceCount > 0);
183 // Check our total link count for this name array
186 if( pNameArray->LinkCount >= (LONG)pDevExt->Specific.RDR.MaxLinkCount)
189 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
192 pCurrentObject = pDirEntry->ObjectInformation;
194 KeQueryTickCount( &pCurrentObject->LastAccessCount);
197 // Check that the directory entry is not deleted or pending delete
200 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
203 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
204 AFS_TRACE_LEVEL_ERROR,
205 "AFSLocateNameEntry (FO: %p) Deleted parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
207 &pDirEntry->NameInformation.FileName,
208 pCurrentObject->FileId.Cell,
209 pCurrentObject->FileId.Volume,
210 pCurrentObject->FileId.Vnode,
211 pCurrentObject->FileId.Unique,
212 STATUS_FILE_DELETED);
214 try_return( ntStatus = STATUS_FILE_DELETED);
217 if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
220 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
221 AFS_TRACE_LEVEL_ERROR,
222 "AFSLocateNameEntry (FO: %p) Delete pending on %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
224 &pDirEntry->NameInformation.FileName,
225 pCurrentObject->FileId.Cell,
226 pCurrentObject->FileId.Volume,
227 pCurrentObject->FileId.Vnode,
228 pCurrentObject->FileId.Unique,
229 STATUS_DELETE_PENDING);
231 try_return( ntStatus = STATUS_DELETE_PENDING);
235 // Check if the directory requires verification
238 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
239 ( pCurrentObject->FileType != AFS_FILE_TYPE_DIRECTORY ||
240 !AFSIsEnumerationInProcess( pCurrentObject)))
243 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
244 AFS_TRACE_LEVEL_VERBOSE,
245 "AFSLocateNameEntry (FO: %p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
247 &pDirEntry->NameInformation.FileName,
248 pCurrentObject->FileId.Cell,
249 pCurrentObject->FileId.Volume,
250 pCurrentObject->FileId.Vnode,
251 pCurrentObject->FileId.Unique);
254 // Directory TreeLock should be exclusively held
257 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
260 ntStatus = AFSVerifyEntry( AuthGroup,
263 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
265 if( !NT_SUCCESS( ntStatus))
268 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
269 AFS_TRACE_LEVEL_ERROR,
270 "AFSLocateNameEntry (FO: %p) Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
272 &pDirEntry->NameInformation.FileName,
273 pCurrentObject->FileId.Cell,
274 pCurrentObject->FileId.Volume,
275 pCurrentObject->FileId.Vnode,
276 pCurrentObject->FileId.Unique,
279 try_return( ntStatus);
284 // Ensure the parent node has been evaluated, if not then go do it now
287 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) ||
288 pCurrentObject->FileType == AFS_FILE_TYPE_UNKNOWN)
291 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
292 AFS_TRACE_LEVEL_VERBOSE,
293 "AFSLocateNameEntry (FO: %p) Evaluating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
295 &pDirEntry->NameInformation.FileName,
296 pCurrentObject->FileId.Cell,
297 pCurrentObject->FileId.Volume,
298 pCurrentObject->FileId.Vnode,
299 pCurrentObject->FileId.Unique);
301 ntStatus = AFSEvaluateNode( AuthGroup,
304 if( !NT_SUCCESS( ntStatus))
307 if ( ntStatus == STATUS_NOT_A_DIRECTORY)
310 if ( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
313 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
314 AFS_TRACE_LEVEL_ERROR,
315 "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT NULL Status %08lX\n",
317 &pDirEntry->NameInformation.FileName,
318 pCurrentObject->FileId.Cell,
319 pCurrentObject->FileId.Volume,
320 pCurrentObject->FileId.Vnode,
321 pCurrentObject->FileId.Unique,
327 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
328 AFS_TRACE_LEVEL_ERROR,
329 "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT %08lX-%08lX-%08lX-%08lX Status %08lX\n",
331 &pDirEntry->NameInformation.FileName,
332 pCurrentObject->FileId.Cell,
333 pCurrentObject->FileId.Volume,
334 pCurrentObject->FileId.Vnode,
335 pCurrentObject->FileId.Unique,
336 pCurrentObject->ParentFileId.Cell,
337 pCurrentObject->ParentFileId.Volume,
338 pCurrentObject->ParentFileId.Vnode,
339 pCurrentObject->ParentFileId.Unique,
345 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
346 AFS_TRACE_LEVEL_ERROR,
347 "AFSLocateNameEntry (FO: %p) Failed to evaluate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
349 &pDirEntry->NameInformation.FileName,
350 pCurrentObject->FileId.Cell,
351 pCurrentObject->FileId.Volume,
352 pCurrentObject->FileId.Vnode,
353 pCurrentObject->FileId.Unique,
357 try_return( ntStatus);
360 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
364 // If this is a mount point or symlink then go get the real directory node
367 switch( pCurrentObject->FileType)
370 case AFS_FILE_TYPE_SYMLINK:
373 UNICODE_STRING uniTempName;
374 WCHAR *pTmpBuffer = NULL;
378 // Check if the flag is set to NOT evaluate a symlink
379 // and we are done with the parsing
382 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL) &&
383 uniRemainingPath.Length == 0)
387 // Pass back the directory entries
390 *OutParentDirectoryCB = pParentDirEntry;
392 pParentDirEntry = NULL;
394 *OutDirectoryCB = pDirEntry;
398 *OutVolumeCB = pCurrentVolume;
400 *OutVolumeReferenceReason = VolumeReferenceReason;
402 bReleaseCurrentVolume = FALSE;
404 *RootPathName = uniFullPathName;
406 try_return( ntStatus);
409 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
412 AFSAcquireExcl( &pDirEntry->NonPaged->Lock,
415 if( pDirEntry->NameInformation.TargetName.Length == 0)
419 // We'll reset the DV to ensure we validate the metadata content
422 pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
424 SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
426 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
427 AFS_TRACE_LEVEL_VERBOSE,
428 "AFSLocateNameEntry (FO: %p) Verifying symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
430 &pDirEntry->NameInformation.FileName,
431 pCurrentObject->FileId.Cell,
432 pCurrentObject->FileId.Volume,
433 pCurrentObject->FileId.Vnode,
434 pCurrentObject->FileId.Unique);
437 // Directory TreeLock should be exclusively held
440 ntStatus = AFSVerifyEntry( AuthGroup,
443 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
445 if( !NT_SUCCESS( ntStatus))
448 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
449 AFS_TRACE_LEVEL_ERROR,
450 "AFSLocateNameEntry (FO: %p) Failed to verify symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
452 &pDirEntry->NameInformation.FileName,
453 pCurrentObject->FileId.Cell,
454 pCurrentObject->FileId.Volume,
455 pCurrentObject->FileId.Vnode,
456 pCurrentObject->FileId.Unique,
459 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
461 try_return( ntStatus);
465 // If the type changed then reprocess this entry
468 if( pCurrentObject->FileType != AFS_FILE_TYPE_SYMLINK)
471 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
479 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
483 // If we were given a zero length target name then deny access to the entry
486 if( pDirEntry->NameInformation.TargetName.Length == 0)
489 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
491 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
492 AFS_TRACE_LEVEL_ERROR,
493 "AFSLocateNameEntry (FO: %p) Failed to retrieve target name for symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
495 &pDirEntry->NameInformation.FileName,
496 pCurrentObject->FileId.Cell,
497 pCurrentObject->FileId.Volume,
498 pCurrentObject->FileId.Vnode,
499 pCurrentObject->FileId.Unique,
502 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
504 try_return( ntStatus);
507 if( AFSIsRelativeName( &pDirEntry->NameInformation.TargetName))
510 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
511 AFS_TRACE_LEVEL_VERBOSE,
512 "AFSLocateNameEntry (FO: %p) Processing relative symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
514 &pDirEntry->NameInformation.TargetName,
515 &pDirEntry->NameInformation.FileName,
516 pCurrentObject->FileId.Cell,
517 pCurrentObject->FileId.Volume,
518 pCurrentObject->FileId.Vnode,
519 pCurrentObject->FileId.Unique);
522 // We'll substitute this name into the current process name
523 // starting at where we sit in the path
526 uniTempName.Length = 0;
527 uniTempName.MaximumLength = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer) +
528 pDirEntry->NameInformation.TargetName.Length +
530 uniRemainingPath.Length;
532 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
533 uniTempName.MaximumLength,
534 AFS_NAME_BUFFER_ONE_TAG);
536 if( uniTempName.Buffer == NULL)
539 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
541 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
545 // We have so first copy in the portion up to the component
549 RtlCopyMemory( uniTempName.Buffer,
550 uniFullPathName.Buffer,
551 (ULONG)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer));
553 uniTempName.Length = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer);
555 if( bAllocatedSymLinkBuffer ||
559 pTmpBuffer = uniFullPathName.Buffer;
562 bAllocatedSymLinkBuffer = TRUE;
565 // Have we parsed this name yet? Better have at least once ...
568 if( uniComponentName.Length == 0)
574 // Copy in the target name ...
577 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
578 pDirEntry->NameInformation.TargetName.Buffer,
579 pDirEntry->NameInformation.TargetName.Length);
581 uniPathName.Buffer = &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)];
583 uniPathName.Length += pDirEntry->NameInformation.TargetName.Length;
584 uniPathName.MaximumLength = uniTempName.MaximumLength;
586 uniTempName.Length += pDirEntry->NameInformation.TargetName.Length;
589 // And now any remaining portion of the name
592 if( uniRemainingPath.Length > 0)
595 if( uniRemainingPath.Buffer[ 0] != L'\\')
598 uniRemainingPath.Buffer--;
599 uniRemainingPath.Length += sizeof( WCHAR);
601 uniPathName.Length += sizeof( WCHAR);
604 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
605 uniRemainingPath.Buffer,
606 uniRemainingPath.Length);
608 uniTempName.Length += uniRemainingPath.Length;
611 uniFullPathName = uniTempName;
613 if( pTmpBuffer != NULL)
616 AFSExFreePoolWithTag( pTmpBuffer, 0);
619 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
622 // Dereference the current entry ..
625 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
627 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
628 AFS_TRACE_LEVEL_VERBOSE,
629 "AFSLocateNameEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
630 &pDirEntry->NameInformation.FileName,
635 ASSERT( lCount >= 0);
638 // OK, need to back up one entry for the correct parent since the current
639 // entry we are on is the symlink itself
642 pDirEntry = AFSBackupEntry( pNameArray);
645 // Increment our reference on this dir entry
648 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
650 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
651 AFS_TRACE_LEVEL_VERBOSE,
652 "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
653 &pDirEntry->NameInformation.FileName,
658 if ( pParentDirEntry)
661 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
663 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
664 AFS_TRACE_LEVEL_VERBOSE,
665 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
666 &pParentDirEntry->NameInformation.FileName,
671 pParentDirEntry = NULL;
674 if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
677 pParentDirEntry = AFSGetParentEntry( pNameArray);
679 ASSERT( pParentDirEntry != pDirEntry);
681 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
683 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
684 AFS_TRACE_LEVEL_VERBOSE,
685 "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
686 &pParentDirEntry->NameInformation.FileName,
695 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
696 AFS_TRACE_LEVEL_VERBOSE,
697 "AFSLocateNameEntry (FO: %p) Processing absolute symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
699 &pDirEntry->NameInformation.TargetName,
700 &pDirEntry->NameInformation.FileName,
701 pCurrentObject->FileId.Cell,
702 pCurrentObject->FileId.Volume,
703 pCurrentObject->FileId.Vnode,
704 pCurrentObject->FileId.Unique);
706 if ( !AFSIsAbsoluteAFSName( &pDirEntry->NameInformation.TargetName))
709 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
710 AFS_TRACE_LEVEL_ERROR,
711 "AFSLocateNameEntry Name %wZ contains invalid server name\n",
712 &pDirEntry->NameInformation.TargetName);
715 // The correct response would be STATUS_OBJECT_PATH_INVALID
716 // but that prevents cmd.exe from performing a recursive
717 // directory enumeration when opening a directory entry
718 // that represents a symlink to an invalid path is discovered.
721 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
723 try_return( ntStatus = STATUS_OBJECT_PATH_NOT_FOUND);
727 // We'll substitute this name into the current process name
728 // starting at where we sit in the path
731 uniTempName.Length = 0;
732 uniTempName.MaximumLength = pDirEntry->NameInformation.TargetName.Length +
734 uniRemainingPath.Length;
736 uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
737 uniTempName.MaximumLength,
738 AFS_NAME_BUFFER_TWO_TAG);
740 if( uniTempName.Buffer == NULL)
743 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
745 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
748 if( bAllocatedSymLinkBuffer ||
752 pTmpBuffer = uniFullPathName.Buffer;
755 bAllocatedSymLinkBuffer = TRUE;
758 // Have we parsed this name yet? Better have at least once ...
761 if( uniComponentName.Length == 0)
767 // Copy in the target name ...
770 RtlCopyMemory( uniTempName.Buffer,
771 &pDirEntry->NameInformation.TargetName.Buffer[ AFSMountRootName.Length/sizeof( WCHAR)],
772 pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length);
774 uniTempName.Length = pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length;
777 // And now any remaining portion of the name
780 if( uniRemainingPath.Length > 0)
783 if( uniRemainingPath.Buffer[ 0] != L'\\')
786 uniRemainingPath.Buffer--;
787 uniRemainingPath.Length += sizeof( WCHAR);
790 RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
791 uniRemainingPath.Buffer,
792 uniRemainingPath.Length);
794 uniTempName.Length += uniRemainingPath.Length;
797 uniFullPathName = uniTempName;
799 uniPathName = uniTempName;
801 if( pTmpBuffer != NULL)
804 AFSExFreePoolWithTag( pTmpBuffer, 0);
807 AFSReleaseResource( &pDirEntry->NonPaged->Lock);
810 // If our current volume is not the global root then make it so ...
813 if( pCurrentVolume != AFSGlobalRoot)
816 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
817 AFS_TRACE_LEVEL_VERBOSE,
818 "AFSLocateNameEntry (FO: %p) Current volume not global, resetting for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
820 &pDirEntry->NameInformation.FileName,
821 pCurrentObject->FileId.Cell,
822 pCurrentObject->FileId.Volume,
823 pCurrentObject->FileId.Vnode,
824 pCurrentObject->FileId.Unique);
826 lCount = AFSVolumeDecrement( pCurrentVolume,
827 VolumeReferenceReason);
829 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
830 AFS_TRACE_LEVEL_VERBOSE,
831 "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
833 VolumeReferenceReason,
836 pCurrentVolume = AFSGlobalRoot;
838 VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
840 lCount = AFSVolumeIncrement( pCurrentVolume,
841 VolumeReferenceReason);
843 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
844 AFS_TRACE_LEVEL_VERBOSE,
845 "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
847 VolumeReferenceReason,
852 // Dereference our current dir entry
855 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
857 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
858 AFS_TRACE_LEVEL_VERBOSE,
859 "AFSLocateNameEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
860 &pDirEntry->NameInformation.FileName,
865 ASSERT( lCount >= 0);
867 pDirEntry = pCurrentVolume->DirectoryCB;
870 // Reference the new dir entry
873 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
875 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
876 AFS_TRACE_LEVEL_VERBOSE,
877 "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
878 &pDirEntry->NameInformation.FileName,
884 // Reset the name array
885 // Persist the link count in the name array
888 lLinkCount = pNameArray->LinkCount;
890 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
891 AFS_TRACE_LEVEL_VERBOSE,
892 "AFSLocateNameEntry (FO: %p) Resetting name array for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
894 &pDirEntry->NameInformation.FileName,
895 pCurrentObject->FileId.Cell,
896 pCurrentObject->FileId.Volume,
897 pCurrentObject->FileId.Vnode,
898 pCurrentObject->FileId.Unique);
900 AFSResetNameArray( pNameArray,
903 pNameArray->LinkCount = lLinkCount;
905 if ( pParentDirEntry)
908 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
910 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
911 AFS_TRACE_LEVEL_VERBOSE,
912 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
913 &pParentDirEntry->NameInformation.FileName,
918 pParentDirEntry = NULL;
923 // Increment our link count
926 lCount = InterlockedIncrement( &pNameArray->LinkCount);
931 case AFS_FILE_TYPE_MOUNTPOINT:
935 // Check if the flag is set to NOT evaluate a mount point
936 // and we are done with the parsing
939 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL) &&
940 uniRemainingPath.Length == 0)
944 // Pass back the directory entries
947 *OutParentDirectoryCB = pParentDirEntry;
949 pParentDirEntry = NULL;
951 *OutDirectoryCB = pDirEntry;
955 *OutVolumeCB = pCurrentVolume;
957 *OutVolumeReferenceReason = VolumeReferenceReason;
959 bReleaseCurrentVolume = FALSE;
961 *RootPathName = uniFullPathName;
963 try_return( ntStatus);
966 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
967 AFS_TRACE_LEVEL_VERBOSE,
968 "AFSLocateNameEntry (FO: %p) Building MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
970 &pDirEntry->NameInformation.FileName,
971 pCurrentObject->FileId.Cell,
972 pCurrentObject->FileId.Volume,
973 pCurrentObject->FileId.Vnode,
974 pCurrentObject->FileId.Unique);
977 // Go retrieve the target entry for this node
978 // Release the current volume cb entry since we would
979 // have lock inversion in the following call
980 // Also decrement the ref count on the volume
983 ntStatus = AFSBuildMountPointTarget( AuthGroup,
987 if( !NT_SUCCESS( ntStatus))
990 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
991 AFS_TRACE_LEVEL_ERROR,
992 "AFSLocateNameEntry (FO: %p) Failed to build MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
994 &pDirEntry->NameInformation.FileName,
995 pCurrentObject->FileId.Cell,
996 pCurrentObject->FileId.Volume,
997 pCurrentObject->FileId.Vnode,
998 pCurrentObject->FileId.Unique,
1001 try_return( ntStatus);
1004 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
1006 lCount = AFSVolumeDecrement( pCurrentVolume,
1007 VolumeReferenceReason);
1009 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1010 AFS_TRACE_LEVEL_VERBOSE,
1011 "AFSLocateNameEntry Decrement2 count on volume %p Reason %u Cnt %d\n",
1013 VolumeReferenceReason,
1016 pCurrentVolume = pTargetVolume;
1018 pTargetVolume = NULL;
1020 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
1022 VolumeReferenceReason = AFS_VOLUME_REFERENCE_MOUNTPT;
1025 // We want to restart processing here on the new parent ...
1026 // Deref and ref count the entries
1029 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1031 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1032 AFS_TRACE_LEVEL_VERBOSE,
1033 "AFSLocateNameEntry Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
1034 &pDirEntry->NameInformation.FileName,
1039 ASSERT( lCount >= 0);
1041 pDirEntry = pCurrentVolume->DirectoryCB;
1043 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1045 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1046 AFS_TRACE_LEVEL_VERBOSE,
1047 "AFSLocateNameEntry Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
1048 &pDirEntry->NameInformation.FileName,
1054 // The name array stores both the mount point and the target.
1055 // Insert the target.
1058 AFSInsertNextElement( pNameArray,
1061 if ( pParentDirEntry)
1064 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1066 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1067 AFS_TRACE_LEVEL_VERBOSE,
1068 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1069 &pParentDirEntry->NameInformation.FileName,
1074 pParentDirEntry = NULL;
1078 // Increment our link count
1081 lCount = InterlockedIncrement( &pNameArray->LinkCount);
1086 case AFS_FILE_TYPE_DFSLINK:
1089 if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL))
1093 // Pass back the directory entries
1096 *OutParentDirectoryCB = pParentDirEntry;
1098 pParentDirEntry = NULL;
1100 *OutDirectoryCB = pDirEntry;
1104 *OutVolumeCB = pCurrentVolume;
1106 *OutVolumeReferenceReason = VolumeReferenceReason;
1108 bReleaseCurrentVolume = FALSE;
1110 *RootPathName = uniFullPathName;
1112 try_return( ntStatus);
1116 // This is a DFS link so we need to update the file name and return STATUS_REPARSE to the
1117 // system for it to reevaluate it
1120 if( FileObject != NULL)
1123 ntStatus = AFSProcessDFSLink( pDirEntry,
1132 // This is where we have been re-entered from an NP evaluation call via the BuildBranch()
1136 ntStatus = STATUS_INVALID_PARAMETER;
1139 if( ntStatus != STATUS_SUCCESS &&
1140 ntStatus != STATUS_REPARSE)
1143 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1144 AFS_TRACE_LEVEL_ERROR,
1145 "AFSLocateNameEntry (FO: %p) Failed to process DFSLink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1147 &pDirEntry->NameInformation.FileName,
1148 pCurrentObject->FileId.Cell,
1149 pCurrentObject->FileId.Volume,
1150 pCurrentObject->FileId.Vnode,
1151 pCurrentObject->FileId.Unique,
1155 try_return( ntStatus);
1158 case AFS_FILE_TYPE_UNKNOWN:
1159 case AFS_FILE_TYPE_INVALID:
1163 // Something was not processed ...
1166 try_return( ntStatus = STATUS_ACCESS_DENIED);
1169 } /* end of switch */
1172 // If the parent is not initialized then do it now
1175 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1176 !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED) &&
1177 uniPathName.Length > 0)
1180 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1181 AFS_TRACE_LEVEL_VERBOSE,
1182 "AFSLocateNameEntry (FO: %p) Enumerating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1184 &pDirEntry->NameInformation.FileName,
1185 pCurrentObject->FileId.Cell,
1186 pCurrentObject->FileId.Volume,
1187 pCurrentObject->FileId.Vnode,
1188 pCurrentObject->FileId.Unique);
1190 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1193 if( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1196 ntStatus = AFSEnumerateDirectory( AuthGroup,
1200 if( !NT_SUCCESS( ntStatus))
1203 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1205 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1206 AFS_TRACE_LEVEL_ERROR,
1207 "AFSLocateNameEntry (FO: %p) Failed to enumerate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1209 &pDirEntry->NameInformation.FileName,
1210 pCurrentObject->FileId.Cell,
1211 pCurrentObject->FileId.Volume,
1212 pCurrentObject->FileId.Vnode,
1213 pCurrentObject->FileId.Unique,
1216 try_return( ntStatus);
1219 SetFlag( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1222 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1224 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1227 if( uniPathName.Length > 0)
1230 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1231 AFS_TRACE_LEVEL_ERROR,
1232 "AFSLocateNameEntry (FO: %p) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1234 &pDirEntry->NameInformation.FileName,
1235 pCurrentObject->FileId.Cell,
1236 pCurrentObject->FileId.Volume,
1237 pCurrentObject->FileId.Vnode,
1238 pCurrentObject->FileId.Unique);
1240 // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1241 // one of the components of the path is not a directory. However, returning
1242 // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1243 // Instead IIS insists on treating the target file as if it is a directory containing
1244 // a potential web.config file. NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1245 // AFS will follow suit.
1247 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1252 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1253 AFS_TRACE_LEVEL_VERBOSE,
1254 "AFSLocateNameEntry (FO: %p) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1256 &pDirEntry->NameInformation.FileName,
1257 pCurrentObject->FileId.Cell,
1258 pCurrentObject->FileId.Volume,
1259 pCurrentObject->FileId.Vnode,
1260 pCurrentObject->FileId.Unique);
1263 // Pass back the directory entries
1266 *OutParentDirectoryCB = pParentDirEntry;
1268 pParentDirEntry = NULL;
1270 *OutDirectoryCB = pDirEntry;
1274 *OutVolumeCB = pCurrentVolume;
1276 *OutVolumeReferenceReason = VolumeReferenceReason;
1278 bReleaseCurrentVolume = FALSE;
1280 *RootPathName = uniFullPathName;
1283 try_return( ntStatus);
1287 // If we are at the end of the processing, set our returned information and get out
1290 if( uniPathName.Length == 0)
1293 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1294 AFS_TRACE_LEVEL_VERBOSE,
1295 "AFSLocateNameEntry (FO: %p) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1297 &pDirEntry->NameInformation.FileName,
1298 pCurrentObject->FileId.Cell,
1299 pCurrentObject->FileId.Volume,
1300 pCurrentObject->FileId.Vnode,
1301 pCurrentObject->FileId.Unique);
1304 // Pass back the directory entries
1307 *OutParentDirectoryCB = pParentDirEntry;
1309 pParentDirEntry = NULL;
1311 *OutDirectoryCB = pDirEntry;
1315 *OutVolumeCB = pCurrentVolume;
1317 *OutVolumeReferenceReason = VolumeReferenceReason;
1319 bReleaseCurrentVolume = FALSE;
1321 *RootPathName = uniFullPathName;
1323 try_return( ntStatus);
1327 // We may have returned to the top of the while( TRUE)
1329 if( bSubstituteName &&
1330 uniSearchName.Buffer != NULL)
1333 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1335 bSubstituteName = FALSE;
1337 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1338 uniSearchName.Buffer = NULL;
1341 ulSubstituteIndex = 1;
1343 ntStatus = STATUS_SUCCESS;
1346 // Get the next component name
1349 FsRtlDissectName( uniPathName,
1354 // Check for the . and .. in the path
1357 if( RtlCompareUnicodeString( &uniComponentName,
1362 uniPathName = uniRemainingPath;
1367 if( RtlCompareUnicodeString( &uniComponentName,
1372 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1373 AFS_TRACE_LEVEL_VERBOSE,
1374 "AFSLocateNameEntry (FO: %p) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1376 &pDirEntry->NameInformation.FileName,
1377 pCurrentObject->FileId.Cell,
1378 pCurrentObject->FileId.Volume,
1379 pCurrentObject->FileId.Vnode,
1380 pCurrentObject->FileId.Unique);
1383 // Need to back up one entry in the name array
1385 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1387 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1388 AFS_TRACE_LEVEL_VERBOSE,
1389 "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1390 &pDirEntry->NameInformation.FileName,
1395 ASSERT( lCount >= 0);
1397 pDirEntry = AFSBackupEntry( NameArray);
1399 if( pDirEntry == NULL)
1402 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1403 AFS_TRACE_LEVEL_ERROR,
1404 "AFSLocateNameEntry AFSBackupEntry failed\n");
1406 try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1409 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1411 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1412 AFS_TRACE_LEVEL_VERBOSE,
1413 "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1414 &pDirEntry->NameInformation.FileName,
1419 if ( pParentDirEntry)
1422 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1424 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1425 AFS_TRACE_LEVEL_VERBOSE,
1426 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1427 &pParentDirEntry->NameInformation.FileName,
1432 pParentDirEntry = NULL;
1435 if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1438 pParentDirEntry = AFSGetParentEntry( pNameArray);
1440 ASSERT( pParentDirEntry != pDirEntry);
1442 if ( pParentDirEntry)
1445 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
1447 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1448 AFS_TRACE_LEVEL_VERBOSE,
1449 "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
1450 &pParentDirEntry->NameInformation.FileName,
1457 uniPathName = uniRemainingPath;
1463 // Update our pointers
1466 if ( pParentDirEntry)
1469 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1471 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1472 AFS_TRACE_LEVEL_VERBOSE,
1473 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1474 &pParentDirEntry->NameInformation.FileName,
1480 pParentDirEntry = pDirEntry;
1484 uniSearchName = uniComponentName;
1486 while( pDirEntry == NULL)
1490 // If the SearchName contains @SYS then we perform the substitution.
1491 // If there is no substitution we give up.
1494 if( !bSubstituteName &&
1495 FsRtlIsNameInExpression( &uniSysName,
1501 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1502 AFS_TRACE_LEVEL_VERBOSE_2,
1503 "AFSLocateNameEntry (FO: %p) Processing @SYS substitution for %wZ Index %08lX\n",
1508 ntStatus = AFSSubstituteSysName( &uniComponentName,
1512 if ( NT_SUCCESS( ntStatus))
1515 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1516 AFS_TRACE_LEVEL_VERBOSE_2,
1517 "AFSLocateNameEntry (FO: %p) Located substitution %wZ for %wZ Index %08lX\n",
1524 // Go reparse the name again
1527 bSubstituteName = TRUE;
1529 ulSubstituteIndex++; // For the next entry, if needed
1531 continue; // while( pDirEntry == NULL)
1536 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1537 AFS_TRACE_LEVEL_ERROR,
1538 "AFSLocateNameEntry (FO: %p) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1544 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1548 // Pass back the directory entries
1551 *OutParentDirectoryCB = pParentDirEntry;
1553 pParentDirEntry = NULL;
1555 *OutDirectoryCB = NULL;
1557 *OutVolumeCB = pCurrentVolume;
1559 *OutVolumeReferenceReason = VolumeReferenceReason;
1561 bReleaseCurrentVolume = FALSE;
1563 if( ComponentName != NULL)
1566 *ComponentName = uniComponentName;
1569 *RootPathName = uniFullPathName;
1573 // We can't possibly have a pDirEntry since the lookup failed
1575 try_return( ntStatus);
1580 // Generate the CRC on the node and perform a case sensitive lookup
1583 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1584 AFS_TRACE_LEVEL_VERBOSE_2,
1585 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case sensitive\n",
1589 ulCRC = AFSGenerateCRC( &uniSearchName,
1592 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1595 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1599 if( pDirEntry == NULL)
1603 // Missed so perform a case insensitive lookup
1606 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1607 AFS_TRACE_LEVEL_VERBOSE_2,
1608 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case insensitive\n",
1612 ulCRC = AFSGenerateCRC( &uniSearchName,
1615 AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1619 if( pDirEntry == NULL)
1623 // OK, if this component is a valid short name then try
1624 // a lookup in the short name tree
1627 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1628 RtlIsNameLegalDOS8Dot3( &uniSearchName,
1633 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1634 AFS_TRACE_LEVEL_VERBOSE_2,
1635 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ short name\n",
1639 AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1644 if ( pDirEntry == NULL &&
1645 pParentDirEntry->ObjectInformation->VolumeCB == AFSGlobalRoot)
1649 // Check with the service to see if this is a valid cell name
1650 // that can be automatically resolved. Drop the shared TreeLock
1651 // since AFSCheckCellName must acquire it exclusively.
1654 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1656 ntStatus = AFSCheckCellName( AuthGroup,
1660 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1664 if( pDirEntry == NULL)
1668 // If we substituted a name then reset our search name and try again
1671 if( bSubstituteName)
1674 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1676 uniSearchName = uniComponentName;
1678 bSubstituteName = FALSE;
1680 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1682 continue; // while( pDirEntry == NULL)
1686 // Node name not found so get out
1689 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1691 if( uniRemainingPath.Length > 0)
1694 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1696 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1697 AFS_TRACE_LEVEL_VERBOSE,
1698 "AFSLocateNameEntry (FO: %p) Returning path not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1701 pCurrentObject->FileId.Cell,
1702 pCurrentObject->FileId.Volume,
1703 pCurrentObject->FileId.Vnode,
1704 pCurrentObject->FileId.Unique);
1709 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1711 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1712 AFS_TRACE_LEVEL_VERBOSE,
1713 "AFSLocateNameEntry (FO: %p) Returning name not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1716 pCurrentObject->FileId.Cell,
1717 pCurrentObject->FileId.Volume,
1718 pCurrentObject->FileId.Vnode,
1719 pCurrentObject->FileId.Unique);
1722 // Pass back the directory entries
1725 *OutParentDirectoryCB = pParentDirEntry;
1727 pParentDirEntry = NULL;
1729 *OutDirectoryCB = NULL;
1731 *OutVolumeCB = pCurrentVolume;
1733 *OutVolumeReferenceReason = VolumeReferenceReason;
1735 bReleaseCurrentVolume = FALSE;
1737 if( ComponentName != NULL)
1740 *ComponentName = uniComponentName;
1743 *RootPathName = uniFullPathName;
1746 try_return( ntStatus);
1753 // Here we have a match on the case insensitive lookup for the name. If there
1754 // Is more than one link entry for this node then fail the lookup request
1757 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1758 pDirEntry->CaseInsensitiveList.fLink != NULL)
1762 // Increment our dir entry ref count since we will decrement it on exit
1765 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1767 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1768 AFS_TRACE_LEVEL_VERBOSE,
1769 "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1770 &pDirEntry->NameInformation.FileName,
1775 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1777 try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1782 if( pDirEntry != NULL)
1786 // If the verify flag is set on the parent and the current entry is deleted
1787 // revalidate the parent and search again.
1790 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1791 BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1794 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1796 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1797 AFS_TRACE_LEVEL_VERBOSE,
1798 "AFSLocateNameEntry (FO: %p) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1800 &pParentDirEntry->NameInformation.FileName,
1801 pParentDirEntry->ObjectInformation->FileId.Cell,
1802 pParentDirEntry->ObjectInformation->FileId.Volume,
1803 pParentDirEntry->ObjectInformation->FileId.Vnode,
1804 pParentDirEntry->ObjectInformation->FileId.Unique);
1807 // Directory TreeLock should be exclusively held
1810 AFSAcquireExcl( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1813 ntStatus = AFSVerifyEntry( AuthGroup,
1816 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1818 if( !NT_SUCCESS( ntStatus))
1821 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1822 AFS_TRACE_LEVEL_ERROR,
1823 "AFSLocateNameEntry (FO: %p) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1825 &pParentDirEntry->NameInformation.FileName,
1826 pParentDirEntry->ObjectInformation->FileId.Cell,
1827 pParentDirEntry->ObjectInformation->FileId.Volume,
1828 pParentDirEntry->ObjectInformation->FileId.Vnode,
1829 pParentDirEntry->ObjectInformation->FileId.Unique,
1832 try_return( ntStatus);
1835 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1836 AFS_TRACE_LEVEL_VERBOSE,
1837 "AFSLocateNameEntry (FO: %p) Reprocessing component %wZ in parent %wZ\n",
1840 &pParentDirEntry->NameInformation.FileName);
1849 // Increment our dir entry ref count
1852 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1854 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1855 AFS_TRACE_LEVEL_VERBOSE,
1856 "AFSLocateNameEntry Increment6 count on %wZ DE %p Ccb %p Cnt %d\n",
1857 &pDirEntry->NameInformation.FileName,
1863 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1865 } // End while( pDirEntry == NULL)
1868 // If we have a dirEntry for this component, perform some basic validation on it
1871 if( pDirEntry != NULL &&
1872 BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1875 pCurrentObject = pDirEntry->ObjectInformation;
1877 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1878 AFS_TRACE_LEVEL_ERROR,
1879 "AFSLocateNameEntry (FO: %p) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1881 &pDirEntry->NameInformation.FileName,
1882 pCurrentObject->FileId.Cell,
1883 pCurrentObject->FileId.Volume,
1884 pCurrentObject->FileId.Vnode,
1885 pCurrentObject->FileId.Unique);
1888 // This entry was deleted through the invalidation call back so perform cleanup
1892 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1895 pParentObjectInfo = AFSFindObjectInfo( pCurrentObject->VolumeCB,
1896 &pCurrentObject->ParentFileId);
1899 ASSERT( pParentObjectInfo != NULL);
1901 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1904 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1907 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1909 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1910 AFS_TRACE_LEVEL_VERBOSE,
1911 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1912 &pDirEntry->NameInformation.FileName,
1917 ASSERT( lCount >= 0);
1922 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1923 AFS_TRACE_LEVEL_VERBOSE,
1924 "AFSLocateNameEntry Deleting dir entry %p (%p) for %wZ\n",
1927 &pDirEntry->NameInformation.FileName);
1930 // Remove and delete the directory entry from the parent list
1933 AFSDeleteDirEntry( pParentObjectInfo,
1936 AFSAcquireShared( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1939 if( pCurrentObject->ObjectReferenceCount <= 0)
1942 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
1945 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1946 AFS_TRACE_LEVEL_VERBOSE,
1947 "AFSLocateNameEntry Removing object %p from volume tree\n",
1950 AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
1951 &pCurrentObject->TreeEntry);
1953 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
1957 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1962 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1963 AFS_TRACE_LEVEL_VERBOSE,
1964 "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
1966 &pDirEntry->NameInformation.FileName);
1968 SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
1970 AFSRemoveNameEntry( pParentObjectInfo,
1974 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1976 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
1978 AFSReleaseObjectInfo( &pParentObjectInfo);
1981 // We deleted the dir entry so check if there is any remaining portion
1982 // of the name to process.
1985 if( uniRemainingPath.Length > 0)
1988 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1990 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1991 AFS_TRACE_LEVEL_VERBOSE,
1992 "AFSLocateNameEntry (FO: %p) Returning path not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1995 pCurrentObject->FileId.Cell,
1996 pCurrentObject->FileId.Volume,
1997 pCurrentObject->FileId.Vnode,
1998 pCurrentObject->FileId.Unique);
2003 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
2005 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2006 AFS_TRACE_LEVEL_VERBOSE,
2007 "AFSLocateNameEntry (FO: %p) Returning name not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2010 pCurrentObject->FileId.Cell,
2011 pCurrentObject->FileId.Volume,
2012 pCurrentObject->FileId.Vnode,
2013 pCurrentObject->FileId.Unique);
2016 // Pass back the directory entries
2019 *OutParentDirectoryCB = pParentDirEntry;
2021 pParentDirEntry = NULL;
2023 *OutDirectoryCB = NULL;
2025 *OutVolumeCB = pCurrentVolume;
2027 *OutVolumeReferenceReason = VolumeReferenceReason;
2029 bReleaseCurrentVolume = FALSE;
2031 if( ComponentName != NULL)
2034 *ComponentName = uniComponentName;
2037 *RootPathName = uniFullPathName;
2041 if( ntStatus != STATUS_SUCCESS)
2044 try_return( ntStatus);
2048 // If we ended up substituting a name in the component then update
2049 // the full path and update the pointers
2052 if( bSubstituteName)
2055 BOOLEAN bRelativeOpen = FALSE;
2057 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2058 AFS_TRACE_LEVEL_VERBOSE_2,
2059 "AFSLocateNameEntry (FO: %p) Substituting %wZ into %wZ Index %08lX\n",
2065 if( FileObject != NULL &&
2066 FileObject->RelatedFileObject != NULL)
2069 bRelativeOpen = TRUE;
2073 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
2074 // and free the prior Buffer contents but only if the fourth
2075 // parameter is TRUE.
2078 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
2083 bAllocatedSymLinkBuffer ||
2086 if( !NT_SUCCESS( ntStatus))
2089 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2090 AFS_TRACE_LEVEL_ERROR,
2091 "AFSLocateNameEntry (FO: %p) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
2098 try_return( ntStatus);
2102 // We have substituted a name into the buffer so if we do this again for this
2103 // path, we need to free up the buffer we allocated.
2106 bSubstitutedName = TRUE;
2110 // Update the search parameters
2113 uniPathName = uniRemainingPath;
2116 // Check if the is a SymLink entry but has no Target FileID or Name. In this
2117 // case it might be a DFS Link so let's go and evaluate it to be sure
2120 if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
2121 ( pCurrentObject->TargetFileId.Vnode == 0 ||
2122 pDirEntry->NameInformation.TargetName.Length == 0))
2125 ntStatus = AFSValidateSymLink( AuthGroup,
2128 if( !NT_SUCCESS( ntStatus))
2131 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2132 AFS_TRACE_LEVEL_ERROR,
2133 "AFSLocateNameEntry (FO: %p) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2135 &pDirEntry->NameInformation.FileName,
2136 pCurrentObject->FileId.Cell,
2137 pCurrentObject->FileId.Volume,
2138 pCurrentObject->FileId.Vnode,
2139 pCurrentObject->FileId.Unique,
2142 try_return( ntStatus);
2147 // Update the name array
2150 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2151 AFS_TRACE_LEVEL_VERBOSE,
2152 "AFSLocateNameEntry (FO: %p) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2154 &pDirEntry->NameInformation.FileName,
2155 pCurrentObject->FileId.Cell,
2156 pCurrentObject->FileId.Volume,
2157 pCurrentObject->FileId.Vnode,
2158 pCurrentObject->FileId.Unique);
2160 ntStatus = AFSInsertNextElement( pNameArray,
2163 if( !NT_SUCCESS( ntStatus))
2166 try_return( ntStatus);
2172 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2173 AFS_TRACE_LEVEL_VERBOSE,
2174 "AFSLocateNameEntry (FO: %p) Completed processing %wZ Status %08lX\n",
2179 if( ( !NT_SUCCESS( ntStatus) &&
2180 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
2181 ntStatus == STATUS_REPARSE)
2183 if( RootPathName->Buffer != uniFullPathName.Buffer)
2186 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
2192 if( *OutParentDirectoryCB != NULL)
2195 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2196 AFS_TRACE_LEVEL_VERBOSE,
2197 "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
2198 &(*OutParentDirectoryCB)->NameInformation.FileName,
2199 *OutParentDirectoryCB,
2201 (*OutParentDirectoryCB)->DirOpenReferenceCount);
2204 if( *OutDirectoryCB != NULL)
2207 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2208 AFS_TRACE_LEVEL_VERBOSE,
2209 "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
2210 &(*OutDirectoryCB)->NameInformation.FileName,
2213 (*OutDirectoryCB)->DirOpenReferenceCount);
2217 if( pDirEntry != NULL)
2220 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
2222 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2223 AFS_TRACE_LEVEL_VERBOSE,
2224 "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
2225 &pDirEntry->NameInformation.FileName,
2230 ASSERT( lCount >= 0);
2233 if( pParentDirEntry != NULL)
2236 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
2238 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2239 AFS_TRACE_LEVEL_VERBOSE,
2240 "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
2241 &pParentDirEntry->NameInformation.FileName,
2246 ASSERT( lCount >= 0);
2249 if( bReleaseCurrentVolume)
2252 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
2254 lCount = AFSVolumeDecrement( pCurrentVolume,
2255 VolumeReferenceReason);
2257 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2258 AFS_TRACE_LEVEL_VERBOSE,
2259 "AFSLocateNameEntry Decrement7 count on volume %p Reason %u Cnt %d\n",
2261 VolumeReferenceReason,
2264 bReleaseCurrentVolume = FALSE;
2267 if( bSubstituteName &&
2268 uniSearchName.Buffer != NULL)
2271 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
2279 AFSCreateDirEntry( IN GUID *AuthGroup,
2280 IN AFSObjectInfoCB *ParentObjectInfo,
2281 IN AFSDirectoryCB *ParentDirCB,
2282 IN PUNICODE_STRING FileName,
2283 IN PUNICODE_STRING ComponentName,
2284 IN ULONG Attributes,
2285 IN OUT AFSDirectoryCB **DirEntry)
2288 UNREFERENCED_PARAMETER(FileName);
2289 NTSTATUS ntStatus = STATUS_SUCCESS;
2290 AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
2291 LARGE_INTEGER liFileSize = {0,0};
2297 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2298 AFS_TRACE_LEVEL_VERBOSE_2,
2299 "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
2300 &ParentDirCB->NameInformation.FileName,
2301 ParentObjectInfo->FileId.Cell,
2302 ParentObjectInfo->FileId.Volume,
2303 ParentObjectInfo->FileId.Vnode,
2304 ParentObjectInfo->FileId.Unique,
2309 // OK, before inserting the node into the parent tree, issue
2310 // the request to the service for node creation
2311 // We will need to drop the lock on the parent node since the create
2312 // could cause a callback into the file system to invalidate it's cache
2315 ntStatus = AFSNotifyFileCreate( AuthGroup,
2323 // If the returned status is STATUS_REPARSE then the entry exists
2324 // and we raced, get out.
2326 if( ntStatus == STATUS_REPARSE)
2329 *DirEntry = pDirNode;
2331 try_return( ntStatus = STATUS_SUCCESS);
2334 if( !NT_SUCCESS( ntStatus))
2337 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2338 AFS_TRACE_LEVEL_ERROR,
2339 "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
2340 &ParentDirCB->NameInformation.FileName,
2341 ParentObjectInfo->FileId.Cell,
2342 ParentObjectInfo->FileId.Volume,
2343 ParentObjectInfo->FileId.Vnode,
2344 ParentObjectInfo->FileId.Unique,
2349 try_return( ntStatus);
2353 // If AFSNotifyFileCreate returns pDirNode != NULL, then its
2354 // DirOpenReferenceCount is held.
2357 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2361 // Before attempting to insert the new entry, check if we need to validate the parent
2364 if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2367 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2368 AFS_TRACE_LEVEL_VERBOSE,
2369 "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2370 &ParentDirCB->NameInformation.FileName,
2371 ParentObjectInfo->FileId.Cell,
2372 ParentObjectInfo->FileId.Volume,
2373 ParentObjectInfo->FileId.Vnode,
2374 ParentObjectInfo->FileId.Unique);
2376 ntStatus = AFSVerifyEntry( AuthGroup,
2379 if( !NT_SUCCESS( ntStatus))
2382 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2383 AFS_TRACE_LEVEL_ERROR,
2384 "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2385 &ParentDirCB->NameInformation.FileName,
2386 ParentObjectInfo->FileId.Cell,
2387 ParentObjectInfo->FileId.Volume,
2388 ParentObjectInfo->FileId.Vnode,
2389 ParentObjectInfo->FileId.Unique,
2392 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2394 try_return( ntStatus);
2399 // Check for the entry in the event we raced with some other thread
2402 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2403 (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2406 if( pExistingDirNode != NULL)
2408 if (AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2409 &pExistingDirNode->ObjectInformation->FileId))
2412 if ( pExistingDirNode != pDirNode)
2415 lCount = InterlockedDecrement( &pDirNode->DirOpenReferenceCount);
2417 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2418 AFS_TRACE_LEVEL_VERBOSE,
2419 "AFSCreateDirEntry Decrement count on %wZ DE %p Cnt %d\n",
2420 &pDirNode->NameInformation.FileName,
2424 AFSDeleteDirEntry( ParentObjectInfo,
2427 lCount = InterlockedIncrement( &pExistingDirNode->DirOpenReferenceCount);
2429 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2430 AFS_TRACE_LEVEL_VERBOSE,
2431 "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2432 &pExistingDirNode->NameInformation.FileName,
2436 *DirEntry = pExistingDirNode;
2439 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2441 try_return( ntStatus = STATUS_SUCCESS);
2447 // Need to tear down this entry and rebuild it below
2450 if( pExistingDirNode->DirOpenReferenceCount <= 0)
2453 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2454 AFS_TRACE_LEVEL_VERBOSE,
2455 "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2457 &pExistingDirNode->NameInformation.FileName,
2458 pExistingDirNode->ObjectInformation->FileId.Cell,
2459 pExistingDirNode->ObjectInformation->FileId.Volume,
2460 pExistingDirNode->ObjectInformation->FileId.Vnode,
2461 pExistingDirNode->ObjectInformation->FileId.Unique,
2462 pDirNode->ObjectInformation->FileId.Cell,
2463 pDirNode->ObjectInformation->FileId.Volume,
2464 pDirNode->ObjectInformation->FileId.Vnode,
2465 pDirNode->ObjectInformation->FileId.Unique);
2467 AFSDeleteDirEntry( ParentObjectInfo,
2473 SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2475 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2476 AFS_TRACE_LEVEL_VERBOSE,
2477 "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2479 &pExistingDirNode->NameInformation.FileName,
2480 pExistingDirNode->ObjectInformation->FileId.Cell,
2481 pExistingDirNode->ObjectInformation->FileId.Volume,
2482 pExistingDirNode->ObjectInformation->FileId.Vnode,
2483 pExistingDirNode->ObjectInformation->FileId.Unique,
2484 pDirNode->ObjectInformation->FileId.Cell,
2485 pDirNode->ObjectInformation->FileId.Volume,
2486 pDirNode->ObjectInformation->FileId.Vnode,
2487 pDirNode->ObjectInformation->FileId.Unique);
2489 AFSRemoveNameEntry( ParentObjectInfo,
2495 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2496 AFS_TRACE_LEVEL_VERBOSE_2,
2497 "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2498 &ParentDirCB->NameInformation.FileName,
2499 ParentObjectInfo->FileId.Cell,
2500 ParentObjectInfo->FileId.Volume,
2501 ParentObjectInfo->FileId.Vnode,
2502 ParentObjectInfo->FileId.Unique,
2506 // Insert the directory node
2509 AFSInsertDirectoryNode( ParentObjectInfo,
2514 // Pass back the dir entry
2517 *DirEntry = pDirNode;
2519 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2530 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2531 IN AFSDirectoryCB *DirEntry,
2532 IN BOOLEAN InsertInEnumList)
2540 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2543 // Insert the node into the directory node tree
2546 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2547 AFS_TRACE_LEVEL_VERBOSE,
2548 "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2550 &DirEntry->NameInformation.FileName);
2552 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2554 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2557 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2559 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2560 AFS_TRACE_LEVEL_VERBOSE,
2561 "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2563 &DirEntry->NameInformation.FileName);
2568 AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2571 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2572 AFS_TRACE_LEVEL_VERBOSE,
2573 "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2575 &DirEntry->NameInformation.FileName);
2578 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2581 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2583 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2585 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2586 AFS_TRACE_LEVEL_VERBOSE,
2587 "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2589 &DirEntry->NameInformation.FileName);
2594 AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2597 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2598 AFS_TRACE_LEVEL_VERBOSE,
2599 "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2601 &DirEntry->NameInformation.FileName);
2605 // Into the shortname tree
2608 if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2611 if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2614 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2616 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2617 AFS_TRACE_LEVEL_VERBOSE,
2618 "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2620 &DirEntry->NameInformation.FileName);
2622 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2627 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2630 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2631 AFS_TRACE_LEVEL_VERBOSE,
2632 "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2634 &DirEntry->NameInformation.FileName);
2638 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2640 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2641 AFS_TRACE_LEVEL_VERBOSE,
2642 "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2644 &DirEntry->NameInformation.FileName);
2649 if( InsertInEnumList)
2653 // And insert the node into the directory list
2656 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2657 AFS_TRACE_LEVEL_VERBOSE,
2658 "AFSInsertDirectoryNode Inserting entry %p %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2660 &DirEntry->NameInformation.FileName,
2661 DirEntry->ObjectInformation->FileId.Cell,
2662 DirEntry->ObjectInformation->FileId.Volume,
2663 DirEntry->ObjectInformation->FileId.Vnode,
2664 DirEntry->ObjectInformation->FileId.Unique);
2666 if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2669 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2674 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2676 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2679 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2681 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2683 lCount = InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2685 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2686 AFS_TRACE_LEVEL_VERBOSE,
2687 "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2688 &DirEntry->NameInformation.FileName,
2690 ParentObjectInfo->FileId.Cell,
2691 ParentObjectInfo->FileId.Volume,
2692 ParentObjectInfo->FileId.Vnode,
2693 ParentObjectInfo->FileId.Unique);
2701 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2702 IN AFSDirectoryCB *DirEntry)
2710 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2711 AFS_TRACE_LEVEL_VERBOSE,
2712 "AFSDeleteDirEntry Deleting dir entry in parent %p Entry %p %wZ FID %08lX-%08lX-%08lX-%08lX RefCount %d\n",
2715 &DirEntry->NameInformation.FileName,
2716 DirEntry->ObjectInformation->FileId.Cell,
2717 DirEntry->ObjectInformation->FileId.Volume,
2718 DirEntry->ObjectInformation->FileId.Vnode,
2719 DirEntry->ObjectInformation->FileId.Unique,
2720 DirEntry->DirOpenReferenceCount);
2722 ASSERT( DirEntry->DirOpenReferenceCount == 0);
2724 AFSRemoveDirNodeFromParent( ParentObjectInfo,
2729 // Free up the name buffer if it was reallocated
2732 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2735 AFSExFreePoolWithTag( DirEntry->NameInformation.FileName.Buffer, 0);
2738 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2741 AFSExFreePoolWithTag( DirEntry->NameInformation.TargetName.Buffer, 0);
2745 // Dereference the object for this dir entry
2748 lCount = AFSObjectInfoDecrement( DirEntry->ObjectInformation,
2749 AFS_OBJECT_REFERENCE_DIRENTRY);
2751 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2752 AFS_TRACE_LEVEL_VERBOSE,
2753 "AFSDeleteDirEntry Decrement count on object %p Cnt %d\n",
2754 DirEntry->ObjectInformation,
2757 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
2758 DirEntry->ObjectInformation->Links == 0)
2761 SetFlag( DirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2764 ExDeleteResourceLite( &DirEntry->NonPaged->Lock);
2766 AFSExFreePoolWithTag( DirEntry->NonPaged, AFS_DIR_ENTRY_NP_TAG);
2769 // Free up the dir entry
2772 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
2773 AFS_TRACE_LEVEL_VERBOSE,
2774 "AFSDeleteDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
2777 AFSExFreePoolWithTag( DirEntry, AFS_DIR_ENTRY_TAG);
2782 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2783 IN AFSDirectoryCB *DirEntry,
2784 IN BOOLEAN RemoveFromEnumList)
2787 NTSTATUS ntStatus = STATUS_SUCCESS;
2794 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2796 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2797 AFS_TRACE_LEVEL_VERBOSE,
2798 "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %p\n",
2800 &DirEntry->NameInformation.FileName,
2801 DirEntry->ObjectInformation->FileId.Cell,
2802 DirEntry->ObjectInformation->FileId.Volume,
2803 DirEntry->ObjectInformation->FileId.Vnode,
2804 DirEntry->ObjectInformation->FileId.Unique,
2807 if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2810 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2811 AFS_TRACE_LEVEL_VERBOSE,
2812 "AFSRemoveDirNodeFromParent Removing DirEntry %p name %wZ\n",
2814 &DirEntry->NameInformation.FileName);
2816 AFSRemoveNameEntry( ParentObjectInfo,
2822 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2823 AFS_TRACE_LEVEL_VERBOSE,
2824 "AFSRemoveDirNodeFromParent DE %p for %wZ NOT removing entry due to flag set\n",
2826 &DirEntry->NameInformation.FileName);
2830 if( RemoveFromEnumList &&
2831 BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST))
2835 // And remove the entry from the enumeration list
2838 if( DirEntry->ListEntry.fLink == NULL)
2841 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = (AFSDirectoryCB *)DirEntry->ListEntry.bLink;
2846 ((AFSDirectoryCB *)DirEntry->ListEntry.fLink)->ListEntry.bLink = DirEntry->ListEntry.bLink;
2849 if( DirEntry->ListEntry.bLink == NULL)
2852 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = (AFSDirectoryCB *)DirEntry->ListEntry.fLink;
2857 ((AFSDirectoryCB *)DirEntry->ListEntry.bLink)->ListEntry.fLink = DirEntry->ListEntry.fLink;
2860 ASSERT( ParentObjectInfo->Specific.Directory.DirectoryNodeCount > 0);
2862 lCount = InterlockedDecrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2864 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2866 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2867 AFS_TRACE_LEVEL_VERBOSE,
2868 "AFSRemoveDirNodeFromParent Removing entry %wZ Dec Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2869 &DirEntry->NameInformation.FileName,
2871 ParentObjectInfo->FileId.Cell,
2872 ParentObjectInfo->FileId.Volume,
2873 ParentObjectInfo->FileId.Vnode,
2874 ParentObjectInfo->FileId.Unique);
2876 DirEntry->ListEntry.fLink = NULL;
2877 DirEntry->ListEntry.bLink = NULL;
2885 AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
2886 IN OUT PUNICODE_STRING TargetFileName)
2889 NTSTATUS ntStatus = STATUS_SUCCESS;
2890 UNICODE_STRING uniFileName;
2896 // We will process backwards from the end of the name looking
2897 // for the first \ we encounter
2900 uniFileName.Length = FileName->Length;
2901 uniFileName.MaximumLength = FileName->MaximumLength;
2903 uniFileName.Buffer = FileName->Buffer;
2908 if( uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
2912 // Subtract one more character off of the filename if it is not the root
2915 if( uniFileName.Length > sizeof( WCHAR))
2918 uniFileName.Length -= sizeof( WCHAR);
2922 // Now build up the target name
2925 TargetFileName->Length = FileName->Length - uniFileName.Length;
2928 // If we are not on the root then fixup the name
2931 if( uniFileName.Length > sizeof( WCHAR))
2934 TargetFileName->Length -= sizeof( WCHAR);
2936 TargetFileName->Buffer = &uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) + 1];
2941 TargetFileName->Buffer = &uniFileName.Buffer[ uniFileName.Length/sizeof( WCHAR)];
2945 // Fixup the passed back filename length
2948 FileName->Length = uniFileName.Length;
2950 TargetFileName->MaximumLength = TargetFileName->Length;
2955 uniFileName.Length -= sizeof( WCHAR);
2963 AFSParseName( IN PIRP Irp,
2965 OUT PUNICODE_STRING FileName,
2966 OUT PUNICODE_STRING ParsedFileName,
2967 OUT PUNICODE_STRING RootFileName,
2968 OUT ULONG *ParseFlags,
2969 OUT AFSVolumeCB **VolumeCB,
2970 OUT AFSDirectoryCB **ParentDirectoryCB,
2971 OUT AFSNameArrayHdr **NameArray)
2974 NTSTATUS ntStatus = STATUS_SUCCESS;
2975 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2976 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2977 UNICODE_STRING uniFullName, uniComponentName, uniRemainingPath;
2979 AFSDirectoryCB *pDirEntry = NULL;
2980 USHORT usIndex = 0, usDriveIndex = 0;
2981 AFSCcb *pRelatedCcb = NULL;
2982 AFSNameArrayHdr *pNameArray = NULL, *pRelatedNameArray = NULL;
2983 USHORT usComponentIndex = 0;
2984 USHORT usComponentLength = 0;
2985 AFSVolumeCB *pVolumeCB = NULL;
2986 AFSFcb *pRelatedFcb = NULL;
2987 BOOLEAN bReleaseTreeLock = FALSE;
2988 BOOLEAN bIsAllShare = FALSE;
2995 // Indicate we are opening a root ...
2998 *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
3000 *ParentDirectoryCB = NULL;
3002 if( pIrpSp->FileObject->RelatedFileObject != NULL)
3005 pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
3007 pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
3009 pRelatedNameArray = pRelatedCcb->NameArray;
3011 uniFullName = pIrpSp->FileObject->FileName;
3013 ASSERT( pRelatedFcb != NULL);
3016 // No wild cards in the name
3019 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3020 AFS_TRACE_LEVEL_VERBOSE_2,
3021 "AFSParseName (%p) Relative open for %wZ FID %08lX-%08lX-%08lX-%08lX component %wZ\n",
3023 &pRelatedCcb->DirectoryCB->NameInformation.FileName,
3024 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Cell,
3025 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Volume,
3026 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
3027 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Unique,
3030 if( FsRtlDoesNameContainWildCards( &uniFullName))
3033 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3034 AFS_TRACE_LEVEL_ERROR,
3035 "AFSParseName (%p) Component %wZ contains wild cards\n",
3039 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3042 pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
3044 pDirEntry = pRelatedCcb->DirectoryCB;
3046 *FileName = pIrpSp->FileObject->FileName;
3049 // Grab the root node while checking state
3052 AFSAcquireShared( pVolumeCB->VolumeLock,
3055 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3056 BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3060 // The volume has been taken off line so fail the access
3063 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3064 AFS_TRACE_LEVEL_ERROR,
3065 "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3067 pVolumeCB->ObjectInformation.FileId.Cell,
3068 pVolumeCB->ObjectInformation.FileId.Volume);
3070 AFSReleaseResource( pVolumeCB->VolumeLock);
3072 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3075 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3078 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3079 AFS_TRACE_LEVEL_VERBOSE,
3080 "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
3082 pVolumeCB->ObjectInformation.FileId.Cell,
3083 pVolumeCB->ObjectInformation.FileId.Volume);
3085 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3088 if( !NT_SUCCESS( ntStatus))
3091 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3092 AFS_TRACE_LEVEL_ERROR,
3093 "AFSParseName (%p) Failed verification of root Status %08lX\n",
3097 AFSReleaseResource( pVolumeCB->VolumeLock);
3099 try_return( ntStatus);
3103 AFSReleaseResource( pVolumeCB->VolumeLock);
3105 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
3108 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3109 AFS_TRACE_LEVEL_VERBOSE,
3110 "AFSParseName (%p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3112 &pDirEntry->NameInformation.FileName,
3113 pDirEntry->ObjectInformation->FileId.Cell,
3114 pDirEntry->ObjectInformation->FileId.Volume,
3115 pDirEntry->ObjectInformation->FileId.Vnode,
3116 pDirEntry->ObjectInformation->FileId.Unique);
3119 // Directory TreeLock should be exclusively held
3122 AFSAcquireExcl( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
3125 ntStatus = AFSVerifyEntry( AuthGroup,
3128 AFSReleaseResource( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
3130 if( !NT_SUCCESS( ntStatus))
3133 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3134 AFS_TRACE_LEVEL_VERBOSE,
3135 "AFSParseName (%p) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3137 &pDirEntry->NameInformation.FileName,
3138 pDirEntry->ObjectInformation->FileId.Cell,
3139 pDirEntry->ObjectInformation->FileId.Volume,
3140 pDirEntry->ObjectInformation->FileId.Vnode,
3141 pDirEntry->ObjectInformation->FileId.Unique,
3144 try_return( ntStatus);
3149 // Create our full path name buffer
3152 uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length +
3154 pIrpSp->FileObject->FileName.Length +
3157 uniFullName.Length = 0;
3159 uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
3160 uniFullName.MaximumLength,
3161 AFS_NAME_BUFFER_THREE_TAG);
3163 if( uniFullName.Buffer == NULL)
3166 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3167 AFS_TRACE_LEVEL_ERROR,
3168 "AFSParseName (%p) Failed to allocate full name buffer\n",
3171 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3174 RtlZeroMemory( uniFullName.Buffer,
3175 uniFullName.MaximumLength);
3177 RtlCopyMemory( uniFullName.Buffer,
3178 pRelatedCcb->FullFileName.Buffer,
3179 pRelatedCcb->FullFileName.Length);
3181 uniFullName.Length = pRelatedCcb->FullFileName.Length;
3183 usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
3185 usComponentLength = pIrpSp->FileObject->FileName.Length;
3187 if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
3188 pIrpSp->FileObject->FileName.Length > 0 &&
3189 pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
3190 pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
3193 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
3195 uniFullName.Length += sizeof( WCHAR);
3197 usComponentLength += sizeof( WCHAR);
3200 if( pIrpSp->FileObject->FileName.Length > 0)
3203 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
3204 pIrpSp->FileObject->FileName.Buffer,
3205 pIrpSp->FileObject->FileName.Length);
3207 uniFullName.Length += pIrpSp->FileObject->FileName.Length;
3210 *RootFileName = uniFullName;
3213 // We populate up to the current parent
3216 if( pRelatedNameArray == NULL)
3220 // Init and populate our name array
3223 pNameArray = AFSInitNameArray( NULL,
3226 if( pNameArray == NULL)
3229 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3230 AFS_TRACE_LEVEL_VERBOSE,
3231 "AFSParseName (%p) Failed to initialize name array\n",
3234 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3236 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3239 ntStatus = AFSPopulateNameArray( pNameArray,
3241 pRelatedCcb->DirectoryCB);
3247 // Init and populate our name array
3250 pNameArray = AFSInitNameArray( NULL,
3251 pRelatedNameArray->MaxElementCount);
3253 if( pNameArray == NULL)
3256 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3257 AFS_TRACE_LEVEL_VERBOSE,
3258 "AFSParseName (%p) Failed to initialize name array\n",
3261 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3263 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3266 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
3268 pRelatedCcb->DirectoryCB);
3271 if( !NT_SUCCESS( ntStatus))
3274 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3275 AFS_TRACE_LEVEL_VERBOSE,
3276 "AFSParseName (%p) Failed to populate name array\n",
3279 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3281 try_return( ntStatus);
3284 ParsedFileName->Length = usComponentLength;
3285 ParsedFileName->MaximumLength = uniFullName.MaximumLength;
3287 ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
3290 // Indicate to caller that RootFileName must be freed
3293 SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
3295 *NameArray = pNameArray;
3298 // Increment our volume reference count
3301 lCount = AFSVolumeIncrement( pVolumeCB,
3302 AFS_VOLUME_REFERENCE_PARSE_NAME);
3304 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3305 AFS_TRACE_LEVEL_VERBOSE,
3306 "AFSParseName Increment count on volume %p Cnt %d\n",
3310 *VolumeCB = pVolumeCB;
3312 *ParentDirectoryCB = pDirEntry;
3314 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3315 AFS_TRACE_LEVEL_VERBOSE_2,
3316 "AFSParseName (%p) Returning full name %wZ\n",
3320 try_return( ntStatus);
3324 // No wild cards in the name
3327 uniFullName = pIrpSp->FileObject->FileName;
3329 if( FsRtlDoesNameContainWildCards( &uniFullName) ||
3330 uniFullName.Length < AFSServerName.Length)
3333 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3334 AFS_TRACE_LEVEL_ERROR,
3335 "AFSParseName (%p) Name %wZ contains wild cards or too short\n",
3339 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3343 // The name is a fully qualified name. Parse out the server/share names and
3344 // point to the root qualified name
3345 // First thing is to locate the server name
3348 FsRtlDissectName( uniFullName,
3352 uniFullName = uniRemainingPath;
3355 // This component is the server name we are serving
3358 if( RtlCompareUnicodeString( &uniComponentName,
3364 // Drive letter based name?
3367 uniFullName = pIrpSp->FileObject->FileName;
3369 while( usIndex < uniFullName.Length/sizeof( WCHAR))
3372 if( uniFullName.Buffer[ usIndex] == L':')
3375 uniFullName.Buffer = &uniFullName.Buffer[ usIndex + 2];
3377 uniFullName.Length -= (usIndex + 2) * sizeof( WCHAR);
3379 usDriveIndex = usIndex - 1;
3388 // Do we have the right server name now?
3391 FsRtlDissectName( uniFullName,
3395 uniFullName = uniRemainingPath;
3398 // This component is the server name we are serving
3401 if( RtlCompareUnicodeString( &uniComponentName,
3406 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3407 AFS_TRACE_LEVEL_ERROR,
3408 "AFSParseName (%p) Name %wZ does not have server name\n",
3410 &pIrpSp->FileObject->FileName);
3412 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3416 // Validate this drive letter is actively mapped
3419 if( usDriveIndex > 0 &&
3420 !AFSIsDriveMapped( pIrpSp->FileObject->FileName.Buffer[ usDriveIndex]))
3423 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3424 AFS_TRACE_LEVEL_ERROR,
3425 "AFSParseName (%p) Name %wZ contains invalid drive mapping\n",
3427 &pIrpSp->FileObject->FileName);
3429 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3433 if( FsRtlDoesNameContainWildCards( &uniFullName))
3436 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3437 AFS_TRACE_LEVEL_ERROR,
3438 "AFSParseName (%p) Component %wZ contains wild cards\n",
3442 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3445 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3446 AFS_TRACE_LEVEL_VERBOSE_2,
3447 "AFSParseName (%p) Processing full name %wZ\n",
3451 if( uniFullName.Length > 0 &&
3452 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] == L'\\')
3455 uniFullName.Length -= sizeof( WCHAR);
3459 // Be sure we are online and ready to go
3462 AFSAcquireShared( AFSGlobalRoot->VolumeLock,
3465 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3466 BooleanFlagOn( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3470 // The volume has been taken off line so fail the access
3473 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3474 AFS_TRACE_LEVEL_ERROR,
3475 "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3477 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3478 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3480 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3482 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3485 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3488 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3489 AFS_TRACE_LEVEL_VERBOSE,
3490 "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
3492 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3493 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3495 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3498 if( !NT_SUCCESS( ntStatus))
3501 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3502 AFS_TRACE_LEVEL_ERROR,
3503 "AFSParseName (%p) Failed verification of root Status %08lX\n",
3507 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3509 try_return( ntStatus);
3513 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3515 if( !BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3518 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3519 AFS_TRACE_LEVEL_VERBOSE,
3520 "AFSParseName (%p) Enumerating global root of volume %08lX:%08lX\n",
3522 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3523 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3525 ntStatus = AFSEnumerateGlobalRoot( AuthGroup);
3527 if( !NT_SUCCESS( ntStatus))
3530 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3531 AFS_TRACE_LEVEL_ERROR,
3532 "AFSParseName (%p) Failed enumeraiton of root Status %08lX\n",
3536 try_return( ntStatus);
3541 // Check for the \\Server access and return it as though it were \\Server\Globalroot
3544 if( uniRemainingPath.Buffer == NULL ||
3545 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3546 uniRemainingPath.Buffer[ 0] == L'\\'))
3549 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3550 AFS_TRACE_LEVEL_VERBOSE_2,
3551 "AFSParseName (%p) Returning global root access\n",
3554 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3556 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3557 AFS_TRACE_LEVEL_VERBOSE,
3558 "AFSParseName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3559 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3560 AFSGlobalRoot->DirectoryCB,
3566 FileName->Length = 0;
3567 FileName->MaximumLength = 0;
3568 FileName->Buffer = NULL;
3570 try_return( ntStatus = STATUS_SUCCESS);
3573 *RootFileName = uniFullName;
3576 // Include the starting \ in the root name
3579 if( RootFileName->Buffer[ 0] != L'\\')
3581 RootFileName->Buffer--;
3582 RootFileName->Length += sizeof( WCHAR);
3583 RootFileName->MaximumLength += sizeof( WCHAR);
3587 // Get the 'share' name
3590 FsRtlDissectName( uniFullName,
3594 if( FsRtlDoesNameContainWildCards( &uniFullName))
3597 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3598 AFS_TRACE_LEVEL_ERROR,
3599 "AFSParseName (%p) Component %wZ contains wild cards\n",
3603 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3607 // If this is the ALL access then perform some additional processing
3610 if( uniComponentName.Length == 0 ||
3611 RtlCompareUnicodeString( &uniComponentName,
3619 // If there is nothing else then get out
3622 if( uniRemainingPath.Buffer == NULL ||
3623 uniRemainingPath.Length == 0 ||
3624 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3625 uniRemainingPath.Buffer[ 0] == L'\\'))
3628 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3629 AFS_TRACE_LEVEL_VERBOSE_2,
3630 "AFSParseName (%p) Returning global root access\n",
3633 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3635 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3636 AFS_TRACE_LEVEL_VERBOSE,
3637 "AFSParseName Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
3638 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3639 AFSGlobalRoot->DirectoryCB,
3645 FileName->Length = 0;
3646 FileName->MaximumLength = 0;
3647 FileName->Buffer = NULL;
3649 try_return( ntStatus = STATUS_SUCCESS);
3653 // Process the name again to strip off the ALL portion
3656 uniFullName = uniRemainingPath;
3658 FsRtlDissectName( uniFullName,
3663 // Check for the PIOCtl name
3666 if( RtlCompareUnicodeString( &uniComponentName,
3671 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3672 AFS_TRACE_LEVEL_VERBOSE_2,
3673 "AFSParseName (%p) Returning root PIOCtl access\n",
3676 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3678 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3679 AFS_TRACE_LEVEL_VERBOSE,
3680 "AFSParseName Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
3681 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3682 AFSGlobalRoot->DirectoryCB,
3686 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3690 *FileName = AFSPIOCtlName;
3692 try_return( ntStatus = STATUS_SUCCESS);
3695 else if( (pDirEntry = AFSGetSpecialShareNameEntry( &uniComponentName,
3696 &uniRemainingPath)) != NULL)
3699 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3700 AFS_TRACE_LEVEL_VERBOSE_2,
3701 "AFSParseName (%p) Returning root share name %wZ access\n",
3706 // Add in the full share name to pass back
3709 if( uniRemainingPath.Buffer != NULL)
3713 // This routine strips off the leading slash so add it back in
3716 uniRemainingPath.Buffer--;
3717 uniRemainingPath.Length += sizeof( WCHAR);
3718 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3721 // And the cell name
3724 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3725 uniRemainingPath.Length += uniComponentName.Length;
3726 uniRemainingPath.MaximumLength += uniComponentName.Length;
3728 uniComponentName = uniRemainingPath;
3733 *FileName = uniComponentName;
3735 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3737 *ParentDirectoryCB = pDirEntry;
3739 try_return( ntStatus = STATUS_SUCCESS);
3743 // Determine the 'share' we are accessing
3746 ulCRC = AFSGenerateCRC( &uniComponentName,
3749 AFSAcquireShared( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3752 bReleaseTreeLock = TRUE;
3754 AFSLocateCaseSensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
3758 if( pDirEntry == NULL)
3761 ulCRC = AFSGenerateCRC( &uniComponentName,
3764 AFSLocateCaseInsensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
3768 if( pDirEntry == NULL)
3772 // OK, if this component is a valid short name then try
3773 // a lookup in the short name tree
3776 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3777 RtlIsNameLegalDOS8Dot3( &uniComponentName,
3782 AFSLocateShortNameDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.ShortNameTree,
3787 if( pDirEntry == NULL)
3791 // Check with the service whether it is a valid cell name
3794 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3796 bReleaseTreeLock = FALSE;
3798 ntStatus = AFSCheckCellName( AuthGroup,
3802 if( !NT_SUCCESS( ntStatus))
3806 uniRemainingPath.Length == 0 &&
3807 ntStatus == STATUS_OBJECT_PATH_NOT_FOUND)
3810 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3811 AFS_TRACE_LEVEL_VERBOSE,
3812 "AFSParseName (%p) AFSCheckCellName %wZ returned path not found; ntStatus %08X\n",
3815 STATUS_OBJECT_NAME_NOT_FOUND);
3817 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
3820 try_return( ntStatus);
3826 if( bReleaseTreeLock)
3828 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3833 // Be sure we are starting from the correct volume
3836 if( pDirEntry->ObjectInformation->VolumeCB != AFSGlobalRoot)
3840 // We dropped the global root in the CheckCellName routine which is the
3841 // only way we can be here
3844 pVolumeCB = pDirEntry->ObjectInformation->VolumeCB;
3847 // Init our name array
3850 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
3853 if( pNameArray == NULL)
3856 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3857 AFS_TRACE_LEVEL_VERBOSE,
3858 "AFSParseName (%p) Failed to initialize name array\n",
3861 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3864 ntStatus = AFSInsertNextElement( pNameArray,
3865 pVolumeCB->DirectoryCB);
3870 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3871 AFS_TRACE_LEVEL_VERBOSE,
3872 "AFSParseName (%p) Failed to insert name array element\n",
3875 try_return( ntStatus);
3879 // In this case don't add back in the 'share' name since that is where we are
3880 // starting. Just put the leading slash back in
3883 if( uniRemainingPath.Buffer != NULL)
3886 uniRemainingPath.Buffer--;
3887 uniRemainingPath.Length += sizeof( WCHAR);
3888 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3890 if( uniRemainingPath.Length > sizeof( WCHAR))
3893 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3897 // Pass back the parent being the root of the volume
3900 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3906 // Pass back a root slash
3909 uniRemainingPath = uniComponentName;
3911 uniRemainingPath.Buffer--;
3912 uniRemainingPath.Length = sizeof( WCHAR);
3913 uniRemainingPath.MaximumLength = sizeof( WCHAR);
3916 // This is a root open so pass back no parent
3923 pVolumeCB = AFSGlobalRoot;
3926 // Init our name array
3929 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
3931 if( pNameArray == NULL)
3934 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3935 AFS_TRACE_LEVEL_VERBOSE,
3936 "AFSParseName (%p) Failed to initialize name array\n",
3939 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3943 // Add back in the 'share' portion of the name since we will parse it out on return
3946 if( uniRemainingPath.Buffer != NULL)
3950 // This routine strips off the leading slash so add it back in
3953 uniRemainingPath.Buffer--;
3954 uniRemainingPath.Length += sizeof( WCHAR);
3955 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3957 if( uniRemainingPath.Length > sizeof( WCHAR))
3960 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3964 // And the cell name
3967 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3968 uniRemainingPath.Length += uniComponentName.Length;
3969 uniRemainingPath.MaximumLength += uniComponentName.Length;
3974 uniRemainingPath = uniComponentName;
3978 // And the leading slash again ...
3981 uniRemainingPath.Buffer--;
3982 uniRemainingPath.Length += sizeof( WCHAR);
3983 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3986 // Pass back the parent being the volume root
3989 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3993 // Return the remaining portion as the file name
3996 *FileName = uniRemainingPath;
3998 *ParsedFileName = uniRemainingPath;
4000 *NameArray = pNameArray;
4002 *VolumeCB = pVolumeCB;
4005 // Increment our reference on the volume
4008 lCount = AFSVolumeIncrement( pVolumeCB,
4009 AFS_VOLUME_REFERENCE_PARSE_NAME);
4011 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4012 AFS_TRACE_LEVEL_VERBOSE,
4013 "AFSParseName Increment2 count on global volume %p Cnt %d\n",
4019 if( NT_SUCCESS( ntStatus))
4022 if( *ParentDirectoryCB != NULL)
4025 lCount = InterlockedIncrement( &(*ParentDirectoryCB)->DirOpenReferenceCount);
4027 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4028 AFS_TRACE_LEVEL_VERBOSE,
4029 "AFSParseName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4030 &(*ParentDirectoryCB)->NameInformation.FileName,
4031 (*ParentDirectoryCB),
4037 if( *VolumeCB != NULL)
4039 ASSERT( (*VolumeCB)->VolumeReferenceCount > 0);
4042 if( ntStatus != STATUS_SUCCESS)
4045 if( pNameArray != NULL)
4048 AFSFreeNameArray( pNameArray);
4057 AFSCheckCellName( IN GUID *AuthGroup,
4058 IN UNICODE_STRING *CellName,
4059 OUT AFSDirectoryCB **ShareDirEntry)
4062 NTSTATUS ntStatus = STATUS_SUCCESS;
4063 UNICODE_STRING uniName;
4064 AFSDirEnumEntry *pDirEnumEntry = NULL;
4065 AFSDirHdr *pDirHdr = &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr;
4066 AFSDirectoryCB *pDirNode = NULL;
4067 UNICODE_STRING uniDirName, uniTargetName;
4068 AFSVolumeCB *pVolumeCB = NULL;
4075 // Look for some default names we will not handle
4078 RtlInitUnicodeString( &uniName,
4081 if( RtlCompareUnicodeString( &uniName,
4086 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4089 RtlInitUnicodeString( &uniName,
4092 if( RtlCompareUnicodeString( &uniName,
4097 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4100 RtlInitUnicodeString( &uniName,
4103 if( RtlCompareUnicodeString( &uniName,
4108 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4111 RtlInitUnicodeString( &uniName,
4114 if( RtlCompareUnicodeString( &uniName,
4119 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4123 // OK, ask the CM about this component name
4126 ntStatus = AFSEvaluateTargetByName( AuthGroup,
4127 &AFSGlobalRoot->ObjectInformation,
4132 if( !NT_SUCCESS( ntStatus))
4135 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4136 AFS_TRACE_LEVEL_WARNING,
4137 "AFSCheckCellName entry %wZ does not exist parent FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4139 AFSGlobalRoot->ObjectInformation.FileId.Cell,
4140 AFSGlobalRoot->ObjectInformation.FileId.Volume,
4141 AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4142 AFSGlobalRoot->ObjectInformation.FileId.Unique,
4145 try_return( ntStatus);
4149 // OK, we have a dir enum entry back so add it to the root node
4152 uniDirName = *CellName;
4154 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
4155 uniTargetName.MaximumLength = uniTargetName.Length;
4156 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
4159 // Is this entry a root volume entry?
4162 if( pDirEnumEntry->FileId.Cell != AFSGlobalRoot->ObjectInformation.FileId.Cell ||
4163 pDirEnumEntry->FileId.Volume != AFSGlobalRoot->ObjectInformation.FileId.Volume)
4167 // Build the root volume entry
4170 ntStatus = AFSBuildRootVolume( AuthGroup,
4171 &pDirEnumEntry->FileId,
4175 // On success returns with a volume reference count held
4178 if( !NT_SUCCESS( ntStatus))
4180 try_return( ntStatus);
4183 *ShareDirEntry = pVolumeCB->DirectoryCB;
4185 lCount = InterlockedIncrement( &pVolumeCB->DirectoryCB->DirOpenReferenceCount);
4187 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4188 AFS_TRACE_LEVEL_VERBOSE,
4189 "AFSCheckCellName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4190 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4191 pVolumeCB->DirectoryCB,
4195 lCount = AFSVolumeDecrement( pVolumeCB,
4196 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4198 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4199 AFS_TRACE_LEVEL_VERBOSE,
4200 "AFSCheckCellName Decrement count on volume %p Cnt %d\n",
4207 lCount = InterlockedIncrement( &pDirHdr->ContentIndex);
4209 pDirNode = AFSInitDirEntry( &AFSGlobalRoot->ObjectInformation,
4215 if( pDirNode == NULL)
4218 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4222 // Init the short name if we have one
4225 if( pDirEnumEntry->ShortNameLength > 0)
4228 pDirNode->NameInformation.ShortNameLength = pDirEnumEntry->ShortNameLength;
4230 RtlCopyMemory( pDirNode->NameInformation.ShortName,
4231 pDirEnumEntry->ShortName,
4232 pDirNode->NameInformation.ShortNameLength);
4235 AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4239 // Insert the node into the name tree
4242 ASSERT( ExIsResourceAcquiredExclusiveLite( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock));
4244 if( pDirHdr->CaseSensitiveTreeHead == NULL)
4247 pDirHdr->CaseSensitiveTreeHead = pDirNode;
4252 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( pDirHdr->CaseSensitiveTreeHead,
4256 AFSDeleteDirEntry( &AFSGlobalRoot->ObjectInformation,
4259 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4261 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4265 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
4267 if( pDirHdr->CaseInsensitiveTreeHead == NULL)
4270 pDirHdr->CaseInsensitiveTreeHead = pDirNode;
4272 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
4277 AFSInsertCaseInsensitiveDirEntry( pDirHdr->CaseInsensitiveTreeHead,
4281 if( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead == NULL)
4284 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead = pDirNode;
4289 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
4291 pDirNode->ListEntry.bLink = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail;
4294 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail = pDirNode;
4296 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
4298 lCount = InterlockedIncrement( &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeCount);
4300 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
4301 AFS_TRACE_LEVEL_VERBOSE,
4302 "AFSCheckCellName Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
4303 &pDirNode->NameInformation.FileName,
4305 AFSGlobalRoot->ObjectInformation.FileId.Cell,
4306 AFSGlobalRoot->ObjectInformation.FileId.Volume,
4307 AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4308 AFSGlobalRoot->ObjectInformation.FileId.Unique);
4310 lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
4312 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4313 AFS_TRACE_LEVEL_VERBOSE,
4314 "AFSCheckCellName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
4315 &pDirNode->NameInformation.FileName,
4320 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4323 // Pass back the dir node
4326 *ShareDirEntry = pDirNode;
4331 if( pDirEnumEntry != NULL)
4334 AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_31_TAG);
4342 AFSBuildMountPointTarget( IN GUID *AuthGroup,
4343 IN AFSDirectoryCB *DirectoryCB,
4344 OUT AFSVolumeCB **TargetVolumeCB)
4347 NTSTATUS ntStatus = STATUS_SUCCESS;
4348 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4349 AFSDirEnumEntry *pDirEntry = NULL;
4350 ULONGLONG ullIndex = 0;
4351 AFSVolumeCB *pVolumeCB = NULL;
4352 AFSFileID stTargetFileID;
4354 BOOLEAN bReleaseVolumeLock = FALSE;
4360 // Loop on each entry, building the chain until we encounter the final target
4363 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4364 AFS_TRACE_LEVEL_VERBOSE_2,
4365 "AFSBuildMountPointTarget Building target directory for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4366 &DirectoryCB->NameInformation.FileName,
4367 DirectoryCB->ObjectInformation->FileId.Cell,
4368 DirectoryCB->ObjectInformation->FileId.Volume,
4369 DirectoryCB->ObjectInformation->FileId.Vnode,
4370 DirectoryCB->ObjectInformation->FileId.Unique);
4373 // Do we need to evaluate the node?
4376 //if( DirectoryCB->ObjectInformation->TargetFileId.Vnode == 0 &&
4377 // DirectoryCB->ObjectInformation->TargetFileId.Unique == 0)
4381 // Go evaluate the current target to get the target fid
4384 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4385 AFS_TRACE_LEVEL_VERBOSE_2,
4386 "AFSBuildMountPointTarget Evaluating target %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4387 &DirectoryCB->NameInformation.FileName,
4388 DirectoryCB->ObjectInformation->FileId.Cell,
4389 DirectoryCB->ObjectInformation->FileId.Volume,
4390 DirectoryCB->ObjectInformation->FileId.Vnode,
4391 DirectoryCB->ObjectInformation->FileId.Unique);
4393 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
4398 if( !NT_SUCCESS( ntStatus))
4401 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4402 AFS_TRACE_LEVEL_ERROR,
4403 "AFSBuildMountPointTarget Failed to evaluate target %wZ Status %08lX\n",
4404 &DirectoryCB->NameInformation.FileName,
4406 try_return( ntStatus);
4409 if( pDirEntry->TargetFileId.Vnode == 0 &&
4410 pDirEntry->TargetFileId.Unique == 0)
4413 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4414 AFS_TRACE_LEVEL_ERROR,
4415 "AFSBuildMountPointTarget Target %wZ FID %08lX-%08lX-%08lX-%08lX service returned zero FID\n",
4416 &DirectoryCB->NameInformation.FileName,
4417 DirectoryCB->ObjectInformation->FileId.Cell,
4418 DirectoryCB->ObjectInformation->FileId.Volume,
4419 DirectoryCB->ObjectInformation->FileId.Vnode,
4420 DirectoryCB->ObjectInformation->FileId.Unique);
4422 try_return( ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED);
4425 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
4428 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
4429 &DirectoryCB->Flags,
4430 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4431 (USHORT)pDirEntry->TargetNameLength);
4433 if( !NT_SUCCESS( ntStatus))
4436 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4438 try_return( ntStatus);
4441 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4443 DirectoryCB->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
4446 stTargetFileID = DirectoryCB->ObjectInformation->TargetFileId;
4449 // Try to locate this FID. First the volume then the
4453 ullIndex = AFSCreateHighIndex( &stTargetFileID);
4455 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4456 AFS_TRACE_LEVEL_VERBOSE,
4457 "AFSBuildMountPointTarget Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4458 &pDevExt->Specific.RDR.VolumeTreeLock,
4459 PsGetCurrentThread());
4461 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4464 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4465 AFS_TRACE_LEVEL_VERBOSE_2,
4466 "AFSBuildMountPointTarget Locating volume for target %I64X\n",
4469 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4471 (AFSBTreeEntry **)&pVolumeCB);
4474 // We can be processing a request for a target that is on a volume
4475 // we have never seen before.
4478 if( pVolumeCB == NULL)
4482 // Locking is held correctly in init routine
4485 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4488 // Go init the root of the volume
4491 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4492 AFS_TRACE_LEVEL_VERBOSE_2,
4493 "AFSBuildMountPointTarget Initializing root for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4494 &DirectoryCB->NameInformation.FileName,
4495 DirectoryCB->ObjectInformation->FileId.Cell,
4496 DirectoryCB->ObjectInformation->FileId.Volume,
4497 DirectoryCB->ObjectInformation->FileId.Vnode,
4498 DirectoryCB->ObjectInformation->FileId.Unique);
4500 ntStatus = AFSInitVolume( AuthGroup,
4502 AFS_VOLUME_REFERENCE_MOUNTPT,
4505 if( !NT_SUCCESS( ntStatus))
4508 try_return( ntStatus);
4512 // pVolumeCB->VolumeLock held exclusive and
4513 // pVolumeCB->VolumeReferenceCount has been incremented
4514 // pVolumeCB->RootFcb == NULL
4517 bReleaseVolumeLock = TRUE;
4523 // AFSInitVolume returns with a VolumeReferenceCount
4524 // obtain one to match
4527 lCount = AFSVolumeIncrement( pVolumeCB,
4528 AFS_VOLUME_REFERENCE_MOUNTPT);
4530 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4531 AFS_TRACE_LEVEL_VERBOSE,
4532 "AFSBuildMountPointTarget Increment count on volume %p Cnt %d\n",
4536 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4539 if( pVolumeCB->RootFcb == NULL)
4542 if ( bReleaseVolumeLock == FALSE)
4545 AFSAcquireExcl( pVolumeCB->VolumeLock,
4548 bReleaseVolumeLock = TRUE;
4552 // Initialize the root fcb for this volume
4555 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4558 if( !NT_SUCCESS( ntStatus))
4561 lCount = AFSVolumeDecrement( pVolumeCB,
4562 AFS_VOLUME_REFERENCE_MOUNTPT);
4564 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4565 AFS_TRACE_LEVEL_VERBOSE,
4566 "AFSBuildMountPoint Decrement count on volume %p Cnt %d\n",
4570 AFSReleaseResource( pVolumeCB->VolumeLock);
4572 try_return( ntStatus);
4576 // Drop the lock acquired above
4579 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4582 if ( bReleaseVolumeLock == TRUE)
4585 AFSReleaseResource( pVolumeCB->VolumeLock);
4588 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4589 AFS_TRACE_LEVEL_VERBOSE_2,
4590 "AFSBuildMountPointTarget Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4591 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4592 pVolumeCB->ObjectInformation.FileId.Cell,
4593 pVolumeCB->ObjectInformation.FileId.Volume,
4594 pVolumeCB->ObjectInformation.FileId.Vnode,
4595 pVolumeCB->ObjectInformation.FileId.Unique);
4597 *TargetVolumeCB = pVolumeCB;
4604 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
4612 AFSBuildRootVolume( IN GUID *AuthGroup,
4613 IN AFSFileID *FileId,
4614 OUT AFSVolumeCB **TargetVolumeCB)
4617 NTSTATUS ntStatus = STATUS_SUCCESS;
4618 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4619 ULONGLONG ullIndex = 0;
4620 AFSVolumeCB *pVolumeCB = NULL;
4622 BOOLEAN bReleaseVolumeLock = FALSE;
4627 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4628 AFS_TRACE_LEVEL_VERBOSE_2,
4629 "AFSBuildRootVolume Building target volume for FID %08lX-%08lX-%08lX-%08lX\n",
4635 ullIndex = AFSCreateHighIndex( FileId);
4637 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4638 AFS_TRACE_LEVEL_VERBOSE,
4639 "AFSBuildRootVolume Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4640 &pDevExt->Specific.RDR.VolumeTreeLock,
4641 PsGetCurrentThread());
4643 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4646 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4647 AFS_TRACE_LEVEL_VERBOSE_2,
4648 "AFSBuildRootVolume Locating volume for target %I64X\n",
4651 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4653 (AFSBTreeEntry **)&pVolumeCB);
4656 // We can be processing a request for a target that is on a volume
4657 // we have never seen before.
4660 if( pVolumeCB == NULL)
4664 // Locking is held correctly in init routine
4667 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4670 // Go init the root of the volume
4673 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4674 AFS_TRACE_LEVEL_VERBOSE_2,
4675 "AFSBuildRootVolume Initializing root for FID %08lX-%08lX-%08lX-%08lX\n",
4681 ntStatus = AFSInitVolume( AuthGroup,
4683 AFS_VOLUME_REFERENCE_BUILD_ROOT,
4686 if( !NT_SUCCESS( ntStatus))
4689 try_return( ntStatus);
4693 // pVolumeCB->VolumeLock is held exclusive
4694 // pVolumeCB->VolumeReferenceCount has been incremented
4695 // pVolumeCB->RootFcb == NULL
4698 bReleaseVolumeLock = TRUE;
4704 // AFSInitVolume returns with a VolumeReferenceCount
4705 // obtain one to match
4708 lCount = AFSVolumeIncrement( pVolumeCB,
4709 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4711 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4712 AFS_TRACE_LEVEL_VERBOSE,
4713 "AFSBuildRootVolume Increment count on volume %p Cnt %d\n",
4717 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4721 if( pVolumeCB->RootFcb == NULL)
4724 if ( bReleaseVolumeLock == FALSE)
4727 AFSAcquireExcl( pVolumeCB->VolumeLock,
4730 bReleaseVolumeLock = TRUE;
4734 // Initialize the root fcb for this volume
4737 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4740 if( !NT_SUCCESS( ntStatus))
4743 lCount = AFSVolumeDecrement( pVolumeCB,
4744 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4746 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4747 AFS_TRACE_LEVEL_VERBOSE,
4748 "AFSBuildRootVolume Decrement count on volume %p Cnt %d\n",
4752 AFSReleaseResource( pVolumeCB->VolumeLock);
4754 try_return( ntStatus);
4758 // Drop the lock acquired above
4761 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4764 if ( bReleaseVolumeLock == TRUE)
4767 AFSReleaseResource( pVolumeCB->VolumeLock);
4770 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4771 AFS_TRACE_LEVEL_VERBOSE_2,
4772 "AFSBuildRootVolume Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4773 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4774 pVolumeCB->ObjectInformation.FileId.Cell,
4775 pVolumeCB->ObjectInformation.FileId.Volume,
4776 pVolumeCB->ObjectInformation.FileId.Vnode,
4777 pVolumeCB->ObjectInformation.FileId.Unique);
4779 *TargetVolumeCB = pVolumeCB;
4790 AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
4791 IN PFILE_OBJECT FileObject,
4792 IN UNICODE_STRING *RemainingPath,
4796 NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
4797 UNICODE_STRING uniReparseName;
4798 UNICODE_STRING uniMUPDeviceName;
4799 UNICODE_STRING uniIOMgrDeviceName;
4800 AFSDirEnumEntry *pDirEntry = NULL;
4806 // Build up the name to reparse
4809 RtlInitUnicodeString( &uniMUPDeviceName,
4812 RtlInitUnicodeString( &uniIOMgrDeviceName,
4815 uniReparseName.Length = 0;
4816 uniReparseName.Buffer = NULL;
4819 // Be sure we have a target name
4822 if( DirEntry->NameInformation.TargetName.Length == 0)
4825 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
4830 if( !NT_SUCCESS( ntStatus) ||
4831 pDirEntry->TargetNameLength == 0)
4834 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4835 AFS_TRACE_LEVEL_ERROR,
4836 "AFSProcessDFSLink EvaluateTargetByID failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4837 &DirEntry->NameInformation.FileName,
4838 DirEntry->ObjectInformation->FileId.Cell,
4839 DirEntry->ObjectInformation->FileId.Volume,
4840 DirEntry->ObjectInformation->FileId.Vnode,
4841 DirEntry->ObjectInformation->FileId.Unique,
4844 if( NT_SUCCESS( ntStatus))
4847 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
4850 try_return( ntStatus);
4854 // Update the target name
4857 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
4860 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
4862 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4863 (USHORT)pDirEntry->TargetNameLength);
4865 if( !NT_SUCCESS( ntStatus))
4868 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4869 AFS_TRACE_LEVEL_ERROR,
4870 "AFSProcessDFSLink UpdateTargetName failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4871 &DirEntry->NameInformation.FileName,
4872 DirEntry->ObjectInformation->FileId.Cell,
4873 DirEntry->ObjectInformation->FileId.Volume,
4874 DirEntry->ObjectInformation->FileId.Vnode,
4875 DirEntry->ObjectInformation->FileId.Unique,
4878 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4880 try_return( ntStatus);
4883 AFSConvertToShared( &DirEntry->NonPaged->Lock);
4887 AFSAcquireShared( &DirEntry->NonPaged->Lock,
4891 uniReparseName.MaximumLength = uniMUPDeviceName.Length +
4893 DirEntry->NameInformation.TargetName.Length +
4896 if( RemainingPath != NULL &&
4897 RemainingPath->Length > 0)
4900 uniReparseName.MaximumLength += RemainingPath->Length;
4904 // Allocate the reparse buffer
4907 uniReparseName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4908 uniReparseName.MaximumLength,
4909 AFS_REPARSE_NAME_TAG);
4911 if( uniReparseName.Buffer == NULL)
4914 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4915 AFS_TRACE_LEVEL_ERROR,
4916 "AFSProcessDFSLink uniReparseName.Buffer == NULL Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4917 &DirEntry->NameInformation.FileName,
4918 DirEntry->ObjectInformation->FileId.Cell,
4919 DirEntry->ObjectInformation->FileId.Volume,
4920 DirEntry->ObjectInformation->FileId.Vnode,
4921 DirEntry->ObjectInformation->FileId.Unique,
4922 STATUS_INSUFFICIENT_RESOURCES);
4924 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4926 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4930 // Start building the name
4933 if ( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\' &&
4934 DirEntry->NameInformation.TargetName.Buffer[ 1] == L':')
4937 RtlCopyMemory( uniReparseName.Buffer,
4938 uniIOMgrDeviceName.Buffer,
4939 uniIOMgrDeviceName.Length);
4941 uniReparseName.Length = uniIOMgrDeviceName.Length;
4946 RtlCopyMemory( uniReparseName.Buffer,
4947 uniMUPDeviceName.Buffer,
4948 uniMUPDeviceName.Length);
4950 uniReparseName.Length = uniMUPDeviceName.Length;
4952 if( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\')
4955 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
4957 uniReparseName.Length += sizeof( WCHAR);
4961 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
4962 DirEntry->NameInformation.TargetName.Buffer,
4963 DirEntry->NameInformation.TargetName.Length);
4965 uniReparseName.Length += DirEntry->NameInformation.TargetName.Length;
4967 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4969 if( RemainingPath != NULL &&
4970 RemainingPath->Length > 0)
4973 if( uniReparseName.Buffer[ (uniReparseName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
4974 RemainingPath->Buffer[ 0] != L'\\')
4977 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
4979 uniReparseName.Length += sizeof( WCHAR);
4982 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
4983 RemainingPath->Buffer,
4984 RemainingPath->Length);
4986 uniReparseName.Length += RemainingPath->Length;
4990 // Update the name in the file object
4993 if( FileObject->FileName.Buffer != NULL)
4996 AFSExFreePoolWithTag( FileObject->FileName.Buffer, 0);
4999 FileObject->FileName = uniReparseName;
5001 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
5002 AFS_TRACE_LEVEL_VERBOSE,
5003 "AFSProcessDFSLink Reparsing access to Fcb %wZ FID %08lX-%08lX-%08lX-%08lX to %wZ\n",
5004 &DirEntry->NameInformation.FileName,
5005 DirEntry->ObjectInformation->FileId.Cell,
5006 DirEntry->ObjectInformation->FileId.Volume,
5007 DirEntry->ObjectInformation->FileId.Vnode,
5008 DirEntry->ObjectInformation->FileId.Unique,
5012 // Return status reparse ...
5015 ntStatus = STATUS_REPARSE;
5022 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);