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);
1220 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1222 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1225 if( uniPathName.Length > 0)
1228 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1229 AFS_TRACE_LEVEL_ERROR,
1230 "AFSLocateNameEntry (FO: %p) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1232 &pDirEntry->NameInformation.FileName,
1233 pCurrentObject->FileId.Cell,
1234 pCurrentObject->FileId.Volume,
1235 pCurrentObject->FileId.Vnode,
1236 pCurrentObject->FileId.Unique);
1238 // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1239 // one of the components of the path is not a directory. However, returning
1240 // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1241 // Instead IIS insists on treating the target file as if it is a directory containing
1242 // a potential web.config file. NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1243 // AFS will follow suit.
1245 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1250 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1251 AFS_TRACE_LEVEL_VERBOSE,
1252 "AFSLocateNameEntry (FO: %p) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1254 &pDirEntry->NameInformation.FileName,
1255 pCurrentObject->FileId.Cell,
1256 pCurrentObject->FileId.Volume,
1257 pCurrentObject->FileId.Vnode,
1258 pCurrentObject->FileId.Unique);
1261 // Pass back the directory entries
1264 *OutParentDirectoryCB = pParentDirEntry;
1266 pParentDirEntry = NULL;
1268 *OutDirectoryCB = pDirEntry;
1272 *OutVolumeCB = pCurrentVolume;
1274 *OutVolumeReferenceReason = VolumeReferenceReason;
1276 bReleaseCurrentVolume = FALSE;
1278 *RootPathName = uniFullPathName;
1281 try_return( ntStatus);
1285 // If we are at the end of the processing, set our returned information and get out
1288 if( uniPathName.Length == 0)
1291 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1292 AFS_TRACE_LEVEL_VERBOSE,
1293 "AFSLocateNameEntry (FO: %p) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1295 &pDirEntry->NameInformation.FileName,
1296 pCurrentObject->FileId.Cell,
1297 pCurrentObject->FileId.Volume,
1298 pCurrentObject->FileId.Vnode,
1299 pCurrentObject->FileId.Unique);
1302 // Pass back the directory entries
1305 *OutParentDirectoryCB = pParentDirEntry;
1307 pParentDirEntry = NULL;
1309 *OutDirectoryCB = pDirEntry;
1313 *OutVolumeCB = pCurrentVolume;
1315 *OutVolumeReferenceReason = VolumeReferenceReason;
1317 bReleaseCurrentVolume = FALSE;
1319 *RootPathName = uniFullPathName;
1321 try_return( ntStatus);
1325 // We may have returned to the top of the while( TRUE)
1327 if( bSubstituteName &&
1328 uniSearchName.Buffer != NULL)
1331 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1333 bSubstituteName = FALSE;
1335 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1336 uniSearchName.Buffer = NULL;
1339 ulSubstituteIndex = 1;
1341 ntStatus = STATUS_SUCCESS;
1344 // Get the next component name
1347 FsRtlDissectName( uniPathName,
1352 // Check for the . and .. in the path
1355 if( RtlCompareUnicodeString( &uniComponentName,
1360 uniPathName = uniRemainingPath;
1365 if( RtlCompareUnicodeString( &uniComponentName,
1370 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1371 AFS_TRACE_LEVEL_VERBOSE,
1372 "AFSLocateNameEntry (FO: %p) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1374 &pDirEntry->NameInformation.FileName,
1375 pCurrentObject->FileId.Cell,
1376 pCurrentObject->FileId.Volume,
1377 pCurrentObject->FileId.Vnode,
1378 pCurrentObject->FileId.Unique);
1381 // Need to back up one entry in the name array
1383 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1385 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1386 AFS_TRACE_LEVEL_VERBOSE,
1387 "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1388 &pDirEntry->NameInformation.FileName,
1393 ASSERT( lCount >= 0);
1395 pDirEntry = AFSBackupEntry( NameArray);
1397 if( pDirEntry == NULL)
1400 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1401 AFS_TRACE_LEVEL_ERROR,
1402 "AFSLocateNameEntry AFSBackupEntry failed\n");
1404 try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1407 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1409 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1410 AFS_TRACE_LEVEL_VERBOSE,
1411 "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1412 &pDirEntry->NameInformation.FileName,
1417 if ( pParentDirEntry)
1420 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1422 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1423 AFS_TRACE_LEVEL_VERBOSE,
1424 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1425 &pParentDirEntry->NameInformation.FileName,
1430 pParentDirEntry = NULL;
1433 if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1436 pParentDirEntry = AFSGetParentEntry( pNameArray);
1438 ASSERT( pParentDirEntry != pDirEntry);
1440 if ( pParentDirEntry)
1443 lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
1445 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1446 AFS_TRACE_LEVEL_VERBOSE,
1447 "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
1448 &pParentDirEntry->NameInformation.FileName,
1455 uniPathName = uniRemainingPath;
1461 // Update our pointers
1464 if ( pParentDirEntry)
1467 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1469 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1470 AFS_TRACE_LEVEL_VERBOSE,
1471 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1472 &pParentDirEntry->NameInformation.FileName,
1478 pParentDirEntry = pDirEntry;
1482 uniSearchName = uniComponentName;
1484 while( pDirEntry == NULL)
1488 // If the SearchName contains @SYS then we perform the substitution.
1489 // If there is no substitution we give up.
1492 if( !bSubstituteName &&
1493 FsRtlIsNameInExpression( &uniSysName,
1499 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1500 AFS_TRACE_LEVEL_VERBOSE_2,
1501 "AFSLocateNameEntry (FO: %p) Processing @SYS substitution for %wZ Index %08lX\n",
1506 ntStatus = AFSSubstituteSysName( &uniComponentName,
1510 if ( NT_SUCCESS( ntStatus))
1513 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1514 AFS_TRACE_LEVEL_VERBOSE_2,
1515 "AFSLocateNameEntry (FO: %p) Located substitution %wZ for %wZ Index %08lX\n",
1522 // Go reparse the name again
1525 bSubstituteName = TRUE;
1527 ulSubstituteIndex++; // For the next entry, if needed
1529 continue; // while( pDirEntry == NULL)
1534 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1535 AFS_TRACE_LEVEL_ERROR,
1536 "AFSLocateNameEntry (FO: %p) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1542 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1546 // Pass back the directory entries
1549 *OutParentDirectoryCB = pParentDirEntry;
1551 pParentDirEntry = NULL;
1553 *OutDirectoryCB = NULL;
1555 *OutVolumeCB = pCurrentVolume;
1557 *OutVolumeReferenceReason = VolumeReferenceReason;
1559 bReleaseCurrentVolume = FALSE;
1561 if( ComponentName != NULL)
1564 *ComponentName = uniComponentName;
1567 *RootPathName = uniFullPathName;
1571 // We can't possibly have a pDirEntry since the lookup failed
1573 try_return( ntStatus);
1578 // Generate the CRC on the node and perform a case sensitive lookup
1581 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1582 AFS_TRACE_LEVEL_VERBOSE_2,
1583 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case sensitive\n",
1587 ulCRC = AFSGenerateCRC( &uniSearchName,
1590 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1593 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1597 if( pDirEntry == NULL)
1601 // Missed so perform a case insensitive lookup
1604 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1605 AFS_TRACE_LEVEL_VERBOSE_2,
1606 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case insensitive\n",
1610 ulCRC = AFSGenerateCRC( &uniSearchName,
1613 AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1617 if( pDirEntry == NULL)
1621 // OK, if this component is a valid short name then try
1622 // a lookup in the short name tree
1625 if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1626 RtlIsNameLegalDOS8Dot3( &uniSearchName,
1631 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1632 AFS_TRACE_LEVEL_VERBOSE_2,
1633 "AFSLocateNameEntry (FO: %p) Searching for entry %wZ short name\n",
1637 AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1642 if ( pDirEntry == NULL &&
1643 pParentDirEntry->ObjectInformation->VolumeCB == AFSGlobalRoot)
1647 // Check with the service to see if this is a valid cell name
1648 // that can be automatically resolved. Drop the shared TreeLock
1649 // since AFSCheckCellName must acquire it exclusively.
1652 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1654 ntStatus = AFSCheckCellName( AuthGroup,
1658 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1662 if( pDirEntry == NULL)
1666 // If we substituted a name then reset our search name and try again
1669 if( bSubstituteName)
1672 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1674 uniSearchName = uniComponentName;
1676 bSubstituteName = FALSE;
1678 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1680 continue; // while( pDirEntry == NULL)
1684 // Node name not found so get out
1687 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1689 if( uniRemainingPath.Length > 0)
1692 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1694 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1695 AFS_TRACE_LEVEL_VERBOSE,
1696 "AFSLocateNameEntry (FO: %p) Returning path not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1699 pCurrentObject->FileId.Cell,
1700 pCurrentObject->FileId.Volume,
1701 pCurrentObject->FileId.Vnode,
1702 pCurrentObject->FileId.Unique);
1707 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1709 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1710 AFS_TRACE_LEVEL_VERBOSE,
1711 "AFSLocateNameEntry (FO: %p) Returning name not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1714 pCurrentObject->FileId.Cell,
1715 pCurrentObject->FileId.Volume,
1716 pCurrentObject->FileId.Vnode,
1717 pCurrentObject->FileId.Unique);
1720 // Pass back the directory entries
1723 *OutParentDirectoryCB = pParentDirEntry;
1725 pParentDirEntry = NULL;
1727 *OutDirectoryCB = NULL;
1729 *OutVolumeCB = pCurrentVolume;
1731 *OutVolumeReferenceReason = VolumeReferenceReason;
1733 bReleaseCurrentVolume = FALSE;
1735 if( ComponentName != NULL)
1738 *ComponentName = uniComponentName;
1741 *RootPathName = uniFullPathName;
1744 try_return( ntStatus);
1751 // Here we have a match on the case insensitive lookup for the name. If there
1752 // Is more than one link entry for this node then fail the lookup request
1755 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1756 pDirEntry->CaseInsensitiveList.fLink != NULL)
1760 // Increment our dir entry ref count since we will decrement it on exit
1763 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1765 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1766 AFS_TRACE_LEVEL_VERBOSE,
1767 "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1768 &pDirEntry->NameInformation.FileName,
1773 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1775 try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1780 if( pDirEntry != NULL)
1784 // If the verify flag is set on the parent and the current entry is deleted
1785 // revalidate the parent and search again.
1788 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1789 BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1792 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1794 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1795 AFS_TRACE_LEVEL_VERBOSE,
1796 "AFSLocateNameEntry (FO: %p) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1798 &pParentDirEntry->NameInformation.FileName,
1799 pParentDirEntry->ObjectInformation->FileId.Cell,
1800 pParentDirEntry->ObjectInformation->FileId.Volume,
1801 pParentDirEntry->ObjectInformation->FileId.Vnode,
1802 pParentDirEntry->ObjectInformation->FileId.Unique);
1805 // Directory TreeLock should be exclusively held
1808 AFSAcquireExcl( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1811 ntStatus = AFSVerifyEntry( AuthGroup,
1814 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1816 if( !NT_SUCCESS( ntStatus))
1819 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1820 AFS_TRACE_LEVEL_ERROR,
1821 "AFSLocateNameEntry (FO: %p) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1823 &pParentDirEntry->NameInformation.FileName,
1824 pParentDirEntry->ObjectInformation->FileId.Cell,
1825 pParentDirEntry->ObjectInformation->FileId.Volume,
1826 pParentDirEntry->ObjectInformation->FileId.Vnode,
1827 pParentDirEntry->ObjectInformation->FileId.Unique,
1830 try_return( ntStatus);
1833 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1834 AFS_TRACE_LEVEL_VERBOSE,
1835 "AFSLocateNameEntry (FO: %p) Reprocessing component %wZ in parent %wZ\n",
1838 &pParentDirEntry->NameInformation.FileName);
1847 // Increment our dir entry ref count
1850 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1852 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1853 AFS_TRACE_LEVEL_VERBOSE,
1854 "AFSLocateNameEntry Increment6 count on %wZ DE %p Ccb %p Cnt %d\n",
1855 &pDirEntry->NameInformation.FileName,
1861 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1863 } // End while( pDirEntry == NULL)
1866 // If we have a dirEntry for this component, perform some basic validation on it
1869 if( pDirEntry != NULL &&
1870 BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1873 pCurrentObject = pDirEntry->ObjectInformation;
1875 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1876 AFS_TRACE_LEVEL_ERROR,
1877 "AFSLocateNameEntry (FO: %p) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1879 &pDirEntry->NameInformation.FileName,
1880 pCurrentObject->FileId.Cell,
1881 pCurrentObject->FileId.Volume,
1882 pCurrentObject->FileId.Vnode,
1883 pCurrentObject->FileId.Unique);
1886 // This entry was deleted through the invalidation call back so perform cleanup
1890 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1893 pParentObjectInfo = AFSFindObjectInfo( pCurrentObject->VolumeCB,
1894 &pCurrentObject->ParentFileId);
1897 ASSERT( pParentObjectInfo != NULL);
1899 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1902 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1905 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1907 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1908 AFS_TRACE_LEVEL_VERBOSE,
1909 "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1910 &pDirEntry->NameInformation.FileName,
1915 ASSERT( lCount >= 0);
1920 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1921 AFS_TRACE_LEVEL_VERBOSE,
1922 "AFSLocateNameEntry Deleting dir entry %p (%p) for %wZ\n",
1925 &pDirEntry->NameInformation.FileName);
1928 // Remove and delete the directory entry from the parent list
1931 AFSDeleteDirEntry( pParentObjectInfo,
1934 AFSAcquireShared( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1937 if( pCurrentObject->ObjectReferenceCount <= 0)
1940 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
1943 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1944 AFS_TRACE_LEVEL_VERBOSE,
1945 "AFSLocateNameEntry Removing object %p from volume tree\n",
1948 AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
1949 &pCurrentObject->TreeEntry);
1951 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
1955 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1960 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1961 AFS_TRACE_LEVEL_VERBOSE,
1962 "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
1964 &pDirEntry->NameInformation.FileName);
1966 SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
1968 AFSRemoveNameEntry( pParentObjectInfo,
1972 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1974 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
1976 AFSReleaseObjectInfo( &pParentObjectInfo);
1979 // We deleted the dir entry so check if there is any remaining portion
1980 // of the name to process.
1983 if( uniRemainingPath.Length > 0)
1986 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1988 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1989 AFS_TRACE_LEVEL_VERBOSE,
1990 "AFSLocateNameEntry (FO: %p) Returning path not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1993 pCurrentObject->FileId.Cell,
1994 pCurrentObject->FileId.Volume,
1995 pCurrentObject->FileId.Vnode,
1996 pCurrentObject->FileId.Unique);
2001 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
2003 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2004 AFS_TRACE_LEVEL_VERBOSE,
2005 "AFSLocateNameEntry (FO: %p) Returning name not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2008 pCurrentObject->FileId.Cell,
2009 pCurrentObject->FileId.Volume,
2010 pCurrentObject->FileId.Vnode,
2011 pCurrentObject->FileId.Unique);
2014 // Pass back the directory entries
2017 *OutParentDirectoryCB = pParentDirEntry;
2019 pParentDirEntry = NULL;
2021 *OutDirectoryCB = NULL;
2023 *OutVolumeCB = pCurrentVolume;
2025 *OutVolumeReferenceReason = VolumeReferenceReason;
2027 bReleaseCurrentVolume = FALSE;
2029 if( ComponentName != NULL)
2032 *ComponentName = uniComponentName;
2035 *RootPathName = uniFullPathName;
2039 if( ntStatus != STATUS_SUCCESS)
2042 try_return( ntStatus);
2046 // If we ended up substituting a name in the component then update
2047 // the full path and update the pointers
2050 if( bSubstituteName)
2053 BOOLEAN bRelativeOpen = FALSE;
2055 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2056 AFS_TRACE_LEVEL_VERBOSE_2,
2057 "AFSLocateNameEntry (FO: %p) Substituting %wZ into %wZ Index %08lX\n",
2063 if( FileObject != NULL &&
2064 FileObject->RelatedFileObject != NULL)
2067 bRelativeOpen = TRUE;
2071 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
2072 // and free the prior Buffer contents but only if the fourth
2073 // parameter is TRUE.
2076 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
2081 bAllocatedSymLinkBuffer ||
2084 if( !NT_SUCCESS( ntStatus))
2087 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2088 AFS_TRACE_LEVEL_ERROR,
2089 "AFSLocateNameEntry (FO: %p) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
2096 try_return( ntStatus);
2100 // We have substituted a name into the buffer so if we do this again for this
2101 // path, we need to free up the buffer we allocated.
2104 bSubstitutedName = TRUE;
2108 // Update the search parameters
2111 uniPathName = uniRemainingPath;
2114 // Check if the is a SymLink entry but has no Target FileID or Name. In this
2115 // case it might be a DFS Link so let's go and evaluate it to be sure
2118 if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
2119 ( pCurrentObject->TargetFileId.Vnode == 0 ||
2120 pDirEntry->NameInformation.TargetName.Length == 0))
2123 ntStatus = AFSValidateSymLink( AuthGroup,
2126 if( !NT_SUCCESS( ntStatus))
2129 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2130 AFS_TRACE_LEVEL_ERROR,
2131 "AFSLocateNameEntry (FO: %p) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2133 &pDirEntry->NameInformation.FileName,
2134 pCurrentObject->FileId.Cell,
2135 pCurrentObject->FileId.Volume,
2136 pCurrentObject->FileId.Vnode,
2137 pCurrentObject->FileId.Unique,
2140 try_return( ntStatus);
2145 // Update the name array
2148 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2149 AFS_TRACE_LEVEL_VERBOSE,
2150 "AFSLocateNameEntry (FO: %p) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2152 &pDirEntry->NameInformation.FileName,
2153 pCurrentObject->FileId.Cell,
2154 pCurrentObject->FileId.Volume,
2155 pCurrentObject->FileId.Vnode,
2156 pCurrentObject->FileId.Unique);
2158 ntStatus = AFSInsertNextElement( pNameArray,
2161 if( !NT_SUCCESS( ntStatus))
2164 try_return( ntStatus);
2170 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2171 AFS_TRACE_LEVEL_VERBOSE,
2172 "AFSLocateNameEntry (FO: %p) Completed processing %wZ Status %08lX\n",
2177 if( ( !NT_SUCCESS( ntStatus) &&
2178 ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
2179 ntStatus == STATUS_REPARSE)
2181 if( RootPathName->Buffer != uniFullPathName.Buffer)
2184 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
2190 if( *OutParentDirectoryCB != NULL)
2193 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2194 AFS_TRACE_LEVEL_VERBOSE,
2195 "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
2196 &(*OutParentDirectoryCB)->NameInformation.FileName,
2197 *OutParentDirectoryCB,
2199 (*OutParentDirectoryCB)->DirOpenReferenceCount);
2202 if( *OutDirectoryCB != NULL)
2205 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2206 AFS_TRACE_LEVEL_VERBOSE,
2207 "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
2208 &(*OutDirectoryCB)->NameInformation.FileName,
2211 (*OutDirectoryCB)->DirOpenReferenceCount);
2215 if( pDirEntry != NULL)
2218 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
2220 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2221 AFS_TRACE_LEVEL_VERBOSE,
2222 "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
2223 &pDirEntry->NameInformation.FileName,
2228 ASSERT( lCount >= 0);
2231 if( pParentDirEntry != NULL)
2234 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
2236 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2237 AFS_TRACE_LEVEL_VERBOSE,
2238 "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
2239 &pParentDirEntry->NameInformation.FileName,
2244 ASSERT( lCount >= 0);
2247 if( bReleaseCurrentVolume)
2250 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
2252 lCount = AFSVolumeDecrement( pCurrentVolume,
2253 VolumeReferenceReason);
2255 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2256 AFS_TRACE_LEVEL_VERBOSE,
2257 "AFSLocateNameEntry Decrement7 count on volume %p Reason %u Cnt %d\n",
2259 VolumeReferenceReason,
2262 bReleaseCurrentVolume = FALSE;
2265 if( bSubstituteName &&
2266 uniSearchName.Buffer != NULL)
2269 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
2277 AFSCreateDirEntry( IN GUID *AuthGroup,
2278 IN AFSObjectInfoCB *ParentObjectInfo,
2279 IN AFSDirectoryCB *ParentDirCB,
2280 IN PUNICODE_STRING FileName,
2281 IN PUNICODE_STRING ComponentName,
2282 IN ULONG Attributes,
2283 IN OUT AFSDirectoryCB **DirEntry)
2286 UNREFERENCED_PARAMETER(FileName);
2287 NTSTATUS ntStatus = STATUS_SUCCESS;
2288 AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
2289 LARGE_INTEGER liFileSize = {0,0};
2295 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2296 AFS_TRACE_LEVEL_VERBOSE_2,
2297 "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
2298 &ParentDirCB->NameInformation.FileName,
2299 ParentObjectInfo->FileId.Cell,
2300 ParentObjectInfo->FileId.Volume,
2301 ParentObjectInfo->FileId.Vnode,
2302 ParentObjectInfo->FileId.Unique,
2307 // OK, before inserting the node into the parent tree, issue
2308 // the request to the service for node creation
2309 // We will need to drop the lock on the parent node since the create
2310 // could cause a callback into the file system to invalidate it's cache
2313 ntStatus = AFSNotifyFileCreate( AuthGroup,
2321 // If the returned status is STATUS_REPARSE then the entry exists
2322 // and we raced, get out.
2324 if( ntStatus == STATUS_REPARSE)
2327 *DirEntry = pDirNode;
2329 try_return( ntStatus = STATUS_SUCCESS);
2332 if( !NT_SUCCESS( ntStatus))
2335 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2336 AFS_TRACE_LEVEL_ERROR,
2337 "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
2338 &ParentDirCB->NameInformation.FileName,
2339 ParentObjectInfo->FileId.Cell,
2340 ParentObjectInfo->FileId.Volume,
2341 ParentObjectInfo->FileId.Vnode,
2342 ParentObjectInfo->FileId.Unique,
2347 try_return( ntStatus);
2351 // If AFSNotifyFileCreate returns pDirNode != NULL, then its
2352 // DirOpenReferenceCount is held.
2355 AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2359 // Before attempting to insert the new entry, check if we need to validate the parent
2362 if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2365 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2366 AFS_TRACE_LEVEL_VERBOSE,
2367 "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2368 &ParentDirCB->NameInformation.FileName,
2369 ParentObjectInfo->FileId.Cell,
2370 ParentObjectInfo->FileId.Volume,
2371 ParentObjectInfo->FileId.Vnode,
2372 ParentObjectInfo->FileId.Unique);
2374 ntStatus = AFSVerifyEntry( AuthGroup,
2377 if( !NT_SUCCESS( ntStatus))
2380 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2381 AFS_TRACE_LEVEL_ERROR,
2382 "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2383 &ParentDirCB->NameInformation.FileName,
2384 ParentObjectInfo->FileId.Cell,
2385 ParentObjectInfo->FileId.Volume,
2386 ParentObjectInfo->FileId.Vnode,
2387 ParentObjectInfo->FileId.Unique,
2390 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2392 try_return( ntStatus);
2397 // Check for the entry in the event we raced with some other thread
2400 AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2401 (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2404 if( pExistingDirNode != NULL)
2406 if (AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2407 &pExistingDirNode->ObjectInformation->FileId))
2410 if ( pExistingDirNode != pDirNode)
2413 lCount = InterlockedDecrement( &pDirNode->DirOpenReferenceCount);
2415 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2416 AFS_TRACE_LEVEL_VERBOSE,
2417 "AFSCreateDirEntry Decrement count on %wZ DE %p Cnt %d\n",
2418 &pDirNode->NameInformation.FileName,
2422 AFSDeleteDirEntry( ParentObjectInfo,
2425 lCount = InterlockedIncrement( &pExistingDirNode->DirOpenReferenceCount);
2427 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2428 AFS_TRACE_LEVEL_VERBOSE,
2429 "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2430 &pExistingDirNode->NameInformation.FileName,
2434 *DirEntry = pExistingDirNode;
2437 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2439 try_return( ntStatus = STATUS_SUCCESS);
2445 // Need to tear down this entry and rebuild it below
2448 if( pExistingDirNode->DirOpenReferenceCount <= 0)
2451 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2452 AFS_TRACE_LEVEL_VERBOSE,
2453 "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2455 &pExistingDirNode->NameInformation.FileName,
2456 pExistingDirNode->ObjectInformation->FileId.Cell,
2457 pExistingDirNode->ObjectInformation->FileId.Volume,
2458 pExistingDirNode->ObjectInformation->FileId.Vnode,
2459 pExistingDirNode->ObjectInformation->FileId.Unique,
2460 pDirNode->ObjectInformation->FileId.Cell,
2461 pDirNode->ObjectInformation->FileId.Volume,
2462 pDirNode->ObjectInformation->FileId.Vnode,
2463 pDirNode->ObjectInformation->FileId.Unique);
2465 AFSDeleteDirEntry( ParentObjectInfo,
2471 SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2473 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2474 AFS_TRACE_LEVEL_VERBOSE,
2475 "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2477 &pExistingDirNode->NameInformation.FileName,
2478 pExistingDirNode->ObjectInformation->FileId.Cell,
2479 pExistingDirNode->ObjectInformation->FileId.Volume,
2480 pExistingDirNode->ObjectInformation->FileId.Vnode,
2481 pExistingDirNode->ObjectInformation->FileId.Unique,
2482 pDirNode->ObjectInformation->FileId.Cell,
2483 pDirNode->ObjectInformation->FileId.Volume,
2484 pDirNode->ObjectInformation->FileId.Vnode,
2485 pDirNode->ObjectInformation->FileId.Unique);
2487 AFSRemoveNameEntry( ParentObjectInfo,
2493 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2494 AFS_TRACE_LEVEL_VERBOSE_2,
2495 "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2496 &ParentDirCB->NameInformation.FileName,
2497 ParentObjectInfo->FileId.Cell,
2498 ParentObjectInfo->FileId.Volume,
2499 ParentObjectInfo->FileId.Vnode,
2500 ParentObjectInfo->FileId.Unique,
2504 // Insert the directory node
2507 AFSInsertDirectoryNode( ParentObjectInfo,
2512 // Pass back the dir entry
2515 *DirEntry = pDirNode;
2517 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2528 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2529 IN AFSDirectoryCB *DirEntry,
2530 IN BOOLEAN InsertInEnumList)
2538 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2541 // Insert the node into the directory node tree
2544 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2545 AFS_TRACE_LEVEL_VERBOSE,
2546 "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2548 &DirEntry->NameInformation.FileName);
2550 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2552 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2555 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2557 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2558 AFS_TRACE_LEVEL_VERBOSE,
2559 "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2561 &DirEntry->NameInformation.FileName);
2566 AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2569 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2570 AFS_TRACE_LEVEL_VERBOSE,
2571 "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2573 &DirEntry->NameInformation.FileName);
2576 if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2579 ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2581 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2583 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2584 AFS_TRACE_LEVEL_VERBOSE,
2585 "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2587 &DirEntry->NameInformation.FileName);
2592 AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2595 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2596 AFS_TRACE_LEVEL_VERBOSE,
2597 "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2599 &DirEntry->NameInformation.FileName);
2603 // Into the shortname tree
2606 if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2609 if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2612 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2614 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2615 AFS_TRACE_LEVEL_VERBOSE,
2616 "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2618 &DirEntry->NameInformation.FileName);
2620 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2625 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2628 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2629 AFS_TRACE_LEVEL_VERBOSE,
2630 "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2632 &DirEntry->NameInformation.FileName);
2636 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2638 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2639 AFS_TRACE_LEVEL_VERBOSE,
2640 "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2642 &DirEntry->NameInformation.FileName);
2647 if( InsertInEnumList)
2651 // And insert the node into the directory list
2654 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2655 AFS_TRACE_LEVEL_VERBOSE,
2656 "AFSInsertDirectoryNode Inserting entry %p %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2658 &DirEntry->NameInformation.FileName,
2659 DirEntry->ObjectInformation->FileId.Cell,
2660 DirEntry->ObjectInformation->FileId.Volume,
2661 DirEntry->ObjectInformation->FileId.Vnode,
2662 DirEntry->ObjectInformation->FileId.Unique);
2664 if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2667 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2672 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2674 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2677 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2679 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2681 lCount = InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2683 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2684 AFS_TRACE_LEVEL_VERBOSE,
2685 "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2686 &DirEntry->NameInformation.FileName,
2688 ParentObjectInfo->FileId.Cell,
2689 ParentObjectInfo->FileId.Volume,
2690 ParentObjectInfo->FileId.Vnode,
2691 ParentObjectInfo->FileId.Unique);
2699 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2700 IN AFSDirectoryCB *DirEntry)
2708 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2709 AFS_TRACE_LEVEL_VERBOSE,
2710 "AFSDeleteDirEntry Deleting dir entry in parent %p Entry %p %wZ FID %08lX-%08lX-%08lX-%08lX RefCount %d\n",
2713 &DirEntry->NameInformation.FileName,
2714 DirEntry->ObjectInformation->FileId.Cell,
2715 DirEntry->ObjectInformation->FileId.Volume,
2716 DirEntry->ObjectInformation->FileId.Vnode,
2717 DirEntry->ObjectInformation->FileId.Unique,
2718 DirEntry->DirOpenReferenceCount);
2720 ASSERT( DirEntry->DirOpenReferenceCount == 0);
2722 AFSRemoveDirNodeFromParent( ParentObjectInfo,
2727 // Free up the name buffer if it was reallocated
2730 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2733 AFSExFreePoolWithTag( DirEntry->NameInformation.FileName.Buffer, 0);
2736 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2739 AFSExFreePoolWithTag( DirEntry->NameInformation.TargetName.Buffer, 0);
2743 // Dereference the object for this dir entry
2746 lCount = AFSObjectInfoDecrement( DirEntry->ObjectInformation,
2747 AFS_OBJECT_REFERENCE_DIRENTRY);
2749 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2750 AFS_TRACE_LEVEL_VERBOSE,
2751 "AFSDeleteDirEntry Decrement count on object %p Cnt %d\n",
2752 DirEntry->ObjectInformation,
2755 if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
2756 DirEntry->ObjectInformation->Links == 0)
2759 SetFlag( DirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2762 ExDeleteResourceLite( &DirEntry->NonPaged->Lock);
2764 AFSExFreePoolWithTag( DirEntry->NonPaged, AFS_DIR_ENTRY_NP_TAG);
2767 // Free up the dir entry
2770 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
2771 AFS_TRACE_LEVEL_VERBOSE,
2772 "AFSDeleteDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
2775 AFSExFreePoolWithTag( DirEntry, AFS_DIR_ENTRY_TAG);
2780 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2781 IN AFSDirectoryCB *DirEntry,
2782 IN BOOLEAN RemoveFromEnumList)
2785 NTSTATUS ntStatus = STATUS_SUCCESS;
2792 ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2794 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2795 AFS_TRACE_LEVEL_VERBOSE,
2796 "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %p\n",
2798 &DirEntry->NameInformation.FileName,
2799 DirEntry->ObjectInformation->FileId.Cell,
2800 DirEntry->ObjectInformation->FileId.Volume,
2801 DirEntry->ObjectInformation->FileId.Vnode,
2802 DirEntry->ObjectInformation->FileId.Unique,
2805 if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2808 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2809 AFS_TRACE_LEVEL_VERBOSE,
2810 "AFSRemoveDirNodeFromParent Removing DirEntry %p name %wZ\n",
2812 &DirEntry->NameInformation.FileName);
2814 AFSRemoveNameEntry( ParentObjectInfo,
2820 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2821 AFS_TRACE_LEVEL_VERBOSE,
2822 "AFSRemoveDirNodeFromParent DE %p for %wZ NOT removing entry due to flag set\n",
2824 &DirEntry->NameInformation.FileName);
2828 if( RemoveFromEnumList &&
2829 BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST))
2833 // And remove the entry from the enumeration list
2836 if( DirEntry->ListEntry.fLink == NULL)
2839 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = (AFSDirectoryCB *)DirEntry->ListEntry.bLink;
2844 ((AFSDirectoryCB *)DirEntry->ListEntry.fLink)->ListEntry.bLink = DirEntry->ListEntry.bLink;
2847 if( DirEntry->ListEntry.bLink == NULL)
2850 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = (AFSDirectoryCB *)DirEntry->ListEntry.fLink;
2855 ((AFSDirectoryCB *)DirEntry->ListEntry.bLink)->ListEntry.fLink = DirEntry->ListEntry.fLink;
2858 ASSERT( ParentObjectInfo->Specific.Directory.DirectoryNodeCount > 0);
2860 lCount = InterlockedDecrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2862 ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2864 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2865 AFS_TRACE_LEVEL_VERBOSE,
2866 "AFSRemoveDirNodeFromParent Removing entry %wZ Dec Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2867 &DirEntry->NameInformation.FileName,
2869 ParentObjectInfo->FileId.Cell,
2870 ParentObjectInfo->FileId.Volume,
2871 ParentObjectInfo->FileId.Vnode,
2872 ParentObjectInfo->FileId.Unique);
2874 DirEntry->ListEntry.fLink = NULL;
2875 DirEntry->ListEntry.bLink = NULL;
2883 AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
2884 IN OUT PUNICODE_STRING TargetFileName)
2887 NTSTATUS ntStatus = STATUS_SUCCESS;
2888 UNICODE_STRING uniFileName;
2894 // We will process backwards from the end of the name looking
2895 // for the first \ we encounter
2898 uniFileName.Length = FileName->Length;
2899 uniFileName.MaximumLength = FileName->MaximumLength;
2901 uniFileName.Buffer = FileName->Buffer;
2906 if( uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
2910 // Subtract one more character off of the filename if it is not the root
2913 if( uniFileName.Length > sizeof( WCHAR))
2916 uniFileName.Length -= sizeof( WCHAR);
2920 // Now build up the target name
2923 TargetFileName->Length = FileName->Length - uniFileName.Length;
2926 // If we are not on the root then fixup the name
2929 if( uniFileName.Length > sizeof( WCHAR))
2932 TargetFileName->Length -= sizeof( WCHAR);
2934 TargetFileName->Buffer = &uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) + 1];
2939 TargetFileName->Buffer = &uniFileName.Buffer[ uniFileName.Length/sizeof( WCHAR)];
2943 // Fixup the passed back filename length
2946 FileName->Length = uniFileName.Length;
2948 TargetFileName->MaximumLength = TargetFileName->Length;
2953 uniFileName.Length -= sizeof( WCHAR);
2961 AFSParseName( IN PIRP Irp,
2963 OUT PUNICODE_STRING FileName,
2964 OUT PUNICODE_STRING ParsedFileName,
2965 OUT PUNICODE_STRING RootFileName,
2966 OUT ULONG *ParseFlags,
2967 OUT AFSVolumeCB **VolumeCB,
2968 OUT AFSDirectoryCB **ParentDirectoryCB,
2969 OUT AFSNameArrayHdr **NameArray)
2972 NTSTATUS ntStatus = STATUS_SUCCESS;
2973 PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2974 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2975 UNICODE_STRING uniFullName, uniComponentName, uniRemainingPath;
2977 AFSDirectoryCB *pDirEntry = NULL;
2978 USHORT usIndex = 0, usDriveIndex = 0;
2979 AFSCcb *pRelatedCcb = NULL;
2980 AFSNameArrayHdr *pNameArray = NULL, *pRelatedNameArray = NULL;
2981 USHORT usComponentIndex = 0;
2982 USHORT usComponentLength = 0;
2983 AFSVolumeCB *pVolumeCB = NULL;
2984 AFSFcb *pRelatedFcb = NULL;
2985 BOOLEAN bReleaseTreeLock = FALSE;
2986 BOOLEAN bIsAllShare = FALSE;
2993 // Indicate we are opening a root ...
2996 *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
2998 *ParentDirectoryCB = NULL;
3000 if( pIrpSp->FileObject->RelatedFileObject != NULL)
3003 pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
3005 pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
3007 pRelatedNameArray = pRelatedCcb->NameArray;
3009 uniFullName = pIrpSp->FileObject->FileName;
3011 ASSERT( pRelatedFcb != NULL);
3014 // No wild cards in the name
3017 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3018 AFS_TRACE_LEVEL_VERBOSE_2,
3019 "AFSParseName (%p) Relative open for %wZ FID %08lX-%08lX-%08lX-%08lX component %wZ\n",
3021 &pRelatedCcb->DirectoryCB->NameInformation.FileName,
3022 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Cell,
3023 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Volume,
3024 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
3025 pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Unique,
3028 if( FsRtlDoesNameContainWildCards( &uniFullName))
3031 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3032 AFS_TRACE_LEVEL_ERROR,
3033 "AFSParseName (%p) Component %wZ contains wild cards\n",
3037 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3040 pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
3042 pDirEntry = pRelatedCcb->DirectoryCB;
3044 *FileName = pIrpSp->FileObject->FileName;
3047 // Grab the root node while checking state
3050 AFSAcquireShared( pVolumeCB->VolumeLock,
3053 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3054 BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3058 // The volume has been taken off line so fail the access
3061 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3062 AFS_TRACE_LEVEL_ERROR,
3063 "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3065 pVolumeCB->ObjectInformation.FileId.Cell,
3066 pVolumeCB->ObjectInformation.FileId.Volume);
3068 AFSReleaseResource( pVolumeCB->VolumeLock);
3070 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3073 if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3076 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3077 AFS_TRACE_LEVEL_VERBOSE,
3078 "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
3080 pVolumeCB->ObjectInformation.FileId.Cell,
3081 pVolumeCB->ObjectInformation.FileId.Volume);
3083 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3086 if( !NT_SUCCESS( ntStatus))
3089 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3090 AFS_TRACE_LEVEL_ERROR,
3091 "AFSParseName (%p) Failed verification of root Status %08lX\n",
3095 AFSReleaseResource( pVolumeCB->VolumeLock);
3097 try_return( ntStatus);
3101 AFSReleaseResource( pVolumeCB->VolumeLock);
3103 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
3106 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3107 AFS_TRACE_LEVEL_VERBOSE,
3108 "AFSParseName (%p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3110 &pDirEntry->NameInformation.FileName,
3111 pDirEntry->ObjectInformation->FileId.Cell,
3112 pDirEntry->ObjectInformation->FileId.Volume,
3113 pDirEntry->ObjectInformation->FileId.Vnode,
3114 pDirEntry->ObjectInformation->FileId.Unique);
3117 // Directory TreeLock should be exclusively held
3120 AFSAcquireExcl( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
3123 ntStatus = AFSVerifyEntry( AuthGroup,
3126 AFSReleaseResource( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
3128 if( !NT_SUCCESS( ntStatus))
3131 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3132 AFS_TRACE_LEVEL_VERBOSE,
3133 "AFSParseName (%p) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3135 &pDirEntry->NameInformation.FileName,
3136 pDirEntry->ObjectInformation->FileId.Cell,
3137 pDirEntry->ObjectInformation->FileId.Volume,
3138 pDirEntry->ObjectInformation->FileId.Vnode,
3139 pDirEntry->ObjectInformation->FileId.Unique,
3142 try_return( ntStatus);
3147 // Create our full path name buffer
3150 uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length +
3152 pIrpSp->FileObject->FileName.Length +
3155 uniFullName.Length = 0;
3157 uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
3158 uniFullName.MaximumLength,
3159 AFS_NAME_BUFFER_THREE_TAG);
3161 if( uniFullName.Buffer == NULL)
3164 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3165 AFS_TRACE_LEVEL_ERROR,
3166 "AFSParseName (%p) Failed to allocate full name buffer\n",
3169 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3172 RtlZeroMemory( uniFullName.Buffer,
3173 uniFullName.MaximumLength);
3175 RtlCopyMemory( uniFullName.Buffer,
3176 pRelatedCcb->FullFileName.Buffer,
3177 pRelatedCcb->FullFileName.Length);
3179 uniFullName.Length = pRelatedCcb->FullFileName.Length;
3181 usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
3183 usComponentLength = pIrpSp->FileObject->FileName.Length;
3185 if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
3186 pIrpSp->FileObject->FileName.Length > 0 &&
3187 pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
3188 pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
3191 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
3193 uniFullName.Length += sizeof( WCHAR);
3195 usComponentLength += sizeof( WCHAR);
3198 if( pIrpSp->FileObject->FileName.Length > 0)
3201 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
3202 pIrpSp->FileObject->FileName.Buffer,
3203 pIrpSp->FileObject->FileName.Length);
3205 uniFullName.Length += pIrpSp->FileObject->FileName.Length;
3208 *RootFileName = uniFullName;
3211 // We populate up to the current parent
3214 if( pRelatedNameArray == NULL)
3218 // Init and populate our name array
3221 pNameArray = AFSInitNameArray( NULL,
3224 if( pNameArray == NULL)
3227 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3228 AFS_TRACE_LEVEL_VERBOSE,
3229 "AFSParseName (%p) Failed to initialize name array\n",
3232 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3234 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3237 ntStatus = AFSPopulateNameArray( pNameArray,
3239 pRelatedCcb->DirectoryCB);
3245 // Init and populate our name array
3248 pNameArray = AFSInitNameArray( NULL,
3249 pRelatedNameArray->MaxElementCount);
3251 if( pNameArray == NULL)
3254 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3255 AFS_TRACE_LEVEL_VERBOSE,
3256 "AFSParseName (%p) Failed to initialize name array\n",
3259 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3261 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3264 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
3266 pRelatedCcb->DirectoryCB);
3269 if( !NT_SUCCESS( ntStatus))
3272 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3273 AFS_TRACE_LEVEL_VERBOSE,
3274 "AFSParseName (%p) Failed to populate name array\n",
3277 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3279 try_return( ntStatus);
3282 ParsedFileName->Length = usComponentLength;
3283 ParsedFileName->MaximumLength = uniFullName.MaximumLength;
3285 ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
3288 // Indicate to caller that RootFileName must be freed
3291 SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
3293 *NameArray = pNameArray;
3296 // Increment our volume reference count
3299 lCount = AFSVolumeIncrement( pVolumeCB,
3300 AFS_VOLUME_REFERENCE_PARSE_NAME);
3302 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3303 AFS_TRACE_LEVEL_VERBOSE,
3304 "AFSParseName Increment count on volume %p Cnt %d\n",
3308 *VolumeCB = pVolumeCB;
3310 *ParentDirectoryCB = pDirEntry;
3312 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3313 AFS_TRACE_LEVEL_VERBOSE_2,
3314 "AFSParseName (%p) Returning full name %wZ\n",
3318 try_return( ntStatus);
3322 // No wild cards in the name
3325 uniFullName = pIrpSp->FileObject->FileName;
3327 if( FsRtlDoesNameContainWildCards( &uniFullName) ||
3328 uniFullName.Length < AFSServerName.Length)
3331 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3332 AFS_TRACE_LEVEL_ERROR,
3333 "AFSParseName (%p) Name %wZ contains wild cards or too short\n",
3337 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3341 // The name is a fully qualified name. Parse out the server/share names and
3342 // point to the root qualified name
3343 // First thing is to locate the server name
3346 FsRtlDissectName( uniFullName,
3350 uniFullName = uniRemainingPath;
3353 // This component is the server name we are serving
3356 if( RtlCompareUnicodeString( &uniComponentName,
3362 // Drive letter based name?
3365 uniFullName = pIrpSp->FileObject->FileName;
3367 while( usIndex < uniFullName.Length/sizeof( WCHAR))
3370 if( uniFullName.Buffer[ usIndex] == L':')
3373 uniFullName.Buffer = &uniFullName.Buffer[ usIndex + 2];
3375 uniFullName.Length -= (usIndex + 2) * sizeof( WCHAR);
3377 usDriveIndex = usIndex - 1;
3386 // Do we have the right server name now?
3389 FsRtlDissectName( uniFullName,
3393 uniFullName = uniRemainingPath;
3396 // This component is the server name we are serving
3399 if( RtlCompareUnicodeString( &uniComponentName,
3404 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3405 AFS_TRACE_LEVEL_ERROR,
3406 "AFSParseName (%p) Name %wZ does not have server name\n",
3408 &pIrpSp->FileObject->FileName);
3410 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3414 // Validate this drive letter is actively mapped
3417 if( usDriveIndex > 0 &&
3418 !AFSIsDriveMapped( pIrpSp->FileObject->FileName.Buffer[ usDriveIndex]))
3421 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3422 AFS_TRACE_LEVEL_ERROR,
3423 "AFSParseName (%p) Name %wZ contains invalid drive mapping\n",
3425 &pIrpSp->FileObject->FileName);
3427 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3431 if( FsRtlDoesNameContainWildCards( &uniFullName))
3434 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3435 AFS_TRACE_LEVEL_ERROR,
3436 "AFSParseName (%p) Component %wZ contains wild cards\n",
3440 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3443 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3444 AFS_TRACE_LEVEL_VERBOSE_2,
3445 "AFSParseName (%p) Processing full name %wZ\n",
3449 if( uniFullName.Length > 0 &&
3450 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] == L'\\')
3453 uniFullName.Length -= sizeof( WCHAR);
3457 // Be sure we are online and ready to go
3460 AFSAcquireShared( AFSGlobalRoot->VolumeLock,
3463 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3464 BooleanFlagOn( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3468 // The volume has been taken off line so fail the access
3471 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3472 AFS_TRACE_LEVEL_ERROR,
3473 "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3475 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3476 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3478 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3480 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3483 if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3486 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3487 AFS_TRACE_LEVEL_VERBOSE,
3488 "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
3490 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3491 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3493 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3496 if( !NT_SUCCESS( ntStatus))
3499 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3500 AFS_TRACE_LEVEL_ERROR,
3501 "AFSParseName (%p) Failed verification of root Status %08lX\n",
3505 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3507 try_return( ntStatus);
3511 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3513 if( !BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3516 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3517 AFS_TRACE_LEVEL_VERBOSE,
3518 "AFSParseName (%p) Enumerating global root of volume %08lX:%08lX\n",
3520 AFSGlobalRoot->ObjectInformation.FileId.Cell,
3521 AFSGlobalRoot->ObjectInformation.FileId.Volume);
3523 ntStatus = AFSEnumerateGlobalRoot( AuthGroup);
3525 if( !NT_SUCCESS( ntStatus))
3528 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3529 AFS_TRACE_LEVEL_ERROR,
3530 "AFSParseName (%p) Failed enumeraiton of root Status %08lX\n",
3534 try_return( ntStatus);
3539 // Check for the \\Server access and return it as though it were \\Server\Globalroot
3542 if( uniRemainingPath.Buffer == NULL ||
3543 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3544 uniRemainingPath.Buffer[ 0] == L'\\'))
3547 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3548 AFS_TRACE_LEVEL_VERBOSE_2,
3549 "AFSParseName (%p) Returning global root access\n",
3552 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3554 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3555 AFS_TRACE_LEVEL_VERBOSE,
3556 "AFSParseName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3557 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3558 AFSGlobalRoot->DirectoryCB,
3564 FileName->Length = 0;
3565 FileName->MaximumLength = 0;
3566 FileName->Buffer = NULL;
3568 try_return( ntStatus = STATUS_SUCCESS);
3571 *RootFileName = uniFullName;
3574 // Include the starting \ in the root name
3577 if( RootFileName->Buffer[ 0] != L'\\')
3579 RootFileName->Buffer--;
3580 RootFileName->Length += sizeof( WCHAR);
3581 RootFileName->MaximumLength += sizeof( WCHAR);
3585 // Get the 'share' name
3588 FsRtlDissectName( uniFullName,
3592 if( FsRtlDoesNameContainWildCards( &uniFullName))
3595 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3596 AFS_TRACE_LEVEL_ERROR,
3597 "AFSParseName (%p) Component %wZ contains wild cards\n",
3601 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3605 // If this is the ALL access then perform some additional processing
3608 if( uniComponentName.Length == 0 ||
3609 RtlCompareUnicodeString( &uniComponentName,
3617 // If there is nothing else then get out
3620 if( uniRemainingPath.Buffer == NULL ||
3621 uniRemainingPath.Length == 0 ||
3622 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3623 uniRemainingPath.Buffer[ 0] == L'\\'))
3626 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3627 AFS_TRACE_LEVEL_VERBOSE_2,
3628 "AFSParseName (%p) Returning global root access\n",
3631 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3633 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3634 AFS_TRACE_LEVEL_VERBOSE,
3635 "AFSParseName Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
3636 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3637 AFSGlobalRoot->DirectoryCB,
3643 FileName->Length = 0;
3644 FileName->MaximumLength = 0;
3645 FileName->Buffer = NULL;
3647 try_return( ntStatus = STATUS_SUCCESS);
3651 // Process the name again to strip off the ALL portion
3654 uniFullName = uniRemainingPath;
3656 FsRtlDissectName( uniFullName,
3661 // Check for the PIOCtl name
3664 if( RtlCompareUnicodeString( &uniComponentName,
3669 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3670 AFS_TRACE_LEVEL_VERBOSE_2,
3671 "AFSParseName (%p) Returning root PIOCtl access\n",
3674 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3676 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3677 AFS_TRACE_LEVEL_VERBOSE,
3678 "AFSParseName Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
3679 &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3680 AFSGlobalRoot->DirectoryCB,
3684 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3688 *FileName = AFSPIOCtlName;
3690 try_return( ntStatus = STATUS_SUCCESS);
3693 else if( (pDirEntry = AFSGetSpecialShareNameEntry( &uniComponentName,
3694 &uniRemainingPath)) != NULL)
3697 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3698 AFS_TRACE_LEVEL_VERBOSE_2,
3699 "AFSParseName (%p) Returning root share name %wZ access\n",
3704 // Add in the full share name to pass back
3707 if( uniRemainingPath.Buffer != NULL)
3711 // This routine strips off the leading slash so add it back in
3714 uniRemainingPath.Buffer--;
3715 uniRemainingPath.Length += sizeof( WCHAR);
3716 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3719 // And the cell name
3722 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3723 uniRemainingPath.Length += uniComponentName.Length;
3724 uniRemainingPath.MaximumLength += uniComponentName.Length;
3726 uniComponentName = uniRemainingPath;
3731 *FileName = uniComponentName;
3733 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3735 *ParentDirectoryCB = pDirEntry;
3737 try_return( ntStatus = STATUS_SUCCESS);
3741 // Determine the 'share' we are accessing
3744 ulCRC = AFSGenerateCRC( &uniComponentName,
3747 AFSAcquireShared( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3750 bReleaseTreeLock = TRUE;
3752 AFSLocateCaseSensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
3756 if( pDirEntry == NULL)
3759 ulCRC = AFSGenerateCRC( &uniComponentName,
3762 AFSLocateCaseInsensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
3766 if( pDirEntry == NULL)
3770 // OK, if this component is a valid short name then try
3771 // a lookup in the short name tree
3774 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3775 RtlIsNameLegalDOS8Dot3( &uniComponentName,
3780 AFSLocateShortNameDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.ShortNameTree,
3785 if( pDirEntry == NULL)
3789 // Check with the service whether it is a valid cell name
3792 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3794 bReleaseTreeLock = FALSE;
3796 ntStatus = AFSCheckCellName( AuthGroup,
3800 if( !NT_SUCCESS( ntStatus))
3804 uniRemainingPath.Length == 0 &&
3805 ntStatus == STATUS_OBJECT_PATH_NOT_FOUND)
3808 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3809 AFS_TRACE_LEVEL_VERBOSE,
3810 "AFSParseName (%p) AFSCheckCellName %wZ returned path not found; ntStatus %08X\n",
3813 STATUS_OBJECT_NAME_NOT_FOUND);
3815 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
3818 try_return( ntStatus);
3824 if( bReleaseTreeLock)
3826 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3831 // Be sure we are starting from the correct volume
3834 if( pDirEntry->ObjectInformation->VolumeCB != AFSGlobalRoot)
3838 // We dropped the global root in the CheckCellName routine which is the
3839 // only way we can be here
3842 pVolumeCB = pDirEntry->ObjectInformation->VolumeCB;
3845 // Init our name array
3848 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
3851 if( pNameArray == NULL)
3854 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3855 AFS_TRACE_LEVEL_VERBOSE,
3856 "AFSParseName (%p) Failed to initialize name array\n",
3859 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3862 ntStatus = AFSInsertNextElement( pNameArray,
3863 pVolumeCB->DirectoryCB);
3868 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3869 AFS_TRACE_LEVEL_VERBOSE,
3870 "AFSParseName (%p) Failed to insert name array element\n",
3873 try_return( ntStatus);
3877 // In this case don't add back in the 'share' name since that is where we are
3878 // starting. Just put the leading slash back in
3881 if( uniRemainingPath.Buffer != NULL)
3884 uniRemainingPath.Buffer--;
3885 uniRemainingPath.Length += sizeof( WCHAR);
3886 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3888 if( uniRemainingPath.Length > sizeof( WCHAR))
3891 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3895 // Pass back the parent being the root of the volume
3898 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3904 // Pass back a root slash
3907 uniRemainingPath = uniComponentName;
3909 uniRemainingPath.Buffer--;
3910 uniRemainingPath.Length = sizeof( WCHAR);
3911 uniRemainingPath.MaximumLength = sizeof( WCHAR);
3914 // This is a root open so pass back no parent
3921 pVolumeCB = AFSGlobalRoot;
3924 // Init our name array
3927 pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
3929 if( pNameArray == NULL)
3932 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3933 AFS_TRACE_LEVEL_VERBOSE,
3934 "AFSParseName (%p) Failed to initialize name array\n",
3937 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3941 // Add back in the 'share' portion of the name since we will parse it out on return
3944 if( uniRemainingPath.Buffer != NULL)
3948 // This routine strips off the leading slash so add it back in
3951 uniRemainingPath.Buffer--;
3952 uniRemainingPath.Length += sizeof( WCHAR);
3953 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3955 if( uniRemainingPath.Length > sizeof( WCHAR))
3958 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3962 // And the cell name
3965 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3966 uniRemainingPath.Length += uniComponentName.Length;
3967 uniRemainingPath.MaximumLength += uniComponentName.Length;
3972 uniRemainingPath = uniComponentName;
3976 // And the leading slash again ...
3979 uniRemainingPath.Buffer--;
3980 uniRemainingPath.Length += sizeof( WCHAR);
3981 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3984 // Pass back the parent being the volume root
3987 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3991 // Return the remaining portion as the file name
3994 *FileName = uniRemainingPath;
3996 *ParsedFileName = uniRemainingPath;
3998 *NameArray = pNameArray;
4000 *VolumeCB = pVolumeCB;
4003 // Increment our reference on the volume
4006 lCount = AFSVolumeIncrement( pVolumeCB,
4007 AFS_VOLUME_REFERENCE_PARSE_NAME);
4009 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4010 AFS_TRACE_LEVEL_VERBOSE,
4011 "AFSParseName Increment2 count on global volume %p Cnt %d\n",
4017 if( NT_SUCCESS( ntStatus))
4020 if( *ParentDirectoryCB != NULL)
4023 lCount = InterlockedIncrement( &(*ParentDirectoryCB)->DirOpenReferenceCount);
4025 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4026 AFS_TRACE_LEVEL_VERBOSE,
4027 "AFSParseName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4028 &(*ParentDirectoryCB)->NameInformation.FileName,
4029 (*ParentDirectoryCB),
4035 if( *VolumeCB != NULL)
4037 ASSERT( (*VolumeCB)->VolumeReferenceCount > 0);
4040 if( ntStatus != STATUS_SUCCESS)
4043 if( pNameArray != NULL)
4046 AFSFreeNameArray( pNameArray);
4055 AFSCheckCellName( IN GUID *AuthGroup,
4056 IN UNICODE_STRING *CellName,
4057 OUT AFSDirectoryCB **ShareDirEntry)
4060 NTSTATUS ntStatus = STATUS_SUCCESS;
4061 UNICODE_STRING uniName;
4062 AFSDirEnumEntry *pDirEnumEntry = NULL;
4063 AFSDirHdr *pDirHdr = &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr;
4064 AFSDirectoryCB *pDirNode = NULL;
4065 UNICODE_STRING uniDirName, uniTargetName;
4066 AFSVolumeCB *pVolumeCB = NULL;
4073 // Look for some default names we will not handle
4076 RtlInitUnicodeString( &uniName,
4079 if( RtlCompareUnicodeString( &uniName,
4084 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4087 RtlInitUnicodeString( &uniName,
4090 if( RtlCompareUnicodeString( &uniName,
4095 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4098 RtlInitUnicodeString( &uniName,
4101 if( RtlCompareUnicodeString( &uniName,
4106 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4109 RtlInitUnicodeString( &uniName,
4112 if( RtlCompareUnicodeString( &uniName,
4117 try_return( ntStatus = STATUS_NO_SUCH_FILE);
4121 // OK, ask the CM about this component name
4124 ntStatus = AFSEvaluateTargetByName( AuthGroup,
4125 &AFSGlobalRoot->ObjectInformation,
4130 if( !NT_SUCCESS( ntStatus))
4133 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4134 AFS_TRACE_LEVEL_WARNING,
4135 "AFSCheckCellName entry %wZ does not exist parent FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4137 AFSGlobalRoot->ObjectInformation.FileId.Cell,
4138 AFSGlobalRoot->ObjectInformation.FileId.Volume,
4139 AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4140 AFSGlobalRoot->ObjectInformation.FileId.Unique,
4143 try_return( ntStatus);
4147 // OK, we have a dir enum entry back so add it to the root node
4150 uniDirName = *CellName;
4152 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
4153 uniTargetName.MaximumLength = uniTargetName.Length;
4154 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
4157 // Is this entry a root volume entry?
4160 if( pDirEnumEntry->FileId.Cell != AFSGlobalRoot->ObjectInformation.FileId.Cell ||
4161 pDirEnumEntry->FileId.Volume != AFSGlobalRoot->ObjectInformation.FileId.Volume)
4165 // Build the root volume entry
4168 ntStatus = AFSBuildRootVolume( AuthGroup,
4169 &pDirEnumEntry->FileId,
4173 // On success returns with a volume reference count held
4176 if( !NT_SUCCESS( ntStatus))
4178 try_return( ntStatus);
4181 *ShareDirEntry = pVolumeCB->DirectoryCB;
4183 lCount = InterlockedIncrement( &pVolumeCB->DirectoryCB->DirOpenReferenceCount);
4185 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4186 AFS_TRACE_LEVEL_VERBOSE,
4187 "AFSCheckCellName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4188 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4189 pVolumeCB->DirectoryCB,
4193 lCount = AFSVolumeDecrement( pVolumeCB,
4194 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4196 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4197 AFS_TRACE_LEVEL_VERBOSE,
4198 "AFSCheckCellName Decrement count on volume %p Cnt %d\n",
4205 lCount = InterlockedIncrement( &pDirHdr->ContentIndex);
4207 pDirNode = AFSInitDirEntry( &AFSGlobalRoot->ObjectInformation,
4213 if( pDirNode == NULL)
4216 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4220 // Init the short name if we have one
4223 if( pDirEnumEntry->ShortNameLength > 0)
4226 pDirNode->NameInformation.ShortNameLength = pDirEnumEntry->ShortNameLength;
4228 RtlCopyMemory( pDirNode->NameInformation.ShortName,
4229 pDirEnumEntry->ShortName,
4230 pDirNode->NameInformation.ShortNameLength);
4233 AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4237 // Insert the node into the name tree
4240 ASSERT( ExIsResourceAcquiredExclusiveLite( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock));
4242 if( pDirHdr->CaseSensitiveTreeHead == NULL)
4245 pDirHdr->CaseSensitiveTreeHead = pDirNode;
4250 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( pDirHdr->CaseSensitiveTreeHead,
4254 AFSDeleteDirEntry( &AFSGlobalRoot->ObjectInformation,
4257 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4259 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4263 ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
4265 if( pDirHdr->CaseInsensitiveTreeHead == NULL)
4268 pDirHdr->CaseInsensitiveTreeHead = pDirNode;
4270 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
4275 AFSInsertCaseInsensitiveDirEntry( pDirHdr->CaseInsensitiveTreeHead,
4279 if( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead == NULL)
4282 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead = pDirNode;
4287 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
4289 pDirNode->ListEntry.bLink = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail;
4292 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail = pDirNode;
4294 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
4296 lCount = InterlockedIncrement( &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeCount);
4298 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
4299 AFS_TRACE_LEVEL_VERBOSE,
4300 "AFSCheckCellName Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
4301 &pDirNode->NameInformation.FileName,
4303 AFSGlobalRoot->ObjectInformation.FileId.Cell,
4304 AFSGlobalRoot->ObjectInformation.FileId.Volume,
4305 AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4306 AFSGlobalRoot->ObjectInformation.FileId.Unique);
4308 lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
4310 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4311 AFS_TRACE_LEVEL_VERBOSE,
4312 "AFSCheckCellName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
4313 &pDirNode->NameInformation.FileName,
4318 AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4321 // Pass back the dir node
4324 *ShareDirEntry = pDirNode;
4329 if( pDirEnumEntry != NULL)
4332 AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_31_TAG);
4340 AFSBuildMountPointTarget( IN GUID *AuthGroup,
4341 IN AFSDirectoryCB *DirectoryCB,
4342 OUT AFSVolumeCB **TargetVolumeCB)
4345 NTSTATUS ntStatus = STATUS_SUCCESS;
4346 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4347 AFSDirEnumEntry *pDirEntry = NULL;
4348 ULONGLONG ullIndex = 0;
4349 AFSVolumeCB *pVolumeCB = NULL;
4350 AFSFileID stTargetFileID;
4352 BOOLEAN bReleaseVolumeLock = FALSE;
4358 // Loop on each entry, building the chain until we encounter the final target
4361 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4362 AFS_TRACE_LEVEL_VERBOSE_2,
4363 "AFSBuildMountPointTarget Building target directory for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4364 &DirectoryCB->NameInformation.FileName,
4365 DirectoryCB->ObjectInformation->FileId.Cell,
4366 DirectoryCB->ObjectInformation->FileId.Volume,
4367 DirectoryCB->ObjectInformation->FileId.Vnode,
4368 DirectoryCB->ObjectInformation->FileId.Unique);
4371 // Do we need to evaluate the node?
4374 //if( DirectoryCB->ObjectInformation->TargetFileId.Vnode == 0 &&
4375 // DirectoryCB->ObjectInformation->TargetFileId.Unique == 0)
4379 // Go evaluate the current target to get the target fid
4382 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4383 AFS_TRACE_LEVEL_VERBOSE_2,
4384 "AFSBuildMountPointTarget Evaluating target %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4385 &DirectoryCB->NameInformation.FileName,
4386 DirectoryCB->ObjectInformation->FileId.Cell,
4387 DirectoryCB->ObjectInformation->FileId.Volume,
4388 DirectoryCB->ObjectInformation->FileId.Vnode,
4389 DirectoryCB->ObjectInformation->FileId.Unique);
4391 ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
4396 if( !NT_SUCCESS( ntStatus))
4399 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4400 AFS_TRACE_LEVEL_ERROR,
4401 "AFSBuildMountPointTarget Failed to evaluate target %wZ Status %08lX\n",
4402 &DirectoryCB->NameInformation.FileName,
4404 try_return( ntStatus);
4407 if( pDirEntry->TargetFileId.Vnode == 0 &&
4408 pDirEntry->TargetFileId.Unique == 0)
4411 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4412 AFS_TRACE_LEVEL_ERROR,
4413 "AFSBuildMountPointTarget Target %wZ FID %08lX-%08lX-%08lX-%08lX service returned zero FID\n",
4414 &DirectoryCB->NameInformation.FileName,
4415 DirectoryCB->ObjectInformation->FileId.Cell,
4416 DirectoryCB->ObjectInformation->FileId.Volume,
4417 DirectoryCB->ObjectInformation->FileId.Vnode,
4418 DirectoryCB->ObjectInformation->FileId.Unique);
4420 try_return( ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED);
4423 AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
4426 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
4427 &DirectoryCB->Flags,
4428 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4429 (USHORT)pDirEntry->TargetNameLength);
4431 if( !NT_SUCCESS( ntStatus))
4434 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4436 try_return( ntStatus);
4439 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4441 DirectoryCB->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
4444 stTargetFileID = DirectoryCB->ObjectInformation->TargetFileId;
4447 // Try to locate this FID. First the volume then the
4451 ullIndex = AFSCreateHighIndex( &stTargetFileID);
4453 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4454 AFS_TRACE_LEVEL_VERBOSE,
4455 "AFSBuildMountPointTarget Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4456 &pDevExt->Specific.RDR.VolumeTreeLock,
4457 PsGetCurrentThread());
4459 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4462 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4463 AFS_TRACE_LEVEL_VERBOSE_2,
4464 "AFSBuildMountPointTarget Locating volume for target %I64X\n",
4467 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4469 (AFSBTreeEntry **)&pVolumeCB);
4472 // We can be processing a request for a target that is on a volume
4473 // we have never seen before.
4476 if( pVolumeCB == NULL)
4480 // Locking is held correctly in init routine
4483 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4486 // Go init the root of the volume
4489 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4490 AFS_TRACE_LEVEL_VERBOSE_2,
4491 "AFSBuildMountPointTarget Initializing root for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4492 &DirectoryCB->NameInformation.FileName,
4493 DirectoryCB->ObjectInformation->FileId.Cell,
4494 DirectoryCB->ObjectInformation->FileId.Volume,
4495 DirectoryCB->ObjectInformation->FileId.Vnode,
4496 DirectoryCB->ObjectInformation->FileId.Unique);
4498 ntStatus = AFSInitVolume( AuthGroup,
4500 AFS_VOLUME_REFERENCE_MOUNTPT,
4503 if( !NT_SUCCESS( ntStatus))
4506 try_return( ntStatus);
4510 // pVolumeCB->VolumeLock held exclusive and
4511 // pVolumeCB->VolumeReferenceCount has been incremented
4512 // pVolumeCB->RootFcb == NULL
4515 bReleaseVolumeLock = TRUE;
4521 // AFSInitVolume returns with a VolumeReferenceCount
4522 // obtain one to match
4525 lCount = AFSVolumeIncrement( pVolumeCB,
4526 AFS_VOLUME_REFERENCE_MOUNTPT);
4528 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4529 AFS_TRACE_LEVEL_VERBOSE,
4530 "AFSBuildMountPointTarget Increment count on volume %p Cnt %d\n",
4534 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4537 if( pVolumeCB->RootFcb == NULL)
4540 if ( bReleaseVolumeLock == FALSE)
4543 AFSAcquireExcl( pVolumeCB->VolumeLock,
4546 bReleaseVolumeLock = TRUE;
4550 // Initialize the root fcb for this volume
4553 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4556 if( !NT_SUCCESS( ntStatus))
4559 lCount = AFSVolumeDecrement( pVolumeCB,
4560 AFS_VOLUME_REFERENCE_MOUNTPT);
4562 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4563 AFS_TRACE_LEVEL_VERBOSE,
4564 "AFSBuildMountPoint Decrement count on volume %p Cnt %d\n",
4568 AFSReleaseResource( pVolumeCB->VolumeLock);
4570 try_return( ntStatus);
4574 // Drop the lock acquired above
4577 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4580 if ( bReleaseVolumeLock == TRUE)
4583 AFSReleaseResource( pVolumeCB->VolumeLock);
4586 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4587 AFS_TRACE_LEVEL_VERBOSE_2,
4588 "AFSBuildMountPointTarget Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4589 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4590 pVolumeCB->ObjectInformation.FileId.Cell,
4591 pVolumeCB->ObjectInformation.FileId.Volume,
4592 pVolumeCB->ObjectInformation.FileId.Vnode,
4593 pVolumeCB->ObjectInformation.FileId.Unique);
4595 *TargetVolumeCB = pVolumeCB;
4602 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
4610 AFSBuildRootVolume( IN GUID *AuthGroup,
4611 IN AFSFileID *FileId,
4612 OUT AFSVolumeCB **TargetVolumeCB)
4615 NTSTATUS ntStatus = STATUS_SUCCESS;
4616 AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4617 ULONGLONG ullIndex = 0;
4618 AFSVolumeCB *pVolumeCB = NULL;
4620 BOOLEAN bReleaseVolumeLock = FALSE;
4625 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4626 AFS_TRACE_LEVEL_VERBOSE_2,
4627 "AFSBuildRootVolume Building target volume for FID %08lX-%08lX-%08lX-%08lX\n",
4633 ullIndex = AFSCreateHighIndex( FileId);
4635 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4636 AFS_TRACE_LEVEL_VERBOSE,
4637 "AFSBuildRootVolume Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4638 &pDevExt->Specific.RDR.VolumeTreeLock,
4639 PsGetCurrentThread());
4641 AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4644 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4645 AFS_TRACE_LEVEL_VERBOSE_2,
4646 "AFSBuildRootVolume Locating volume for target %I64X\n",
4649 ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4651 (AFSBTreeEntry **)&pVolumeCB);
4654 // We can be processing a request for a target that is on a volume
4655 // we have never seen before.
4658 if( pVolumeCB == NULL)
4662 // Locking is held correctly in init routine
4665 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4668 // Go init the root of the volume
4671 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4672 AFS_TRACE_LEVEL_VERBOSE_2,
4673 "AFSBuildRootVolume Initializing root for FID %08lX-%08lX-%08lX-%08lX\n",
4679 ntStatus = AFSInitVolume( AuthGroup,
4681 AFS_VOLUME_REFERENCE_BUILD_ROOT,
4684 if( !NT_SUCCESS( ntStatus))
4687 try_return( ntStatus);
4691 // pVolumeCB->VolumeLock is held exclusive
4692 // pVolumeCB->VolumeReferenceCount has been incremented
4693 // pVolumeCB->RootFcb == NULL
4696 bReleaseVolumeLock = TRUE;
4702 // AFSInitVolume returns with a VolumeReferenceCount
4703 // obtain one to match
4706 lCount = AFSVolumeIncrement( pVolumeCB,
4707 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4709 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4710 AFS_TRACE_LEVEL_VERBOSE,
4711 "AFSBuildRootVolume Increment count on volume %p Cnt %d\n",
4715 AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4719 if( pVolumeCB->RootFcb == NULL)
4722 if ( bReleaseVolumeLock == FALSE)
4725 AFSAcquireExcl( pVolumeCB->VolumeLock,
4728 bReleaseVolumeLock = TRUE;
4732 // Initialize the root fcb for this volume
4735 ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4738 if( !NT_SUCCESS( ntStatus))
4741 lCount = AFSVolumeDecrement( pVolumeCB,
4742 AFS_VOLUME_REFERENCE_BUILD_ROOT);
4744 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4745 AFS_TRACE_LEVEL_VERBOSE,
4746 "AFSBuildRootVolume Decrement count on volume %p Cnt %d\n",
4750 AFSReleaseResource( pVolumeCB->VolumeLock);
4752 try_return( ntStatus);
4756 // Drop the lock acquired above
4759 AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4762 if ( bReleaseVolumeLock == TRUE)
4765 AFSReleaseResource( pVolumeCB->VolumeLock);
4768 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4769 AFS_TRACE_LEVEL_VERBOSE_2,
4770 "AFSBuildRootVolume Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4771 &pVolumeCB->DirectoryCB->NameInformation.FileName,
4772 pVolumeCB->ObjectInformation.FileId.Cell,
4773 pVolumeCB->ObjectInformation.FileId.Volume,
4774 pVolumeCB->ObjectInformation.FileId.Vnode,
4775 pVolumeCB->ObjectInformation.FileId.Unique);
4777 *TargetVolumeCB = pVolumeCB;
4788 AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
4789 IN PFILE_OBJECT FileObject,
4790 IN UNICODE_STRING *RemainingPath,
4794 NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
4795 UNICODE_STRING uniReparseName;
4796 UNICODE_STRING uniMUPDeviceName;
4797 UNICODE_STRING uniIOMgrDeviceName;
4798 AFSDirEnumEntry *pDirEntry = NULL;
4804 // Build up the name to reparse
4807 RtlInitUnicodeString( &uniMUPDeviceName,
4810 RtlInitUnicodeString( &uniIOMgrDeviceName,
4813 uniReparseName.Length = 0;
4814 uniReparseName.Buffer = NULL;
4817 // Be sure we have a target name
4820 if( DirEntry->NameInformation.TargetName.Length == 0)
4823 ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
4828 if( !NT_SUCCESS( ntStatus) ||
4829 pDirEntry->TargetNameLength == 0)
4832 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4833 AFS_TRACE_LEVEL_ERROR,
4834 "AFSProcessDFSLink EvaluateTargetByID failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4835 &DirEntry->NameInformation.FileName,
4836 DirEntry->ObjectInformation->FileId.Cell,
4837 DirEntry->ObjectInformation->FileId.Volume,
4838 DirEntry->ObjectInformation->FileId.Vnode,
4839 DirEntry->ObjectInformation->FileId.Unique,
4842 if( NT_SUCCESS( ntStatus))
4845 ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
4848 try_return( ntStatus);
4852 // Update the target name
4855 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
4858 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
4860 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4861 (USHORT)pDirEntry->TargetNameLength);
4863 if( !NT_SUCCESS( ntStatus))
4866 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4867 AFS_TRACE_LEVEL_ERROR,
4868 "AFSProcessDFSLink UpdateTargetName failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4869 &DirEntry->NameInformation.FileName,
4870 DirEntry->ObjectInformation->FileId.Cell,
4871 DirEntry->ObjectInformation->FileId.Volume,
4872 DirEntry->ObjectInformation->FileId.Vnode,
4873 DirEntry->ObjectInformation->FileId.Unique,
4876 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4878 try_return( ntStatus);
4881 AFSConvertToShared( &DirEntry->NonPaged->Lock);
4885 AFSAcquireShared( &DirEntry->NonPaged->Lock,
4889 uniReparseName.MaximumLength = uniMUPDeviceName.Length +
4891 DirEntry->NameInformation.TargetName.Length +
4894 if( RemainingPath != NULL &&
4895 RemainingPath->Length > 0)
4898 uniReparseName.MaximumLength += RemainingPath->Length;
4902 // Allocate the reparse buffer
4905 uniReparseName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4906 uniReparseName.MaximumLength,
4907 AFS_REPARSE_NAME_TAG);
4909 if( uniReparseName.Buffer == NULL)
4912 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4913 AFS_TRACE_LEVEL_ERROR,
4914 "AFSProcessDFSLink uniReparseName.Buffer == NULL Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4915 &DirEntry->NameInformation.FileName,
4916 DirEntry->ObjectInformation->FileId.Cell,
4917 DirEntry->ObjectInformation->FileId.Volume,
4918 DirEntry->ObjectInformation->FileId.Vnode,
4919 DirEntry->ObjectInformation->FileId.Unique,
4920 STATUS_INSUFFICIENT_RESOURCES);
4922 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4924 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4928 // Start building the name
4931 if ( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\' &&
4932 DirEntry->NameInformation.TargetName.Buffer[ 1] == L':')
4935 RtlCopyMemory( uniReparseName.Buffer,
4936 uniIOMgrDeviceName.Buffer,
4937 uniIOMgrDeviceName.Length);
4939 uniReparseName.Length = uniIOMgrDeviceName.Length;
4944 RtlCopyMemory( uniReparseName.Buffer,
4945 uniMUPDeviceName.Buffer,
4946 uniMUPDeviceName.Length);
4948 uniReparseName.Length = uniMUPDeviceName.Length;
4950 if( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\')
4953 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
4955 uniReparseName.Length += sizeof( WCHAR);
4959 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
4960 DirEntry->NameInformation.TargetName.Buffer,
4961 DirEntry->NameInformation.TargetName.Length);
4963 uniReparseName.Length += DirEntry->NameInformation.TargetName.Length;
4965 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4967 if( RemainingPath != NULL &&
4968 RemainingPath->Length > 0)
4971 if( uniReparseName.Buffer[ (uniReparseName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
4972 RemainingPath->Buffer[ 0] != L'\\')
4975 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
4977 uniReparseName.Length += sizeof( WCHAR);
4980 RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
4981 RemainingPath->Buffer,
4982 RemainingPath->Length);
4984 uniReparseName.Length += RemainingPath->Length;
4988 // Update the name in the file object
4991 if( FileObject->FileName.Buffer != NULL)
4994 AFSExFreePoolWithTag( FileObject->FileName.Buffer, 0);
4997 FileObject->FileName = uniReparseName;
4999 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
5000 AFS_TRACE_LEVEL_VERBOSE,
5001 "AFSProcessDFSLink Reparsing access to Fcb %wZ FID %08lX-%08lX-%08lX-%08lX to %wZ\n",
5002 &DirEntry->NameInformation.FileName,
5003 DirEntry->ObjectInformation->FileId.Cell,
5004 DirEntry->ObjectInformation->FileId.Volume,
5005 DirEntry->ObjectInformation->FileId.Vnode,
5006 DirEntry->ObjectInformation->FileId.Unique,
5010 // Return status reparse ...
5013 ntStatus = STATUS_REPARSE;
5020 AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);