45abe94dc67a8a3cbaae1ce1c3d0b705251f48a9
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSNameSupport.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
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
13  *   notice,
14  *   this list of conditions and the following disclaimer in the
15  *   documentation
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.
21  *
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.
33  */
34
35 //
36 // File: AFSNameSupport.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 //
42 // AFSLocateNameEntry
43 //
44 // On entry, *VolumeCB must have a held ReferenceCount provided by
45 // the caller which will be released.  On successful exit, *VolumeCB
46 // will be assigned the new current volume with a held ReferenceCount.
47 //
48 // On entry, *ParentDirectoryCB must have a held DirOpenReferenceCount
49 // provided by the caller.
50 //
51
52 NTSTATUS
53 AFSLocateNameEntry( IN GUID *AuthGroup,
54                     IN PFILE_OBJECT FileObject,
55                     IN UNICODE_STRING *RootPathName,
56                     IN UNICODE_STRING *ParsedPathName,
57                     IN AFSNameArrayHdr *NameArray,
58                     IN ULONG Flags,
59                     IN OUT AFSVolumeCB **VolumeCB,
60                     IN OUT LONG *pVolumeReferenceReason,
61                     IN OUT AFSDirectoryCB **ParentDirectoryCB,
62                     OUT AFSDirectoryCB **DirectoryCB,
63                     OUT PUNICODE_STRING ComponentName)
64 {
65
66     NTSTATUS          ntStatus = STATUS_SUCCESS;
67     UNICODE_STRING    uniPathName, uniComponentName, uniRemainingPath, uniSearchName, uniFullPathName;
68     ULONG             ulCRC = 0;
69     AFSDirectoryCB   *pDirEntry = NULL, *pParentDirEntry = NULL;
70     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
71     UNICODE_STRING    uniSysName;
72     ULONG             ulSubstituteIndex = 0;
73     BOOLEAN           bSubstituteName = FALSE;
74     AFSNameArrayHdr  *pNameArray = NameArray;
75     BOOLEAN           bAllocatedSymLinkBuffer = FALSE;
76     UNICODE_STRING    uniRelativeName, uniNoOpName;
77     AFSObjectInfoCB  *pCurrentObject = NULL;
78     AFSObjectInfoCB  *pParentObjectInfo = NULL;
79     AFSVolumeCB      *pCurrentVolume = *VolumeCB;
80     AFSVolumeCB      *pTargetVolume = NULL;
81     BOOLEAN           bReleaseCurrentVolume = TRUE;
82     LONG              VolumeReferenceReason = *pVolumeReferenceReason;
83     BOOLEAN           bSubstitutedName = FALSE;
84     LONG              lCount;
85
86     __Enter
87     {
88
89         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
90                       AFS_TRACE_LEVEL_VERBOSE_2,
91                       "AFSLocateNameEntry (FO: %p) Processing full name %wZ\n",
92                       FileObject,
93                       RootPathName);
94
95         RtlInitUnicodeString( &uniSysName,
96                               L"*@SYS");
97
98         RtlInitUnicodeString( &uniRelativeName,
99                               L"..");
100
101         RtlInitUnicodeString( &uniNoOpName,
102                               L".");
103
104         //
105         // Cleanup some parameters
106         //
107
108         if( ComponentName != NULL)
109         {
110
111             ComponentName->Length = 0;
112             ComponentName->MaximumLength = 0;
113             ComponentName->Buffer = NULL;
114         }
115
116         //
117         // We will parse through the filename, locating the directory nodes until we encounter a cache miss
118         // Starting at the root node
119         //
120
121         pParentDirEntry = NULL;
122
123         pDirEntry = *ParentDirectoryCB;
124
125         uniPathName = *ParsedPathName;
126
127         uniFullPathName = *RootPathName;
128
129         uniComponentName.Length = uniComponentName.MaximumLength = 0;
130         uniComponentName.Buffer = NULL;
131
132         uniRemainingPath.Length = uniRemainingPath.MaximumLength = 0;
133         uniRemainingPath.Buffer = NULL;
134
135         uniSearchName.Length = uniSearchName.MaximumLength = 0;
136         uniSearchName.Buffer = NULL;
137
138         while( TRUE)
139         {
140
141             ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
142
143             ASSERT( pDirEntry->DirOpenReferenceCount > 0);
144
145             //
146             // Check our total link count for this name array
147             //
148
149             if( pNameArray->LinkCount >= (LONG)pDevExt->Specific.RDR.MaxLinkCount)
150             {
151
152                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
153             }
154
155             pCurrentObject = pDirEntry->ObjectInformation;
156
157             KeQueryTickCount( &pCurrentObject->LastAccessCount);
158
159             //
160             // Check that the directory entry is not deleted or pending delete
161             //
162
163             if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
164             {
165
166                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
167                               AFS_TRACE_LEVEL_ERROR,
168                               "AFSLocateNameEntry (FO: %p) Deleted parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
169                               FileObject,
170                               &pDirEntry->NameInformation.FileName,
171                               pCurrentObject->FileId.Cell,
172                               pCurrentObject->FileId.Volume,
173                               pCurrentObject->FileId.Vnode,
174                               pCurrentObject->FileId.Unique,
175                               STATUS_FILE_DELETED);
176
177                 try_return( ntStatus = STATUS_FILE_DELETED);
178             }
179
180             if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
181             {
182
183                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
184                               AFS_TRACE_LEVEL_ERROR,
185                               "AFSLocateNameEntry (FO: %p) Delete pending on %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
186                               FileObject,
187                               &pDirEntry->NameInformation.FileName,
188                               pCurrentObject->FileId.Cell,
189                               pCurrentObject->FileId.Volume,
190                               pCurrentObject->FileId.Vnode,
191                               pCurrentObject->FileId.Unique,
192                               STATUS_DELETE_PENDING);
193
194                 try_return( ntStatus = STATUS_DELETE_PENDING);
195             }
196
197             //
198             // Check if the directory requires verification
199             //
200
201             if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
202                 ( pCurrentObject->FileType != AFS_FILE_TYPE_DIRECTORY ||
203                   !AFSIsEnumerationInProcess( pCurrentObject)))
204             {
205
206                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
207                               AFS_TRACE_LEVEL_VERBOSE,
208                               "AFSLocateNameEntry (FO: %p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
209                               FileObject,
210                               &pDirEntry->NameInformation.FileName,
211                               pCurrentObject->FileId.Cell,
212                               pCurrentObject->FileId.Volume,
213                               pCurrentObject->FileId.Vnode,
214                               pCurrentObject->FileId.Unique);
215
216                 //
217                 // Directory TreeLock should be exclusively held
218                 //
219
220                 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
221                                 TRUE);
222
223                 ntStatus = AFSVerifyEntry( AuthGroup,
224                                            pDirEntry);
225
226                 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
227
228                 if( !NT_SUCCESS( ntStatus))
229                 {
230
231                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
232                                   AFS_TRACE_LEVEL_ERROR,
233                                   "AFSLocateNameEntry (FO: %p) Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
234                                   FileObject,
235                                   &pDirEntry->NameInformation.FileName,
236                                   pCurrentObject->FileId.Cell,
237                                   pCurrentObject->FileId.Volume,
238                                   pCurrentObject->FileId.Vnode,
239                                   pCurrentObject->FileId.Unique,
240                                   ntStatus);
241
242                     try_return( ntStatus);
243                 }
244             }
245
246             //
247             // Ensure the parent node has been evaluated, if not then go do it now
248             //
249
250             if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) ||
251                 pCurrentObject->FileType == AFS_FILE_TYPE_UNKNOWN)
252             {
253
254                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
255                               AFS_TRACE_LEVEL_VERBOSE,
256                               "AFSLocateNameEntry (FO: %p) Evaluating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
257                               FileObject,
258                               &pDirEntry->NameInformation.FileName,
259                               pCurrentObject->FileId.Cell,
260                               pCurrentObject->FileId.Volume,
261                               pCurrentObject->FileId.Vnode,
262                               pCurrentObject->FileId.Unique);
263
264                 ntStatus = AFSEvaluateNode( AuthGroup,
265                                             pDirEntry);
266
267                 if( !NT_SUCCESS( ntStatus))
268                 {
269
270                     if ( ntStatus == STATUS_NOT_A_DIRECTORY)
271                     {
272
273                         if ( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
274                         {
275
276                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
277                                           AFS_TRACE_LEVEL_ERROR,
278                                           "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT NULL Status %08lX\n",
279                                           FileObject,
280                                           &pDirEntry->NameInformation.FileName,
281                                           pCurrentObject->FileId.Cell,
282                                           pCurrentObject->FileId.Volume,
283                                           pCurrentObject->FileId.Vnode,
284                                           pCurrentObject->FileId.Unique,
285                                           ntStatus);
286                         }
287                         else
288                         {
289
290                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
291                                           AFS_TRACE_LEVEL_ERROR,
292                                           "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT %08lX-%08lX-%08lX-%08lX Status %08lX\n",
293                                           FileObject,
294                                           &pDirEntry->NameInformation.FileName,
295                                           pCurrentObject->FileId.Cell,
296                                           pCurrentObject->FileId.Volume,
297                                           pCurrentObject->FileId.Vnode,
298                                           pCurrentObject->FileId.Unique,
299                                           pCurrentObject->ParentFileId.Cell,
300                                           pCurrentObject->ParentFileId.Volume,
301                                           pCurrentObject->ParentFileId.Vnode,
302                                           pCurrentObject->ParentFileId.Unique,
303                                           ntStatus);
304                         }
305                     }
306                     else
307                     {
308                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
309                                       AFS_TRACE_LEVEL_ERROR,
310                                       "AFSLocateNameEntry (FO: %p) Failed to evaluate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
311                                       FileObject,
312                                       &pDirEntry->NameInformation.FileName,
313                                       pCurrentObject->FileId.Cell,
314                                       pCurrentObject->FileId.Volume,
315                                       pCurrentObject->FileId.Vnode,
316                                       pCurrentObject->FileId.Unique,
317                                       ntStatus);
318                     }
319
320                     try_return( ntStatus);
321                 }
322
323                 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
324             }
325
326             //
327             // If this is a mount point or symlink then go get the real directory node
328             //
329
330             switch( pCurrentObject->FileType)
331             {
332
333                 case AFS_FILE_TYPE_SYMLINK:
334                 {
335
336                     UNICODE_STRING uniTempName;
337                     WCHAR *pTmpBuffer = NULL;
338                     LONG lLinkCount = 0;
339
340                     //
341                     // Check if the flag is set to NOT evaluate a symlink
342                     // and we are done with the parsing
343                     //
344
345                     if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL) &&
346                         uniRemainingPath.Length == 0)
347                     {
348
349                         //
350                         // Pass back the directory entries
351                         //
352
353                         *ParentDirectoryCB = pParentDirEntry;
354
355                         *DirectoryCB = pDirEntry;
356
357                         *VolumeCB = pCurrentVolume;
358
359                         *RootPathName = uniFullPathName;
360
361                         try_return( ntStatus);
362                     }
363
364                     AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
365                                     TRUE);
366
367                     AFSAcquireExcl( &pDirEntry->NonPaged->Lock,
368                                     TRUE);
369
370                     if( pDirEntry->NameInformation.TargetName.Length == 0)
371                     {
372
373                         //
374                         // We'll reset the DV to ensure we validate the metadata content
375                         //
376
377                         pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
378
379                         SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
380
381                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
382                                       AFS_TRACE_LEVEL_VERBOSE,
383                                       "AFSLocateNameEntry (FO: %p) Verifying symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
384                                       FileObject,
385                                       &pDirEntry->NameInformation.FileName,
386                                       pCurrentObject->FileId.Cell,
387                                       pCurrentObject->FileId.Volume,
388                                       pCurrentObject->FileId.Vnode,
389                                       pCurrentObject->FileId.Unique);
390
391                         //
392                         // Directory TreeLock should be exclusively held
393                         //
394
395                         ntStatus = AFSVerifyEntry( AuthGroup,
396                                                    pDirEntry);
397
398                         AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
399
400                         if( !NT_SUCCESS( ntStatus))
401                         {
402
403                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
404                                           AFS_TRACE_LEVEL_ERROR,
405                                           "AFSLocateNameEntry (FO: %p) Failed to verify symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
406                                           FileObject,
407                                           &pDirEntry->NameInformation.FileName,
408                                           pCurrentObject->FileId.Cell,
409                                           pCurrentObject->FileId.Volume,
410                                           pCurrentObject->FileId.Vnode,
411                                           pCurrentObject->FileId.Unique,
412                                           ntStatus);
413
414                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
415
416                             try_return( ntStatus);
417                         }
418
419                         //
420                         // If the type changed then reprocess this entry
421                         //
422
423                         if( pCurrentObject->FileType != AFS_FILE_TYPE_SYMLINK)
424                         {
425
426                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
427
428                             continue;
429                         }
430                     }
431                     else
432                     {
433
434                         AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
435                     }
436
437                     //
438                     // If we were given a zero length target name then deny access to the entry
439                     //
440
441                     if( pDirEntry->NameInformation.TargetName.Length == 0)
442                     {
443
444                         ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
445
446                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
447                                       AFS_TRACE_LEVEL_ERROR,
448                                       "AFSLocateNameEntry (FO: %p) Failed to retrieve target name for symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
449                                       FileObject,
450                                       &pDirEntry->NameInformation.FileName,
451                                       pCurrentObject->FileId.Cell,
452                                       pCurrentObject->FileId.Volume,
453                                       pCurrentObject->FileId.Vnode,
454                                       pCurrentObject->FileId.Unique,
455                                       ntStatus);
456
457                         AFSReleaseResource( &pDirEntry->NonPaged->Lock);
458
459                         try_return( ntStatus);
460                     }
461
462                     if( AFSIsRelativeName( &pDirEntry->NameInformation.TargetName))
463                     {
464
465                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
466                                       AFS_TRACE_LEVEL_VERBOSE,
467                                       "AFSLocateNameEntry (FO: %p) Processing relative symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
468                                       FileObject,
469                                       &pDirEntry->NameInformation.TargetName,
470                                       &pDirEntry->NameInformation.FileName,
471                                       pCurrentObject->FileId.Cell,
472                                       pCurrentObject->FileId.Volume,
473                                       pCurrentObject->FileId.Vnode,
474                                       pCurrentObject->FileId.Unique);
475
476                         //
477                         // We'll substitute this name into the current process name
478                         // starting at where we sit in the path
479                         //
480
481                         uniTempName.Length = 0;
482                         uniTempName.MaximumLength = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer) +
483                                                                     pDirEntry->NameInformation.TargetName.Length +
484                                                                     sizeof( WCHAR) +
485                                                                     uniRemainingPath.Length;
486
487                         uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
488                                                                                 uniTempName.MaximumLength,
489                                                                                 AFS_NAME_BUFFER_ONE_TAG);
490
491                         if( uniTempName.Buffer == NULL)
492                         {
493
494                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
495
496                             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
497                         }
498
499                         //
500                         // We have so first copy in the portion up to the component
501                         // name
502                         //
503
504                         RtlCopyMemory( uniTempName.Buffer,
505                                        uniFullPathName.Buffer,
506                                        (ULONG)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer));
507
508                         uniTempName.Length = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer);
509
510                         if( bAllocatedSymLinkBuffer ||
511                             bSubstitutedName)
512                         {
513
514                             pTmpBuffer = uniFullPathName.Buffer;
515                         }
516
517                         bAllocatedSymLinkBuffer = TRUE;
518
519                         //
520                         // Have we parsed this name yet? Better have at least once ...
521                         //
522
523                         if( uniComponentName.Length == 0)
524                         {
525                             ASSERT( FALSE);
526                         }
527
528                         //
529                         // Copy in the target name ...
530                         //
531
532                         RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
533                                        pDirEntry->NameInformation.TargetName.Buffer,
534                                        pDirEntry->NameInformation.TargetName.Length);
535
536                         uniPathName.Buffer = &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)];
537
538                         uniPathName.Length += pDirEntry->NameInformation.TargetName.Length;
539                         uniPathName.MaximumLength = uniTempName.MaximumLength;
540
541                         uniTempName.Length += pDirEntry->NameInformation.TargetName.Length;
542
543                         //
544                         // And now any remaining portion of the name
545                         //
546
547                         if( uniRemainingPath.Length > 0)
548                         {
549
550                             if( uniRemainingPath.Buffer[ 0] != L'\\')
551                             {
552
553                                 uniRemainingPath.Buffer--;
554                                 uniRemainingPath.Length += sizeof( WCHAR);
555
556                                 uniPathName.Length += sizeof( WCHAR);
557                             }
558
559                             RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
560                                            uniRemainingPath.Buffer,
561                                            uniRemainingPath.Length);
562
563                             uniTempName.Length += uniRemainingPath.Length;
564                         }
565
566                         uniFullPathName = uniTempName;
567
568                         if( pTmpBuffer != NULL)
569                         {
570
571                             AFSExFreePoolWithTag( pTmpBuffer, 0);
572                         }
573
574                         AFSReleaseResource( &pDirEntry->NonPaged->Lock);
575
576                         //
577                         // Dereference the current entry ..
578                         //
579
580                         lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
581
582                         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
583                                       AFS_TRACE_LEVEL_VERBOSE,
584                                       "AFSLocateNameEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
585                                       &pDirEntry->NameInformation.FileName,
586                                       pDirEntry,
587                                       NULL,
588                                       lCount);
589
590                         ASSERT( lCount >= 0);
591
592                         //
593                         // OK, need to back up one entry for the correct parent since the current
594                         // entry we are on is the symlink itself
595                         //
596
597                         pDirEntry = AFSBackupEntry( pNameArray);
598
599                         //
600                         // Increment our reference on this dir entry
601                         //
602
603                         lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
604
605                         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
606                                       AFS_TRACE_LEVEL_VERBOSE,
607                                       "AFSLocateNameEntry Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
608                                       &pDirEntry->NameInformation.FileName,
609                                       pDirEntry,
610                                       NULL,
611                                       lCount);
612
613                         if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
614                         {
615
616                             pParentDirEntry = NULL;
617                         }
618                         else
619                         {
620
621                             pParentDirEntry = AFSGetParentEntry( pNameArray);
622
623                             ASSERT( pParentDirEntry != pDirEntry);
624                         }
625                     }
626                     else
627                     {
628
629                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
630                                       AFS_TRACE_LEVEL_VERBOSE,
631                                       "AFSLocateNameEntry (FO: %p) Processing absolute symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
632                                       FileObject,
633                                       &pDirEntry->NameInformation.TargetName,
634                                       &pDirEntry->NameInformation.FileName,
635                                       pCurrentObject->FileId.Cell,
636                                       pCurrentObject->FileId.Volume,
637                                       pCurrentObject->FileId.Vnode,
638                                       pCurrentObject->FileId.Unique);
639
640                         if ( !AFSIsAbsoluteAFSName( &pDirEntry->NameInformation.TargetName))
641                         {
642
643                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
644                                           AFS_TRACE_LEVEL_ERROR,
645                                           "AFSLocateNameEntry Name %wZ contains invalid server name\n",
646                                           &pDirEntry->NameInformation.TargetName);
647
648                             //
649                             // The correct response would be STATUS_OBJECT_PATH_INVALID
650                             // but that prevents cmd.exe from performing a recursive
651                             // directory enumeration when opening a directory entry
652                             // that represents a symlink to an invalid path is discovered.
653                             //
654
655                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
656
657                             try_return( ntStatus = STATUS_OBJECT_PATH_NOT_FOUND);
658                         }
659
660                         //
661                         // We'll substitute this name into the current process name
662                         // starting at where we sit in the path
663                         //
664
665                         uniTempName.Length = 0;
666                         uniTempName.MaximumLength = pDirEntry->NameInformation.TargetName.Length +
667                                                                     sizeof( WCHAR) +
668                                                                     uniRemainingPath.Length;
669
670                         uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
671                                                                                 uniTempName.MaximumLength,
672                                                                                 AFS_NAME_BUFFER_TWO_TAG);
673
674                         if( uniTempName.Buffer == NULL)
675                         {
676
677                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
678
679                             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
680                         }
681
682                         if( bAllocatedSymLinkBuffer ||
683                             bSubstitutedName)
684                         {
685
686                             pTmpBuffer = uniFullPathName.Buffer;
687                         }
688
689                         bAllocatedSymLinkBuffer = TRUE;
690
691                         //
692                         // Have we parsed this name yet? Better have at least once ...
693                         //
694
695                         if( uniComponentName.Length == 0)
696                         {
697                             ASSERT( FALSE);
698                         }
699
700                         //
701                         // Copy in the target name ...
702                         //
703
704                         RtlCopyMemory( uniTempName.Buffer,
705                                        &pDirEntry->NameInformation.TargetName.Buffer[ AFSMountRootName.Length/sizeof( WCHAR)],
706                                        pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length);
707
708                         uniTempName.Length = pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length;
709
710                         //
711                         // And now any remaining portion of the name
712                         //
713
714                         if( uniRemainingPath.Length > 0)
715                         {
716
717                             if( uniRemainingPath.Buffer[ 0] != L'\\')
718                             {
719
720                                 uniRemainingPath.Buffer--;
721                                 uniRemainingPath.Length += sizeof( WCHAR);
722                             }
723
724                             RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
725                                            uniRemainingPath.Buffer,
726                                            uniRemainingPath.Length);
727
728                             uniTempName.Length += uniRemainingPath.Length;
729                         }
730
731                         uniFullPathName = uniTempName;
732
733                         uniPathName = uniTempName;
734
735                         if( pTmpBuffer != NULL)
736                         {
737
738                             AFSExFreePoolWithTag( pTmpBuffer, 0);
739                         }
740
741                         AFSReleaseResource( &pDirEntry->NonPaged->Lock);
742
743                         //
744                         // If our current volume is not the global root then make it so ...
745                         //
746
747                         if( pCurrentVolume != AFSGlobalRoot)
748                         {
749
750                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
751                                           AFS_TRACE_LEVEL_VERBOSE,
752                                           "AFSLocateNameEntry (FO: %p) Current volume not global, resetting for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
753                                           FileObject,
754                                           &pDirEntry->NameInformation.FileName,
755                                           pCurrentObject->FileId.Cell,
756                                           pCurrentObject->FileId.Volume,
757                                           pCurrentObject->FileId.Vnode,
758                                           pCurrentObject->FileId.Unique);
759
760                             lCount = AFSVolumeDecrement( pCurrentVolume,
761                                                          VolumeReferenceReason);
762
763                             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
764                                           AFS_TRACE_LEVEL_VERBOSE,
765                                           "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
766                                           pCurrentVolume,
767                                           VolumeReferenceReason,
768                                           lCount);
769
770                             pCurrentVolume = AFSGlobalRoot;
771
772                             VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
773
774                             lCount = AFSVolumeIncrement( pCurrentVolume,
775                                                          VolumeReferenceReason);
776
777                             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
778                                           AFS_TRACE_LEVEL_VERBOSE,
779                                           "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
780                                           pCurrentVolume,
781                                           VolumeReferenceReason,
782                                           lCount);
783                         }
784
785                         //
786                         // Dereference our current dir entry
787                         //
788
789                         lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
790
791                         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
792                                       AFS_TRACE_LEVEL_VERBOSE,
793                                       "AFSLocateNameEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
794                                       &pDirEntry->NameInformation.FileName,
795                                       pDirEntry,
796                                       NULL,
797                                       lCount);
798
799                         ASSERT( lCount >= 0);
800
801                         pDirEntry = pCurrentVolume->DirectoryCB;
802
803                         //
804                         // Reference the new dir entry
805                         //
806
807                         lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
808
809                         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
810                                       AFS_TRACE_LEVEL_VERBOSE,
811                                       "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
812                                       &pDirEntry->NameInformation.FileName,
813                                       pDirEntry,
814                                       NULL,
815                                       lCount);
816
817                         //
818                         // Reset the name array
819                         // Persist the link count in the name array
820                         //
821
822                         lLinkCount = pNameArray->LinkCount;
823
824                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
825                                       AFS_TRACE_LEVEL_VERBOSE,
826                                       "AFSLocateNameEntry (FO: %p) Resetting name array for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
827                                       FileObject,
828                                       &pDirEntry->NameInformation.FileName,
829                                       pCurrentObject->FileId.Cell,
830                                       pCurrentObject->FileId.Volume,
831                                       pCurrentObject->FileId.Vnode,
832                                       pCurrentObject->FileId.Unique);
833
834                         AFSResetNameArray( pNameArray,
835                                            pDirEntry);
836
837                         pNameArray->LinkCount = lLinkCount;
838
839                         pParentDirEntry = NULL;
840                     }
841
842                     //
843                     // Increment our link count
844                     //
845
846                     lCount = InterlockedIncrement( &pNameArray->LinkCount);
847
848                     continue;
849                 }
850
851                 case AFS_FILE_TYPE_MOUNTPOINT:
852                 {
853
854                     //
855                     // Check if the flag is set to NOT evaluate a mount point
856                     // and we are done with the parsing
857                     //
858
859                     if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL) &&
860                         uniRemainingPath.Length == 0)
861                     {
862
863                         //
864                         // Pass back the directory entries
865                         //
866
867                         *ParentDirectoryCB = pParentDirEntry;
868
869                         *DirectoryCB = pDirEntry;
870
871                         *VolumeCB = pCurrentVolume;
872
873                         *RootPathName = uniFullPathName;
874
875                         try_return( ntStatus);
876                     }
877
878                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
879                                   AFS_TRACE_LEVEL_VERBOSE,
880                                   "AFSLocateNameEntry (FO: %p) Building MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
881                                   FileObject,
882                                   &pDirEntry->NameInformation.FileName,
883                                   pCurrentObject->FileId.Cell,
884                                   pCurrentObject->FileId.Volume,
885                                   pCurrentObject->FileId.Vnode,
886                                   pCurrentObject->FileId.Unique);
887
888                     //
889                     // Go retrieve the target entry for this node
890                     // Release the current volume cb entry since we would
891                     // have lock inversion in the following call
892                     // Also decrement the ref count on the volume
893                     //
894
895                     ntStatus = AFSBuildMountPointTarget( AuthGroup,
896                                                          pDirEntry,
897                                                          &pTargetVolume);
898
899                     if( !NT_SUCCESS( ntStatus))
900                     {
901
902                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
903                                       AFS_TRACE_LEVEL_ERROR,
904                                       "AFSLocateNameEntry (FO: %p) Failed to build MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
905                                       FileObject,
906                                       &pDirEntry->NameInformation.FileName,
907                                       pCurrentObject->FileId.Cell,
908                                       pCurrentObject->FileId.Volume,
909                                       pCurrentObject->FileId.Vnode,
910                                       pCurrentObject->FileId.Unique,
911                                       ntStatus);
912
913                         try_return( ntStatus);
914                     }
915
916                     ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
917
918                     lCount = AFSVolumeDecrement( pCurrentVolume,
919                                                  VolumeReferenceReason);
920
921                     AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
922                                   AFS_TRACE_LEVEL_VERBOSE,
923                                   "AFSLocateNameEntry Decrement2 count on volume %p Reason %u Cnt %d\n",
924                                   pCurrentVolume,
925                                   VolumeReferenceReason,
926                                   lCount);
927
928                     pCurrentVolume = pTargetVolume;
929
930                     pTargetVolume = NULL;
931
932                     ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
933
934                     VolumeReferenceReason = AFS_VOLUME_REFERENCE_MOUNTPT;
935
936                     //
937                     // We want to restart processing here on the new parent ...
938                     // Deref and ref count the entries
939                     //
940
941                     lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
942
943                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
944                                   AFS_TRACE_LEVEL_VERBOSE,
945                                   "AFSLocateNameEntry Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
946                                   &pDirEntry->NameInformation.FileName,
947                                   pDirEntry,
948                                   NULL,
949                                   lCount);
950
951                     ASSERT( lCount >= 0);
952
953                     pDirEntry = pCurrentVolume->DirectoryCB;
954
955                     lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
956
957                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
958                                   AFS_TRACE_LEVEL_VERBOSE,
959                                   "AFSLocateNameEntry Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
960                                   &pDirEntry->NameInformation.FileName,
961                                   pDirEntry,
962                                   NULL,
963                                   lCount);
964
965                     //
966                     // The name array stores both the mount point and the target.
967                     // Insert the target.
968                     //
969
970                     AFSInsertNextElement( pNameArray,
971                                           pDirEntry);
972
973                     pParentDirEntry = NULL;
974
975                     //
976                     // Increment our link count
977                     //
978
979                     lCount = InterlockedIncrement( &pNameArray->LinkCount);
980
981                     continue;
982                 }
983
984                 case AFS_FILE_TYPE_DFSLINK:
985                 {
986
987                     if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL))
988                     {
989
990                         //
991                         // Pass back the directory entries
992                         //
993
994                         *ParentDirectoryCB = pParentDirEntry;
995
996                         *DirectoryCB = pDirEntry;
997
998                         *VolumeCB = pCurrentVolume;
999
1000                         *RootPathName = uniFullPathName;
1001
1002                         try_return( ntStatus);
1003                     }
1004
1005                     //
1006                     // This is a DFS link so we need to update the file name and return STATUS_REPARSE to the
1007                     // system for it to reevaluate it
1008                     //
1009
1010                     if( FileObject != NULL)
1011                     {
1012
1013                         ntStatus = AFSProcessDFSLink( pDirEntry,
1014                                                       FileObject,
1015                                                       &uniRemainingPath,
1016                                                       AuthGroup);
1017                     }
1018                     else
1019                     {
1020
1021                         //
1022                         // This is where we have been re-entered from an NP evaluation call via the BuildBranch()
1023                         // routine.
1024                         //
1025
1026                         ntStatus = STATUS_INVALID_PARAMETER;
1027                     }
1028
1029                     if( ntStatus != STATUS_SUCCESS &&
1030                         ntStatus != STATUS_REPARSE)
1031                     {
1032
1033                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1034                                       AFS_TRACE_LEVEL_ERROR,
1035                                       "AFSLocateNameEntry (FO: %p) Failed to process DFSLink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1036                                       FileObject,
1037                                       &pDirEntry->NameInformation.FileName,
1038                                       pCurrentObject->FileId.Cell,
1039                                       pCurrentObject->FileId.Volume,
1040                                       pCurrentObject->FileId.Vnode,
1041                                       pCurrentObject->FileId.Unique,
1042                                       ntStatus);
1043                     }
1044
1045                     try_return( ntStatus);
1046                 }
1047
1048                 case AFS_FILE_TYPE_UNKNOWN:
1049                 case AFS_FILE_TYPE_INVALID:
1050                 {
1051
1052                     //
1053                     // Something was not processed ...
1054                     //
1055
1056                     try_return( ntStatus = STATUS_ACCESS_DENIED);
1057                 }
1058
1059             }   /* end of switch */
1060
1061             //
1062             // If the parent is not initialized then do it now
1063             //
1064
1065             if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1066                 !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1067             {
1068
1069                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1070                               AFS_TRACE_LEVEL_VERBOSE,
1071                               "AFSLocateNameEntry (FO: %p) Enumerating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1072                               FileObject,
1073                               &pDirEntry->NameInformation.FileName,
1074                               pCurrentObject->FileId.Cell,
1075                               pCurrentObject->FileId.Volume,
1076                               pCurrentObject->FileId.Vnode,
1077                               pCurrentObject->FileId.Unique);
1078
1079                 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1080                                 TRUE);
1081
1082                 if( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1083                 {
1084
1085                     ntStatus = AFSEnumerateDirectory( AuthGroup,
1086                                                       pCurrentObject,
1087                                                       TRUE);
1088
1089                     if( !NT_SUCCESS( ntStatus))
1090                     {
1091
1092                         AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1093
1094                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1095                                       AFS_TRACE_LEVEL_ERROR,
1096                                       "AFSLocateNameEntry (FO: %p) Failed to enumerate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1097                                       FileObject,
1098                                       &pDirEntry->NameInformation.FileName,
1099                                       pCurrentObject->FileId.Cell,
1100                                       pCurrentObject->FileId.Volume,
1101                                       pCurrentObject->FileId.Vnode,
1102                                       pCurrentObject->FileId.Unique,
1103                                       ntStatus);
1104
1105                         try_return( ntStatus);
1106                     }
1107
1108                     SetFlag( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1109                 }
1110
1111                 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1112             }
1113             else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1114             {
1115
1116                 if( uniPathName.Length > 0)
1117                 {
1118
1119                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1120                                   AFS_TRACE_LEVEL_ERROR,
1121                                   "AFSLocateNameEntry (FO: %p) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1122                                   FileObject,
1123                                   &pDirEntry->NameInformation.FileName,
1124                                   pCurrentObject->FileId.Cell,
1125                                   pCurrentObject->FileId.Volume,
1126                                   pCurrentObject->FileId.Vnode,
1127                                   pCurrentObject->FileId.Unique);
1128
1129                     // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1130                     // one of the components of the path is not a directory.  However, returning
1131                     // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1132                     // Instead IIS insists on treating the target file as if it is a directory containing
1133                     // a potential web.config file.  NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1134                     // AFS will follow suit.
1135
1136                     ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1137                 }
1138                 else
1139                 {
1140
1141                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1142                                   AFS_TRACE_LEVEL_VERBOSE,
1143                                   "AFSLocateNameEntry (FO: %p) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1144                                   FileObject,
1145                                   &pDirEntry->NameInformation.FileName,
1146                                   pCurrentObject->FileId.Cell,
1147                                   pCurrentObject->FileId.Volume,
1148                                   pCurrentObject->FileId.Vnode,
1149                                   pCurrentObject->FileId.Unique);
1150
1151                     //
1152                     // Pass back the directory entries
1153                     //
1154
1155                     *ParentDirectoryCB = pParentDirEntry;
1156
1157                     *DirectoryCB = pDirEntry;
1158
1159                     *VolumeCB = pCurrentVolume;
1160
1161                     *RootPathName = uniFullPathName;
1162                 }
1163
1164                 try_return( ntStatus);
1165             }
1166
1167             //
1168             // If we are at the end of the processing, set our returned information and get out
1169             //
1170
1171             if( uniPathName.Length == 0)
1172             {
1173
1174                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1175                               AFS_TRACE_LEVEL_VERBOSE,
1176                               "AFSLocateNameEntry (FO: %p) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1177                               FileObject,
1178                               &pDirEntry->NameInformation.FileName,
1179                               pCurrentObject->FileId.Cell,
1180                               pCurrentObject->FileId.Volume,
1181                               pCurrentObject->FileId.Vnode,
1182                               pCurrentObject->FileId.Unique);
1183
1184                 //
1185                 // Pass back the directory entries
1186                 //
1187
1188                 *ParentDirectoryCB = pParentDirEntry;
1189
1190                 *DirectoryCB = pDirEntry;
1191
1192                 *VolumeCB = pCurrentVolume;
1193
1194                 *RootPathName = uniFullPathName;
1195
1196                 try_return( ntStatus);
1197             }
1198
1199             //
1200             // We may have returned to the top of the while( TRUE)
1201             //
1202             if( bSubstituteName &&
1203                 uniSearchName.Buffer != NULL)
1204             {
1205
1206                 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1207
1208                 bSubstituteName = FALSE;
1209
1210                 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1211                 uniSearchName.Buffer = NULL;
1212             }
1213
1214             ulSubstituteIndex = 1;
1215
1216             ntStatus = STATUS_SUCCESS;
1217
1218             //
1219             // Get the next component name
1220             //
1221
1222             FsRtlDissectName( uniPathName,
1223                               &uniComponentName,
1224                               &uniRemainingPath);
1225
1226             //
1227             // Check for the . and .. in the path
1228             //
1229
1230             if( RtlCompareUnicodeString( &uniComponentName,
1231                                          &uniNoOpName,
1232                                          TRUE) == 0)
1233             {
1234
1235                 uniPathName = uniRemainingPath;
1236
1237                 continue;
1238             }
1239
1240             if( RtlCompareUnicodeString( &uniComponentName,
1241                                          &uniRelativeName,
1242                                          TRUE) == 0)
1243             {
1244
1245                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1246                               AFS_TRACE_LEVEL_VERBOSE,
1247                               "AFSLocateNameEntry (FO: %p) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1248                               FileObject,
1249                               &pDirEntry->NameInformation.FileName,
1250                               pCurrentObject->FileId.Cell,
1251                               pCurrentObject->FileId.Volume,
1252                               pCurrentObject->FileId.Vnode,
1253                               pCurrentObject->FileId.Unique);
1254
1255                 //
1256                 // Need to back up one entry in the name array
1257                 //
1258                 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1259
1260                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1261                               AFS_TRACE_LEVEL_VERBOSE,
1262                               "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1263                               &pDirEntry->NameInformation.FileName,
1264                               pDirEntry,
1265                               NULL,
1266                               lCount);
1267
1268                 ASSERT( lCount >= 0);
1269
1270                 pDirEntry = AFSBackupEntry( NameArray);
1271
1272                 if( pDirEntry == NULL)
1273                 {
1274
1275                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1276                                   AFS_TRACE_LEVEL_ERROR,
1277                                   "AFSLocateNameEntry AFSBackupEntry failed\n");
1278
1279                     try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1280                 }
1281
1282                 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1283
1284                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1285                               AFS_TRACE_LEVEL_VERBOSE,
1286                               "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1287                               &pDirEntry->NameInformation.FileName,
1288                               pDirEntry,
1289                               NULL,
1290                               lCount);
1291
1292                 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1293                 {
1294
1295                     pParentDirEntry = NULL;
1296                 }
1297                 else
1298                 {
1299
1300                     pParentDirEntry = AFSGetParentEntry( pNameArray);
1301
1302                     ASSERT( pParentDirEntry != pDirEntry);
1303                 }
1304
1305                 uniPathName = uniRemainingPath;
1306
1307                 continue;
1308             }
1309
1310             //
1311             // Update our pointers
1312             //
1313
1314             pParentDirEntry = pDirEntry;
1315
1316             pDirEntry = NULL;
1317
1318             uniSearchName = uniComponentName;
1319
1320             while( pDirEntry == NULL)
1321             {
1322
1323                 //
1324                 // If the SearchName contains @SYS then we perform the substitution.
1325                 // If there is no substitution we give up.
1326                 //
1327
1328                 if( !bSubstituteName &&
1329                     FsRtlIsNameInExpression( &uniSysName,
1330                                              &uniSearchName,
1331                                              TRUE,
1332                                              NULL))
1333                 {
1334
1335                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1336                                   AFS_TRACE_LEVEL_VERBOSE_2,
1337                                   "AFSLocateNameEntry (FO: %p) Processing @SYS substitution for %wZ Index %08lX\n",
1338                                   FileObject,
1339                                   &uniComponentName,
1340                                   ulSubstituteIndex);
1341
1342                     ntStatus = AFSSubstituteSysName( &uniComponentName,
1343                                                      &uniSearchName,
1344                                                      ulSubstituteIndex);
1345
1346                     if ( NT_SUCCESS( ntStatus))
1347                     {
1348
1349                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1350                                       AFS_TRACE_LEVEL_VERBOSE_2,
1351                                       "AFSLocateNameEntry (FO: %p) Located substitution %wZ for %wZ Index %08lX\n",
1352                                       FileObject,
1353                                       &uniSearchName,
1354                                       &uniComponentName,
1355                                       ulSubstituteIndex);
1356
1357                         //
1358                         // Go reparse the name again
1359                         //
1360
1361                         bSubstituteName = TRUE;
1362
1363                         ulSubstituteIndex++; // For the next entry, if needed
1364
1365                         continue;   // while( pDirEntry == NULL)
1366                     }
1367                     else
1368                     {
1369
1370                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1371                                       AFS_TRACE_LEVEL_ERROR,
1372                                       "AFSLocateNameEntry (FO: %p) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1373                                       FileObject,
1374                                       &uniComponentName,
1375                                       ulSubstituteIndex,
1376                                       ntStatus);
1377
1378                         if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1379                         {
1380
1381                             //
1382                             // Pass back the directory entries
1383                             //
1384
1385                             *ParentDirectoryCB = pParentDirEntry;
1386
1387                             *DirectoryCB = NULL;
1388
1389                             *VolumeCB = pCurrentVolume;
1390
1391                             if( ComponentName != NULL)
1392                             {
1393
1394                                 *ComponentName = uniComponentName;
1395                             }
1396
1397                             *RootPathName = uniFullPathName;
1398                         }
1399
1400                         //
1401                         // We can't possibly have a pDirEntry since the lookup failed
1402                         //
1403                         try_return( ntStatus);
1404                     }
1405                 }
1406
1407                 //
1408                 // Generate the CRC on the node and perform a case sensitive lookup
1409                 //
1410
1411                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1412                               AFS_TRACE_LEVEL_VERBOSE_2,
1413                               "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case sensitive\n",
1414                               FileObject,
1415                               &uniSearchName);
1416
1417                 ulCRC = AFSGenerateCRC( &uniSearchName,
1418                                         FALSE);
1419
1420                 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1421                                   TRUE);
1422
1423                 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1424                                                 ulCRC,
1425                                                 &pDirEntry);
1426
1427                 if( pDirEntry == NULL)
1428                 {
1429
1430                     //
1431                     // Missed so perform a case insensitive lookup
1432                     //
1433
1434                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1435                                   AFS_TRACE_LEVEL_VERBOSE_2,
1436                                   "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case insensitive\n",
1437                                   FileObject,
1438                                   &uniSearchName);
1439
1440                     ulCRC = AFSGenerateCRC( &uniSearchName,
1441                                             TRUE);
1442
1443                     AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1444                                                       ulCRC,
1445                                                       &pDirEntry);
1446
1447                     if( pDirEntry == NULL)
1448                     {
1449
1450                         //
1451                         // OK, if this component is a valid short name then try
1452                         // a lookup in the short name tree
1453                         //
1454
1455                         if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1456                             RtlIsNameLegalDOS8Dot3( &uniSearchName,
1457                                                     NULL,
1458                                                     NULL))
1459                         {
1460
1461                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1462                                           AFS_TRACE_LEVEL_VERBOSE_2,
1463                                           "AFSLocateNameEntry (FO: %p) Searching for entry %wZ short name\n",
1464                                           FileObject,
1465                                           &uniSearchName);
1466
1467                             AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1468                                                         ulCRC,
1469                                                         &pDirEntry);
1470                         }
1471
1472                         if ( pDirEntry == NULL &&
1473                              pParentDirEntry->ObjectInformation->VolumeCB == AFSGlobalRoot)
1474                         {
1475
1476                             //
1477                             // Check with the service to see if this is a valid cell name
1478                             // that can be automatically resolved.  Drop the shared TreeLock
1479                             // since AFSCheckCellName must acquire it exclusively.
1480                             //
1481
1482                             AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1483
1484                             ntStatus = AFSCheckCellName( AuthGroup,
1485                                                          &uniSearchName,
1486                                                          &pDirEntry);
1487
1488                             AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1489                                               TRUE);
1490                         }
1491
1492                         if( pDirEntry == NULL)
1493                         {
1494
1495                             //
1496                             // If we substituted a name then reset our search name and try again
1497                             //
1498
1499                             if( bSubstituteName)
1500                             {
1501
1502                                 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1503
1504                                 uniSearchName = uniComponentName;
1505
1506                                 bSubstituteName = FALSE;
1507
1508                                 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1509
1510                                 continue;       // while( pDirEntry == NULL)
1511                             }
1512
1513                             if( uniRemainingPath.Length > 0)
1514                             {
1515
1516                                 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1517
1518                                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1519                                               AFS_TRACE_LEVEL_VERBOSE,
1520                                               "AFSLocateNameEntry (FO: %p) Returning path not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1521                                               FileObject,
1522                                               &uniSearchName,
1523                                               pCurrentObject->FileId.Cell,
1524                                               pCurrentObject->FileId.Volume,
1525                                               pCurrentObject->FileId.Vnode,
1526                                               pCurrentObject->FileId.Unique);
1527                             }
1528                             else
1529                             {
1530
1531                                 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1532
1533                                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1534                                               AFS_TRACE_LEVEL_VERBOSE,
1535                                               "AFSLocateNameEntry (FO: %p) Returning name not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1536                                               FileObject,
1537                                               &uniSearchName,
1538                                               pCurrentObject->FileId.Cell,
1539                                               pCurrentObject->FileId.Volume,
1540                                               pCurrentObject->FileId.Vnode,
1541                                               pCurrentObject->FileId.Unique);
1542
1543                                 //
1544                                 // Pass back the directory entries
1545                                 //
1546
1547                                 *ParentDirectoryCB = pParentDirEntry;
1548
1549                                 *DirectoryCB = NULL;
1550
1551                                 *VolumeCB = pCurrentVolume;
1552
1553                                 if( ComponentName != NULL)
1554                                 {
1555
1556                                     *ComponentName = uniComponentName;
1557                                 }
1558
1559                                 *RootPathName = uniFullPathName;
1560                             }
1561
1562                             AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1563
1564                             //
1565                             // Node name not found so get out
1566                             //
1567
1568                             try_return( ntStatus);  // while( pDirEntry == NULL)
1569                         }
1570                     }
1571                     else
1572                     {
1573
1574                         //
1575                         // Here we have a match on the case insensitive lookup for the name. If there
1576                         // Is more than one link entry for this node then fail the lookup request
1577                         //
1578
1579                         if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1580                             pDirEntry->CaseInsensitiveList.fLink != NULL)
1581                         {
1582
1583                             //
1584                             // Increment our dir entry ref count since we will decrement it on exit
1585                             //
1586
1587                             lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1588
1589                             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1590                                           AFS_TRACE_LEVEL_VERBOSE,
1591                                           "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1592                                           &pDirEntry->NameInformation.FileName,
1593                                           pDirEntry,
1594                                           NULL,
1595                                           lCount);
1596
1597                             AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1598
1599                             try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1600                         }
1601                     }
1602                 }
1603
1604                 if( pDirEntry != NULL)
1605                 {
1606
1607                     //
1608                     // If the verify flag is set on the parent and the current entry is deleted
1609                     // revalidate the parent and search again.
1610                     //
1611
1612                     if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1613                         BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1614                     {
1615
1616                         AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1617
1618                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1619                                       AFS_TRACE_LEVEL_VERBOSE,
1620                                       "AFSLocateNameEntry (FO: %p) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1621                                       FileObject,
1622                                       &pParentDirEntry->NameInformation.FileName,
1623                                       pParentDirEntry->ObjectInformation->FileId.Cell,
1624                                       pParentDirEntry->ObjectInformation->FileId.Volume,
1625                                       pParentDirEntry->ObjectInformation->FileId.Vnode,
1626                                       pParentDirEntry->ObjectInformation->FileId.Unique);
1627
1628                         //
1629                         // Directory TreeLock should be exclusively held
1630                         //
1631
1632                         AFSAcquireExcl( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1633                                         TRUE);
1634
1635                         ntStatus = AFSVerifyEntry( AuthGroup,
1636                                                    pParentDirEntry);
1637
1638                         AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1639
1640                         if( !NT_SUCCESS( ntStatus))
1641                         {
1642
1643                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1644                                           AFS_TRACE_LEVEL_ERROR,
1645                                           "AFSLocateNameEntry (FO: %p) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1646                                           FileObject,
1647                                           &pParentDirEntry->NameInformation.FileName,
1648                                           pParentDirEntry->ObjectInformation->FileId.Cell,
1649                                           pParentDirEntry->ObjectInformation->FileId.Volume,
1650                                           pParentDirEntry->ObjectInformation->FileId.Vnode,
1651                                           pParentDirEntry->ObjectInformation->FileId.Unique,
1652                                           ntStatus);
1653
1654                             try_return( ntStatus);
1655                         }
1656
1657                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1658                                       AFS_TRACE_LEVEL_VERBOSE,
1659                                       "AFSLocateNameEntry (FO: %p) Reprocessing component %wZ in parent %wZ\n",
1660                                       FileObject,
1661                                       &uniSearchName,
1662                                       &pParentDirEntry->NameInformation.FileName);
1663
1664
1665                         pDirEntry = NULL;
1666
1667                         continue;
1668                     }
1669
1670                     //
1671                     // Increment our dir entry ref count
1672                     //
1673
1674                     lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1675
1676                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1677                                   AFS_TRACE_LEVEL_VERBOSE,
1678                                   "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1679                                   &pDirEntry->NameInformation.FileName,
1680                                   pDirEntry,
1681                                   NULL,
1682                                   lCount);
1683                 }
1684
1685                 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1686
1687             } // End while( pDirEntry == NULL)
1688
1689             //
1690             // If we have a dirEntry for this component, perform some basic validation on it
1691             //
1692
1693             if( pDirEntry != NULL &&
1694                 BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1695             {
1696
1697                 pCurrentObject = pDirEntry->ObjectInformation;
1698
1699                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1700                               AFS_TRACE_LEVEL_ERROR,
1701                               "AFSLocateNameEntry (FO: %p) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1702                               FileObject,
1703                               &pDirEntry->NameInformation.FileName,
1704                               pCurrentObject->FileId.Cell,
1705                               pCurrentObject->FileId.Volume,
1706                               pCurrentObject->FileId.Vnode,
1707                               pCurrentObject->FileId.Unique);
1708
1709                 //
1710                 // This entry was deleted through the invalidation call back so perform cleanup
1711                 // on the entry
1712                 //
1713
1714                 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1715                 {
1716
1717                     pParentObjectInfo = AFSFindObjectInfo( pCurrentObject->VolumeCB,
1718                                                            &pCurrentObject->ParentFileId);
1719                 }
1720
1721                 ASSERT( pParentObjectInfo != NULL);
1722
1723                 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1724                                 TRUE);
1725
1726                 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1727                                 TRUE);
1728
1729                 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1730
1731                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1732                               AFS_TRACE_LEVEL_VERBOSE,
1733                               "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1734                               &pDirEntry->NameInformation.FileName,
1735                               pDirEntry,
1736                               NULL,
1737                               lCount);
1738
1739                 ASSERT( lCount >= 0);
1740
1741                 if( lCount <= 0)
1742                 {
1743
1744                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1745                                   AFS_TRACE_LEVEL_VERBOSE,
1746                                   "AFSLocateNameEntry Deleting dir entry %p (%p) for %wZ\n",
1747                                   pDirEntry,
1748                                   pCurrentObject,
1749                                   &pDirEntry->NameInformation.FileName);
1750
1751                     //
1752                     // Remove and delete the directory entry from the parent list
1753                     //
1754
1755                     AFSDeleteDirEntry( pParentObjectInfo,
1756                                        pDirEntry);
1757
1758                     AFSAcquireShared( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1759                                       TRUE);
1760
1761                     if( pCurrentObject->ObjectReferenceCount <= 0)
1762                     {
1763
1764                         if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
1765                         {
1766
1767                             AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1768                                           AFS_TRACE_LEVEL_VERBOSE,
1769                                           "AFSLocateNameEntry Removing object %p from volume tree\n",
1770                                           pCurrentObject);
1771
1772                             AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
1773                                                 &pCurrentObject->TreeEntry);
1774
1775                             ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
1776                         }
1777                     }
1778
1779                     AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1780                 }
1781                 else
1782                 {
1783
1784                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1785                                   AFS_TRACE_LEVEL_VERBOSE,
1786                                   "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
1787                                   pDirEntry,
1788                                   &pDirEntry->NameInformation.FileName);
1789
1790                     SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
1791
1792                     AFSRemoveNameEntry( pParentObjectInfo,
1793                                         pDirEntry);
1794                 }
1795
1796                 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1797
1798                 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
1799
1800                 AFSReleaseObjectInfo( &pParentObjectInfo);
1801
1802                 //
1803                 // We deleted the dir entry so check if there is any remaining portion
1804                 // of the name to process.
1805                 //
1806
1807                 if( uniRemainingPath.Length > 0)
1808                 {
1809
1810                     ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1811
1812                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1813                                   AFS_TRACE_LEVEL_VERBOSE,
1814                                   "AFSLocateNameEntry (FO: %p) Returning path not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1815                                   FileObject,
1816                                   &uniComponentName,
1817                                   pCurrentObject->FileId.Cell,
1818                                   pCurrentObject->FileId.Volume,
1819                                   pCurrentObject->FileId.Vnode,
1820                                   pCurrentObject->FileId.Unique);
1821                 }
1822                 else
1823                 {
1824
1825                     ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1826
1827                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1828                                   AFS_TRACE_LEVEL_VERBOSE,
1829                                   "AFSLocateNameEntry (FO: %p) Returning name not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1830                                   FileObject,
1831                                   &uniComponentName,
1832                                   pCurrentObject->FileId.Cell,
1833                                   pCurrentObject->FileId.Volume,
1834                                   pCurrentObject->FileId.Vnode,
1835                                   pCurrentObject->FileId.Unique);
1836
1837                     //
1838                     // Pass back the directory entries
1839                     //
1840
1841                     *ParentDirectoryCB = pParentDirEntry;
1842
1843                     *DirectoryCB = NULL;
1844
1845                     *VolumeCB = pCurrentVolume;
1846
1847                     if( ComponentName != NULL)
1848                     {
1849
1850                         *ComponentName = uniComponentName;
1851                     }
1852
1853                     *RootPathName = uniFullPathName;
1854                 }
1855             }
1856
1857             if( ntStatus != STATUS_SUCCESS)
1858             {
1859
1860                 try_return( ntStatus);
1861             }
1862
1863             //
1864             // Decrement the previous parent
1865             //
1866
1867             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1868
1869             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1870                           AFS_TRACE_LEVEL_VERBOSE,
1871                           "AFSLocateNameEntry Decrement5 count on Parent %wZ DE %p Ccb %p Cnt %d\n",
1872                           &pParentDirEntry->NameInformation.FileName,
1873                           pParentDirEntry,
1874                           NULL,
1875                           lCount);
1876
1877             ASSERT( lCount >= 0);
1878
1879             //
1880             // If we ended up substituting a name in the component then update
1881             // the full path and update the pointers
1882             //
1883
1884             if( bSubstituteName)
1885             {
1886
1887                 BOOLEAN bRelativeOpen = FALSE;
1888
1889                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1890                               AFS_TRACE_LEVEL_VERBOSE_2,
1891                               "AFSLocateNameEntry (FO: %p) Substituting %wZ into %wZ Index %08lX\n",
1892                               FileObject,
1893                               &uniSearchName,
1894                               &uniComponentName,
1895                               ulSubstituteIndex);
1896
1897                 if( FileObject != NULL &&
1898                     FileObject->RelatedFileObject != NULL)
1899                 {
1900
1901                     bRelativeOpen = TRUE;
1902                 }
1903
1904                 //
1905                 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
1906                 // and free the prior Buffer contents but only if the fourth
1907                 // parameter is TRUE.
1908                 //
1909
1910                 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
1911                                                     &uniComponentName,
1912                                                     &uniSearchName,
1913                                                     &uniRemainingPath,
1914                                                     bRelativeOpen ||
1915                                                             bAllocatedSymLinkBuffer ||
1916                                                             bSubstitutedName);
1917
1918                 if( !NT_SUCCESS( ntStatus))
1919                 {
1920
1921                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1922                                   AFS_TRACE_LEVEL_ERROR,
1923                                   "AFSLocateNameEntry (FO: %p) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
1924                                   FileObject,
1925                                   &uniSearchName,
1926                                   &uniComponentName,
1927                                   ulSubstituteIndex,
1928                                   ntStatus);
1929
1930                     try_return( ntStatus);
1931                 }
1932
1933                 //
1934                 // We have substituted a name into the buffer so if we do this again for this
1935                 // path, we need to free up the buffer we allocated.
1936                 //
1937
1938                 bSubstitutedName = TRUE;
1939             }
1940
1941             //
1942             // Update the search parameters
1943             //
1944
1945             uniPathName = uniRemainingPath;
1946
1947             //
1948             // Check if the is a SymLink entry but has no Target FileID or Name. In this
1949             // case it might be a DFS Link so let's go and evaluate it to be sure
1950             //
1951
1952             if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
1953                 ( pCurrentObject->TargetFileId.Vnode == 0 ||
1954                   pDirEntry->NameInformation.TargetName.Length == 0))
1955             {
1956
1957                 ntStatus = AFSValidateSymLink( AuthGroup,
1958                                                pDirEntry);
1959
1960                 if( !NT_SUCCESS( ntStatus))
1961                 {
1962
1963                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1964                                   AFS_TRACE_LEVEL_ERROR,
1965                                   "AFSLocateNameEntry (FO: %p) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1966                                   FileObject,
1967                                   &pDirEntry->NameInformation.FileName,
1968                                   pCurrentObject->FileId.Cell,
1969                                   pCurrentObject->FileId.Volume,
1970                                   pCurrentObject->FileId.Vnode,
1971                                   pCurrentObject->FileId.Unique,
1972                                   ntStatus);
1973
1974                     try_return( ntStatus);
1975                 }
1976             }
1977
1978             //
1979             // Update the name array
1980             //
1981
1982             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1983                           AFS_TRACE_LEVEL_VERBOSE,
1984                           "AFSLocateNameEntry (FO: %p) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1985                           FileObject,
1986                           &pDirEntry->NameInformation.FileName,
1987                           pCurrentObject->FileId.Cell,
1988                           pCurrentObject->FileId.Volume,
1989                           pCurrentObject->FileId.Vnode,
1990                           pCurrentObject->FileId.Unique);
1991
1992             ntStatus = AFSInsertNextElement( pNameArray,
1993                                              pDirEntry);
1994
1995             if( !NT_SUCCESS( ntStatus))
1996             {
1997
1998                 try_return( ntStatus);
1999             }
2000         }       // while (TRUE)
2001
2002 try_exit:
2003
2004         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2005                       AFS_TRACE_LEVEL_VERBOSE,
2006                       "AFSLocateNameEntry (FO: %p) Completed processing %wZ Status %08lX\n",
2007                       FileObject,
2008                       RootPathName,
2009                       ntStatus);
2010
2011         if( ( !NT_SUCCESS( ntStatus) &&
2012               ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
2013             ntStatus == STATUS_REPARSE)
2014         {
2015
2016             if( pDirEntry != NULL)
2017             {
2018
2019                 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
2020
2021                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2022                               AFS_TRACE_LEVEL_VERBOSE,
2023                               "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
2024                               &pDirEntry->NameInformation.FileName,
2025                               pDirEntry,
2026                               NULL,
2027                               lCount);
2028
2029                 ASSERT( lCount >= 0);
2030             }
2031             else if( pParentDirEntry != NULL)
2032             {
2033
2034                 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
2035
2036                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2037                               AFS_TRACE_LEVEL_VERBOSE,
2038                               "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
2039                               &pParentDirEntry->NameInformation.FileName,
2040                               pParentDirEntry,
2041                               NULL,
2042                               lCount);
2043
2044                 ASSERT( lCount >= 0);
2045             }
2046
2047             if( bReleaseCurrentVolume)
2048             {
2049
2050                 ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
2051
2052                 lCount = AFSVolumeDecrement( pCurrentVolume,
2053                                              VolumeReferenceReason);
2054
2055                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2056                               AFS_TRACE_LEVEL_VERBOSE,
2057                               "AFSLocateNameEntry Decrement3 count on volume %p Reason %u Cnt %d\n",
2058                               pCurrentVolume,
2059                               VolumeReferenceReason,
2060                               lCount);
2061
2062                 bReleaseCurrentVolume = FALSE;
2063             }
2064
2065             if( RootPathName->Buffer != uniFullPathName.Buffer)
2066             {
2067
2068                 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
2069             }
2070         }
2071         else
2072         {
2073
2074             if( *ParentDirectoryCB != NULL)
2075             {
2076
2077                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2078                               AFS_TRACE_LEVEL_VERBOSE,
2079                               "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
2080                               &(*ParentDirectoryCB)->NameInformation.FileName,
2081                               *ParentDirectoryCB,
2082                               NULL,
2083                               (*ParentDirectoryCB)->DirOpenReferenceCount);
2084             }
2085
2086             if( *DirectoryCB != NULL)
2087             {
2088
2089                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2090                               AFS_TRACE_LEVEL_VERBOSE,
2091                               "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
2092                               &(*DirectoryCB)->NameInformation.FileName,
2093                               *DirectoryCB,
2094                               NULL,
2095                               (*DirectoryCB)->DirOpenReferenceCount);
2096             }
2097         }
2098
2099         if( bSubstituteName &&
2100             uniSearchName.Buffer != NULL)
2101         {
2102
2103             AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
2104         }
2105
2106         if ( bReleaseCurrentVolume) {
2107
2108             *pVolumeReferenceReason = VolumeReferenceReason;
2109         }
2110     }
2111
2112     return ntStatus;
2113 }
2114
2115 NTSTATUS
2116 AFSCreateDirEntry( IN GUID            *AuthGroup,
2117                    IN AFSObjectInfoCB *ParentObjectInfo,
2118                    IN AFSDirectoryCB *ParentDirCB,
2119                    IN PUNICODE_STRING FileName,
2120                    IN PUNICODE_STRING ComponentName,
2121                    IN ULONG Attributes,
2122                    IN OUT AFSDirectoryCB **DirEntry)
2123 {
2124
2125     UNREFERENCED_PARAMETER(FileName);
2126     NTSTATUS ntStatus = STATUS_SUCCESS;
2127     AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
2128     LARGE_INTEGER liFileSize = {0,0};
2129     LONG lCount;
2130
2131     __Enter
2132     {
2133
2134         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2135                       AFS_TRACE_LEVEL_VERBOSE_2,
2136                       "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
2137                       &ParentDirCB->NameInformation.FileName,
2138                       ParentObjectInfo->FileId.Cell,
2139                       ParentObjectInfo->FileId.Volume,
2140                       ParentObjectInfo->FileId.Vnode,
2141                       ParentObjectInfo->FileId.Unique,
2142                       ComponentName,
2143                       Attributes);
2144
2145         //
2146         // OK, before inserting the node into the parent tree, issue
2147         // the request to the service for node creation
2148         // We will need to drop the lock on the parent node since the create
2149         // could cause a callback into the file system to invalidate it's cache
2150         //
2151
2152         ntStatus = AFSNotifyFileCreate( AuthGroup,
2153                                         ParentObjectInfo,
2154                                         &liFileSize,
2155                                         Attributes,
2156                                         ComponentName,
2157                                         &pDirNode);
2158
2159         //
2160         // If the returned status is STATUS_REPARSE then the entry exists
2161         // and we raced, get out.
2162
2163         if( ntStatus == STATUS_REPARSE)
2164         {
2165
2166             *DirEntry = pDirNode;
2167
2168             try_return( ntStatus = STATUS_SUCCESS);
2169         }
2170
2171         if( !NT_SUCCESS( ntStatus))
2172         {
2173
2174             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2175                           AFS_TRACE_LEVEL_ERROR,
2176                           "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
2177                           &ParentDirCB->NameInformation.FileName,
2178                           ParentObjectInfo->FileId.Cell,
2179                           ParentObjectInfo->FileId.Volume,
2180                           ParentObjectInfo->FileId.Vnode,
2181                           ParentObjectInfo->FileId.Unique,
2182                           ComponentName,
2183                           Attributes,
2184                           ntStatus);
2185
2186             try_return( ntStatus);
2187         }
2188
2189         //
2190         // If AFSNotifyFileCreate returns pDirNode != NULL, then its
2191         // DirOpenReferenceCount is held.
2192         //
2193
2194         AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2195                         TRUE);
2196
2197         //
2198         // Before attempting to insert the new entry, check if we need to validate the parent
2199         //
2200
2201         if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2202         {
2203
2204             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2205                           AFS_TRACE_LEVEL_VERBOSE,
2206                           "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2207                           &ParentDirCB->NameInformation.FileName,
2208                           ParentObjectInfo->FileId.Cell,
2209                           ParentObjectInfo->FileId.Volume,
2210                           ParentObjectInfo->FileId.Vnode,
2211                           ParentObjectInfo->FileId.Unique);
2212
2213             ntStatus = AFSVerifyEntry( AuthGroup,
2214                                        ParentDirCB);
2215
2216             if( !NT_SUCCESS( ntStatus))
2217             {
2218
2219                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2220                               AFS_TRACE_LEVEL_ERROR,
2221                               "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2222                               &ParentDirCB->NameInformation.FileName,
2223                               ParentObjectInfo->FileId.Cell,
2224                               ParentObjectInfo->FileId.Volume,
2225                               ParentObjectInfo->FileId.Vnode,
2226                               ParentObjectInfo->FileId.Unique,
2227                               ntStatus);
2228
2229                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2230
2231                 try_return( ntStatus);
2232             }
2233         }
2234
2235         //
2236         // Check for the entry in the event we raced with some other thread
2237         //
2238
2239         AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2240                                         (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2241                                         &pExistingDirNode);
2242
2243         if( pExistingDirNode != NULL)
2244         {
2245             if (AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2246                                &pExistingDirNode->ObjectInformation->FileId))
2247             {
2248
2249                 if ( pExistingDirNode != pDirNode)
2250                 {
2251
2252                     lCount = InterlockedDecrement( &pDirNode->DirOpenReferenceCount);
2253
2254                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2255                                   AFS_TRACE_LEVEL_VERBOSE,
2256                                   "AFSCreateDirEntry Decrement count on %wZ DE %p Cnt %d\n",
2257                                   &pDirNode->NameInformation.FileName,
2258                                   pDirNode,
2259                                   lCount);
2260
2261                     AFSDeleteDirEntry( ParentObjectInfo,
2262                                        pDirNode);
2263
2264                     lCount = InterlockedIncrement( &pExistingDirNode->DirOpenReferenceCount);
2265
2266                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2267                                   AFS_TRACE_LEVEL_VERBOSE,
2268                                   "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2269                                   &pExistingDirNode->NameInformation.FileName,
2270                                   pExistingDirNode,
2271                                   lCount);
2272
2273                     *DirEntry = pExistingDirNode;
2274                 }
2275
2276                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2277
2278                 try_return( ntStatus = STATUS_SUCCESS);
2279             }
2280             else
2281             {
2282
2283                 //
2284                 // Need to tear down this entry and rebuild it below
2285                 //
2286
2287                 if( pExistingDirNode->DirOpenReferenceCount <= 0)
2288                 {
2289
2290                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2291                                   AFS_TRACE_LEVEL_VERBOSE,
2292                                   "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2293                                   pExistingDirNode,
2294                                   &pExistingDirNode->NameInformation.FileName,
2295                                   pExistingDirNode->ObjectInformation->FileId.Cell,
2296                                   pExistingDirNode->ObjectInformation->FileId.Volume,
2297                                   pExistingDirNode->ObjectInformation->FileId.Vnode,
2298                                   pExistingDirNode->ObjectInformation->FileId.Unique,
2299                                   pDirNode->ObjectInformation->FileId.Cell,
2300                                   pDirNode->ObjectInformation->FileId.Volume,
2301                                   pDirNode->ObjectInformation->FileId.Vnode,
2302                                   pDirNode->ObjectInformation->FileId.Unique);
2303
2304                     AFSDeleteDirEntry( ParentObjectInfo,
2305                                        pExistingDirNode);
2306                 }
2307                 else
2308                 {
2309
2310                     SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2311
2312                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2313                                   AFS_TRACE_LEVEL_VERBOSE,
2314                                   "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2315                                   pExistingDirNode,
2316                                   &pExistingDirNode->NameInformation.FileName,
2317                                   pExistingDirNode->ObjectInformation->FileId.Cell,
2318                                   pExistingDirNode->ObjectInformation->FileId.Volume,
2319                                   pExistingDirNode->ObjectInformation->FileId.Vnode,
2320                                   pExistingDirNode->ObjectInformation->FileId.Unique,
2321                                   pDirNode->ObjectInformation->FileId.Cell,
2322                                   pDirNode->ObjectInformation->FileId.Volume,
2323                                   pDirNode->ObjectInformation->FileId.Vnode,
2324                                   pDirNode->ObjectInformation->FileId.Unique);
2325
2326                     AFSRemoveNameEntry( ParentObjectInfo,
2327                                         pExistingDirNode);
2328                 }
2329             }
2330         }
2331
2332         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2333                       AFS_TRACE_LEVEL_VERBOSE_2,
2334                       "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2335                       &ParentDirCB->NameInformation.FileName,
2336                       ParentObjectInfo->FileId.Cell,
2337                       ParentObjectInfo->FileId.Volume,
2338                       ParentObjectInfo->FileId.Vnode,
2339                       ParentObjectInfo->FileId.Unique,
2340                       ComponentName);
2341
2342         //
2343         // Insert the directory node
2344         //
2345
2346         AFSInsertDirectoryNode( ParentObjectInfo,
2347                                 pDirNode,
2348                                 TRUE);
2349
2350         //
2351         // Pass back the dir entry
2352         //
2353
2354         *DirEntry = pDirNode;
2355
2356         AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2357
2358 try_exit:
2359
2360         NOTHING;
2361     }
2362
2363     return ntStatus;
2364 }
2365
2366 void
2367 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2368                         IN AFSDirectoryCB *DirEntry,
2369                         IN BOOLEAN InsertInEnumList)
2370 {
2371
2372     LONG lCount;
2373
2374     __Enter
2375     {
2376
2377         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2378
2379         //
2380         // Insert the node into the directory node tree
2381         //
2382
2383         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2384                       AFS_TRACE_LEVEL_VERBOSE,
2385                       "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2386                       DirEntry,
2387                       &DirEntry->NameInformation.FileName);
2388
2389         ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2390
2391         if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2392         {
2393
2394             ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2395
2396             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2397                           AFS_TRACE_LEVEL_VERBOSE,
2398                           "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2399                           DirEntry,
2400                           &DirEntry->NameInformation.FileName);
2401         }
2402         else
2403         {
2404
2405             AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2406                                             DirEntry);
2407
2408             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2409                           AFS_TRACE_LEVEL_VERBOSE,
2410                           "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2411                           DirEntry,
2412                           &DirEntry->NameInformation.FileName);
2413         }
2414
2415         if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2416         {
2417
2418             ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2419
2420             SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2421
2422             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2423                           AFS_TRACE_LEVEL_VERBOSE,
2424                           "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2425                           DirEntry,
2426                           &DirEntry->NameInformation.FileName);
2427         }
2428         else
2429         {
2430
2431             AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2432                                               DirEntry);
2433
2434             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2435                           AFS_TRACE_LEVEL_VERBOSE,
2436                           "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2437                           DirEntry,
2438                           &DirEntry->NameInformation.FileName);
2439         }
2440
2441         //
2442         // Into the shortname tree
2443         //
2444
2445         if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2446         {
2447
2448             if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2449             {
2450
2451                 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2452
2453                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2454                               AFS_TRACE_LEVEL_VERBOSE,
2455                               "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2456                               DirEntry,
2457                               &DirEntry->NameInformation.FileName);
2458
2459                 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2460             }
2461             else
2462             {
2463
2464                 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2465                                                              DirEntry)))
2466                 {
2467                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2468                                   AFS_TRACE_LEVEL_VERBOSE,
2469                                   "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2470                                   DirEntry,
2471                                   &DirEntry->NameInformation.FileName);
2472                 }
2473                 else
2474                 {
2475                     SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2476
2477                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2478                                   AFS_TRACE_LEVEL_VERBOSE,
2479                                   "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2480                                   DirEntry,
2481                                   &DirEntry->NameInformation.FileName);
2482                 }
2483             }
2484         }
2485
2486         if( InsertInEnumList)
2487         {
2488
2489             //
2490             // And insert the node into the directory list
2491             //
2492
2493             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2494                           AFS_TRACE_LEVEL_VERBOSE,
2495                           "AFSInsertDirectoryNode Inserting entry %p %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2496                           DirEntry,
2497                           &DirEntry->NameInformation.FileName,
2498                           DirEntry->ObjectInformation->FileId.Cell,
2499                           DirEntry->ObjectInformation->FileId.Volume,
2500                           DirEntry->ObjectInformation->FileId.Vnode,
2501                           DirEntry->ObjectInformation->FileId.Unique);
2502
2503             if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2504             {
2505
2506                 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2507             }
2508             else
2509             {
2510
2511                 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2512
2513                 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2514             }
2515
2516             ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2517
2518             SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2519
2520             lCount = InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2521
2522             AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2523                           AFS_TRACE_LEVEL_VERBOSE,
2524                           "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2525                           &DirEntry->NameInformation.FileName,
2526                           lCount,
2527                           ParentObjectInfo->FileId.Cell,
2528                           ParentObjectInfo->FileId.Volume,
2529                           ParentObjectInfo->FileId.Vnode,
2530                           ParentObjectInfo->FileId.Unique);
2531         }
2532     }
2533
2534     return;
2535 }
2536
2537 void
2538 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2539                    IN AFSDirectoryCB *DirEntry)
2540 {
2541
2542     LONG lCount;
2543
2544     __Enter
2545     {
2546
2547         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2548                       AFS_TRACE_LEVEL_VERBOSE,
2549                       "AFSDeleteDirEntry Deleting dir entry in parent %p Entry %p %wZ FID %08lX-%08lX-%08lX-%08lX RefCount %d\n",
2550                       ParentObjectInfo,
2551                       DirEntry,
2552                       &DirEntry->NameInformation.FileName,
2553                       DirEntry->ObjectInformation->FileId.Cell,
2554                       DirEntry->ObjectInformation->FileId.Volume,
2555                       DirEntry->ObjectInformation->FileId.Vnode,
2556                       DirEntry->ObjectInformation->FileId.Unique,
2557                       DirEntry->DirOpenReferenceCount);
2558
2559         ASSERT( DirEntry->DirOpenReferenceCount == 0);
2560
2561         AFSRemoveDirNodeFromParent( ParentObjectInfo,
2562                                     DirEntry,
2563                                     TRUE);
2564
2565         //
2566         // Free up the name buffer if it was reallocated
2567         //
2568
2569         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2570         {
2571
2572             AFSExFreePoolWithTag( DirEntry->NameInformation.FileName.Buffer, 0);
2573         }
2574
2575         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2576         {
2577
2578             AFSExFreePoolWithTag( DirEntry->NameInformation.TargetName.Buffer, 0);
2579         }
2580
2581         //
2582         // Dereference the object for this dir entry
2583         //
2584
2585         lCount = AFSObjectInfoDecrement( DirEntry->ObjectInformation,
2586                                          AFS_OBJECT_REFERENCE_DIRENTRY);
2587
2588         AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2589                       AFS_TRACE_LEVEL_VERBOSE,
2590                       "AFSDeleteDirEntry Decrement count on object %p Cnt %d\n",
2591                       DirEntry->ObjectInformation,
2592                       lCount);
2593
2594         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
2595             DirEntry->ObjectInformation->Links == 0)
2596         {
2597
2598             SetFlag( DirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2599         }
2600
2601         ExDeleteResourceLite( &DirEntry->NonPaged->Lock);
2602
2603         AFSExFreePoolWithTag( DirEntry->NonPaged, AFS_DIR_ENTRY_NP_TAG);
2604
2605         //
2606         // Free up the dir entry
2607         //
2608
2609         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
2610                       AFS_TRACE_LEVEL_VERBOSE,
2611                       "AFSDeleteDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
2612                       DirEntry);
2613
2614         AFSExFreePoolWithTag( DirEntry, AFS_DIR_ENTRY_TAG);
2615     }
2616 }
2617
2618 NTSTATUS
2619 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2620                             IN AFSDirectoryCB *DirEntry,
2621                             IN BOOLEAN RemoveFromEnumList)
2622 {
2623
2624     NTSTATUS ntStatus = STATUS_SUCCESS;
2625     LONG lCount;
2626
2627     __Enter
2628     {
2629
2630
2631         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2632
2633         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2634                       AFS_TRACE_LEVEL_VERBOSE,
2635                       "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %p\n",
2636                       DirEntry,
2637                       &DirEntry->NameInformation.FileName,
2638                       DirEntry->ObjectInformation->FileId.Cell,
2639                       DirEntry->ObjectInformation->FileId.Volume,
2640                       DirEntry->ObjectInformation->FileId.Vnode,
2641                       DirEntry->ObjectInformation->FileId.Unique,
2642                       ParentObjectInfo);
2643
2644         if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2645         {
2646
2647             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2648                           AFS_TRACE_LEVEL_VERBOSE,
2649                           "AFSRemoveDirNodeFromParent Removing DirEntry %p name %wZ\n",
2650                           DirEntry,
2651                           &DirEntry->NameInformation.FileName);
2652
2653             AFSRemoveNameEntry( ParentObjectInfo,
2654                                 DirEntry);
2655         }
2656         else
2657         {
2658
2659             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2660                           AFS_TRACE_LEVEL_VERBOSE,
2661                           "AFSRemoveDirNodeFromParent DE %p for %wZ NOT removing entry due to flag set\n",
2662                           DirEntry,
2663                           &DirEntry->NameInformation.FileName);
2664
2665         }
2666
2667         if( RemoveFromEnumList &&
2668             BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST))
2669         {
2670
2671             //
2672             // And remove the entry from the enumeration list
2673             //
2674
2675             if( DirEntry->ListEntry.fLink == NULL)
2676             {
2677
2678                 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = (AFSDirectoryCB *)DirEntry->ListEntry.bLink;
2679             }
2680             else
2681             {
2682
2683                 ((AFSDirectoryCB *)DirEntry->ListEntry.fLink)->ListEntry.bLink = DirEntry->ListEntry.bLink;
2684             }
2685
2686             if( DirEntry->ListEntry.bLink == NULL)
2687             {
2688
2689                 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = (AFSDirectoryCB *)DirEntry->ListEntry.fLink;
2690             }
2691             else
2692             {
2693
2694                 ((AFSDirectoryCB *)DirEntry->ListEntry.bLink)->ListEntry.fLink = DirEntry->ListEntry.fLink;
2695             }
2696
2697             ASSERT( ParentObjectInfo->Specific.Directory.DirectoryNodeCount > 0);
2698
2699             lCount = InterlockedDecrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2700
2701             ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2702
2703             AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2704                           AFS_TRACE_LEVEL_VERBOSE,
2705                           "AFSRemoveDirNodeFromParent Removing entry %wZ Dec Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2706                           &DirEntry->NameInformation.FileName,
2707                           lCount,
2708                           ParentObjectInfo->FileId.Cell,
2709                           ParentObjectInfo->FileId.Volume,
2710                           ParentObjectInfo->FileId.Vnode,
2711                           ParentObjectInfo->FileId.Unique);
2712
2713             DirEntry->ListEntry.fLink = NULL;
2714             DirEntry->ListEntry.bLink = NULL;
2715         }
2716     }
2717
2718     return ntStatus;
2719 }
2720
2721 NTSTATUS
2722 AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
2723                     IN OUT PUNICODE_STRING TargetFileName)
2724 {
2725
2726     NTSTATUS ntStatus = STATUS_SUCCESS;
2727     UNICODE_STRING uniFileName;
2728
2729     __Enter
2730     {
2731
2732         //
2733         // We will process backwards from the end of the name looking
2734         // for the first \ we encounter
2735         //
2736
2737         uniFileName.Length = FileName->Length;
2738         uniFileName.MaximumLength = FileName->MaximumLength;
2739
2740         uniFileName.Buffer = FileName->Buffer;
2741
2742         while( TRUE)
2743         {
2744
2745             if( uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
2746             {
2747
2748                 //
2749                 // Subtract one more character off of the filename if it is not the root
2750                 //
2751
2752                 if( uniFileName.Length > sizeof( WCHAR))
2753                 {
2754
2755                     uniFileName.Length -= sizeof( WCHAR);
2756                 }
2757
2758                 //
2759                 // Now build up the target name
2760                 //
2761
2762                 TargetFileName->Length = FileName->Length - uniFileName.Length;
2763
2764                 //
2765                 // If we are not on the root then fixup the name
2766                 //
2767
2768                 if( uniFileName.Length > sizeof( WCHAR))
2769                 {
2770
2771                     TargetFileName->Length -= sizeof( WCHAR);
2772
2773                     TargetFileName->Buffer = &uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) + 1];
2774                 }
2775                 else
2776                 {
2777
2778                     TargetFileName->Buffer = &uniFileName.Buffer[ uniFileName.Length/sizeof( WCHAR)];
2779                 }
2780
2781                 //
2782                 // Fixup the passed back filename length
2783                 //
2784
2785                 FileName->Length = uniFileName.Length;
2786
2787                 TargetFileName->MaximumLength = TargetFileName->Length;
2788
2789                 break;
2790             }
2791
2792             uniFileName.Length -= sizeof( WCHAR);
2793         }
2794     }
2795
2796     return ntStatus;
2797 }
2798
2799 NTSTATUS
2800 AFSParseName( IN PIRP Irp,
2801               IN GUID *AuthGroup,
2802               OUT PUNICODE_STRING FileName,
2803               OUT PUNICODE_STRING ParsedFileName,
2804               OUT PUNICODE_STRING RootFileName,
2805               OUT ULONG *ParseFlags,
2806               OUT AFSVolumeCB   **VolumeCB,
2807               OUT AFSDirectoryCB **ParentDirectoryCB,
2808               OUT AFSNameArrayHdr **NameArray)
2809 {
2810
2811     NTSTATUS            ntStatus = STATUS_SUCCESS;
2812     PIO_STACK_LOCATION  pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2813     AFSDeviceExt       *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2814     UNICODE_STRING      uniFullName, uniComponentName, uniRemainingPath;
2815     ULONG               ulCRC = 0;
2816     AFSDirectoryCB     *pDirEntry = NULL;
2817     USHORT              usIndex = 0, usDriveIndex = 0;
2818     AFSCcb             *pRelatedCcb = NULL;
2819     AFSNameArrayHdr    *pNameArray = NULL, *pRelatedNameArray = NULL;
2820     USHORT              usComponentIndex = 0;
2821     USHORT              usComponentLength = 0;
2822     AFSVolumeCB        *pVolumeCB = NULL;
2823     AFSFcb             *pRelatedFcb = NULL;
2824     BOOLEAN             bReleaseTreeLock = FALSE;
2825     BOOLEAN             bIsAllShare = FALSE;
2826     LONG                lCount;
2827
2828     __Enter
2829     {
2830
2831         //
2832         // Indicate we are opening a root ...
2833         //
2834
2835         *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
2836
2837         *ParentDirectoryCB = NULL;
2838
2839         if( pIrpSp->FileObject->RelatedFileObject != NULL)
2840         {
2841
2842             pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
2843
2844             pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
2845
2846             pRelatedNameArray = pRelatedCcb->NameArray;
2847
2848             uniFullName = pIrpSp->FileObject->FileName;
2849
2850             ASSERT( pRelatedFcb != NULL);
2851
2852             //
2853             // No wild cards in the name
2854             //
2855
2856             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2857                           AFS_TRACE_LEVEL_VERBOSE_2,
2858                           "AFSParseName (%p) Relative open for %wZ FID %08lX-%08lX-%08lX-%08lX component %wZ\n",
2859                           Irp,
2860                           &pRelatedCcb->DirectoryCB->NameInformation.FileName,
2861                           pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Cell,
2862                           pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Volume,
2863                           pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
2864                           pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Unique,
2865                           &uniFullName);
2866
2867             if( FsRtlDoesNameContainWildCards( &uniFullName))
2868             {
2869
2870                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2871                               AFS_TRACE_LEVEL_ERROR,
2872                               "AFSParseName (%p) Component %wZ contains wild cards\n",
2873                               Irp,
2874                               &uniFullName);
2875
2876                 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
2877             }
2878
2879             pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
2880
2881             pDirEntry = pRelatedCcb->DirectoryCB;
2882
2883             *FileName = pIrpSp->FileObject->FileName;
2884
2885             //
2886             // Grab the root node while checking state
2887             //
2888
2889             AFSAcquireShared( pVolumeCB->VolumeLock,
2890                               TRUE);
2891
2892             if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
2893                 BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
2894             {
2895
2896                 //
2897                 // The volume has been taken off line so fail the access
2898                 //
2899
2900                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2901                               AFS_TRACE_LEVEL_ERROR,
2902                               "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
2903                               Irp,
2904                               pVolumeCB->ObjectInformation.FileId.Cell,
2905                               pVolumeCB->ObjectInformation.FileId.Volume);
2906
2907                 AFSReleaseResource( pVolumeCB->VolumeLock);
2908
2909                 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
2910             }
2911
2912             if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
2913             {
2914
2915                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2916                               AFS_TRACE_LEVEL_VERBOSE,
2917                               "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
2918                               Irp,
2919                               pVolumeCB->ObjectInformation.FileId.Cell,
2920                               pVolumeCB->ObjectInformation.FileId.Volume);
2921
2922                 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
2923                                             pVolumeCB);
2924
2925                 if( !NT_SUCCESS( ntStatus))
2926                 {
2927
2928                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2929                                   AFS_TRACE_LEVEL_ERROR,
2930                                   "AFSParseName (%p) Failed verification of root Status %08lX\n",
2931                                   Irp,
2932                                   ntStatus);
2933
2934                     AFSReleaseResource( pVolumeCB->VolumeLock);
2935
2936                     try_return( ntStatus);
2937                 }
2938             }
2939
2940             AFSReleaseResource( pVolumeCB->VolumeLock);
2941
2942             if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
2943             {
2944
2945                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2946                               AFS_TRACE_LEVEL_VERBOSE,
2947                               "AFSParseName (%p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2948                               Irp,
2949                               &pDirEntry->NameInformation.FileName,
2950                               pDirEntry->ObjectInformation->FileId.Cell,
2951                               pDirEntry->ObjectInformation->FileId.Volume,
2952                               pDirEntry->ObjectInformation->FileId.Vnode,
2953                               pDirEntry->ObjectInformation->FileId.Unique);
2954
2955                 //
2956                 // Directory TreeLock should be exclusively held
2957                 //
2958
2959                 AFSAcquireExcl( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
2960                                 TRUE);
2961
2962                 ntStatus = AFSVerifyEntry( AuthGroup,
2963                                            pDirEntry);
2964
2965                 AFSReleaseResource( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2966
2967                 if( !NT_SUCCESS( ntStatus))
2968                 {
2969
2970                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2971                                   AFS_TRACE_LEVEL_VERBOSE,
2972                                   "AFSParseName (%p) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2973                                   Irp,
2974                                   &pDirEntry->NameInformation.FileName,
2975                                   pDirEntry->ObjectInformation->FileId.Cell,
2976                                   pDirEntry->ObjectInformation->FileId.Volume,
2977                                   pDirEntry->ObjectInformation->FileId.Vnode,
2978                                   pDirEntry->ObjectInformation->FileId.Unique,
2979                                   ntStatus);
2980
2981                     try_return( ntStatus);
2982                 }
2983             }
2984
2985             //
2986             // Create our full path name buffer
2987             //
2988
2989             uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length +
2990                                                     sizeof( WCHAR) +
2991                                                     pIrpSp->FileObject->FileName.Length +
2992                                                     sizeof( WCHAR);
2993
2994             uniFullName.Length = 0;
2995
2996             uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2997                                                                     uniFullName.MaximumLength,
2998                                                                     AFS_NAME_BUFFER_THREE_TAG);
2999
3000             if( uniFullName.Buffer == NULL)
3001             {
3002
3003                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3004                               AFS_TRACE_LEVEL_ERROR,
3005                               "AFSParseName (%p) Failed to allocate full name buffer\n",
3006                               Irp);
3007
3008                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3009             }
3010
3011             RtlZeroMemory( uniFullName.Buffer,
3012                            uniFullName.MaximumLength);
3013
3014             RtlCopyMemory( uniFullName.Buffer,
3015                            pRelatedCcb->FullFileName.Buffer,
3016                            pRelatedCcb->FullFileName.Length);
3017
3018             uniFullName.Length = pRelatedCcb->FullFileName.Length;
3019
3020             usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
3021
3022             usComponentLength = pIrpSp->FileObject->FileName.Length;
3023
3024             if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
3025                 pIrpSp->FileObject->FileName.Length > 0 &&
3026                 pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
3027                 pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
3028             {
3029
3030                 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
3031
3032                 uniFullName.Length += sizeof( WCHAR);
3033
3034                 usComponentLength += sizeof( WCHAR);
3035             }
3036
3037             if( pIrpSp->FileObject->FileName.Length > 0)
3038             {
3039
3040                 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
3041                                pIrpSp->FileObject->FileName.Buffer,
3042                                pIrpSp->FileObject->FileName.Length);
3043
3044                 uniFullName.Length += pIrpSp->FileObject->FileName.Length;
3045             }
3046
3047             *RootFileName = uniFullName;
3048
3049             //
3050             // We populate up to the current parent
3051             //
3052
3053             if( pRelatedNameArray == NULL)
3054             {
3055
3056                 //
3057                 // Init and populate our name array
3058                 //
3059
3060                 pNameArray = AFSInitNameArray( NULL,
3061                                                0);
3062
3063                 if( pNameArray == NULL)
3064                 {
3065
3066                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3067                                   AFS_TRACE_LEVEL_VERBOSE,
3068                                   "AFSParseName (%p) Failed to initialize name array\n",
3069                                   Irp);
3070
3071                     AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3072
3073                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3074                 }
3075
3076                 ntStatus = AFSPopulateNameArray( pNameArray,
3077                                                  NULL,
3078                                                  pRelatedCcb->DirectoryCB);
3079             }
3080             else
3081             {
3082
3083                 //
3084                 // Init and populate our name array
3085                 //
3086
3087                 pNameArray = AFSInitNameArray( NULL,
3088                                                pRelatedNameArray->MaxElementCount);
3089
3090                 if( pNameArray == NULL)
3091                 {
3092
3093                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3094                                   AFS_TRACE_LEVEL_VERBOSE,
3095                                   "AFSParseName (%p) Failed to initialize name array\n",
3096                                   Irp);
3097
3098                     AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3099
3100                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3101                 }
3102
3103                 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
3104                                                                  pRelatedNameArray,
3105                                                                  pRelatedCcb->DirectoryCB);
3106             }
3107
3108             if( !NT_SUCCESS( ntStatus))
3109             {
3110
3111                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3112                               AFS_TRACE_LEVEL_VERBOSE,
3113                               "AFSParseName (%p) Failed to populate name array\n",
3114                               Irp);
3115
3116                 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3117
3118                 try_return( ntStatus);
3119             }
3120
3121             ParsedFileName->Length = usComponentLength;
3122             ParsedFileName->MaximumLength = uniFullName.MaximumLength;
3123
3124             ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
3125
3126             //
3127             // Indicate to caller that RootFileName must be freed
3128             //
3129
3130             SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
3131
3132             *NameArray = pNameArray;
3133
3134             //
3135             // Increment our volume reference count
3136             //
3137
3138             lCount = AFSVolumeIncrement( pVolumeCB,
3139                                          AFS_VOLUME_REFERENCE_PARSE_NAME);
3140
3141             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3142                           AFS_TRACE_LEVEL_VERBOSE,
3143                           "AFSParseName Increment count on volume %p Cnt %d\n",
3144                           pVolumeCB,
3145                           lCount);
3146
3147             *VolumeCB = pVolumeCB;
3148
3149             *ParentDirectoryCB = pDirEntry;
3150
3151             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3152                           AFS_TRACE_LEVEL_VERBOSE_2,
3153                           "AFSParseName (%p) Returning full name %wZ\n",
3154                           Irp,
3155                           &uniFullName);
3156
3157             try_return( ntStatus);
3158         }
3159
3160         //
3161         // No wild cards in the name
3162         //
3163
3164         uniFullName = pIrpSp->FileObject->FileName;
3165
3166         if( FsRtlDoesNameContainWildCards( &uniFullName) ||
3167             uniFullName.Length < AFSServerName.Length)
3168         {
3169
3170             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3171                           AFS_TRACE_LEVEL_ERROR,
3172                           "AFSParseName (%p) Name %wZ contains wild cards or too short\n",
3173                           Irp,
3174                           &uniFullName);
3175
3176             try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3177         }
3178
3179         //
3180         // The name is a fully qualified name. Parse out the server/share names and
3181         // point to the root qualified name
3182         // First thing is to locate the server name
3183         //
3184
3185         FsRtlDissectName( uniFullName,
3186                           &uniComponentName,
3187                           &uniRemainingPath);
3188
3189         uniFullName = uniRemainingPath;
3190
3191         //
3192         // This component is the server name we are serving
3193         //
3194
3195         if( RtlCompareUnicodeString( &uniComponentName,
3196                                      &AFSServerName,
3197                                      TRUE) != 0)
3198         {
3199
3200             //
3201             // Drive letter based name?
3202             //
3203
3204             uniFullName = pIrpSp->FileObject->FileName;
3205
3206             while( usIndex < uniFullName.Length/sizeof( WCHAR))
3207             {
3208
3209                 if( uniFullName.Buffer[ usIndex] == L':')
3210                 {
3211
3212                     uniFullName.Buffer = &uniFullName.Buffer[ usIndex + 2];
3213
3214                     uniFullName.Length -= (usIndex + 2) * sizeof( WCHAR);
3215
3216                     usDriveIndex = usIndex - 1;
3217
3218                     break;
3219                 }
3220
3221                 usIndex++;
3222             }
3223
3224             //
3225             // Do we have the right server name now?
3226             //
3227
3228             FsRtlDissectName( uniFullName,
3229                               &uniComponentName,
3230                               &uniRemainingPath);
3231
3232             uniFullName = uniRemainingPath;
3233
3234             //
3235             // This component is the server name we are serving
3236             //
3237
3238             if( RtlCompareUnicodeString( &uniComponentName,
3239                                          &AFSServerName,
3240                                          TRUE) != 0)
3241             {
3242
3243                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3244                               AFS_TRACE_LEVEL_ERROR,
3245                               "AFSParseName (%p) Name %wZ does not have server name\n",
3246                               Irp,
3247                               &pIrpSp->FileObject->FileName);
3248
3249                 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3250             }
3251
3252             //
3253             // Validate this drive letter is actively mapped
3254             //
3255
3256             if( usDriveIndex > 0 &&
3257                 !AFSIsDriveMapped( pIrpSp->FileObject->FileName.Buffer[ usDriveIndex]))
3258             {
3259
3260                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3261                               AFS_TRACE_LEVEL_ERROR,
3262                               "AFSParseName (%p) Name %wZ contains invalid drive mapping\n",
3263                               Irp,
3264                               &pIrpSp->FileObject->FileName);
3265
3266                 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3267             }
3268         }
3269
3270         if( FsRtlDoesNameContainWildCards( &uniFullName))
3271         {
3272
3273             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3274                           AFS_TRACE_LEVEL_ERROR,
3275                           "AFSParseName (%p) Component %wZ contains wild cards\n",
3276                           Irp,
3277                           &uniFullName);
3278
3279             try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3280         }
3281
3282         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3283                       AFS_TRACE_LEVEL_VERBOSE_2,
3284                       "AFSParseName (%p) Processing full name %wZ\n",
3285                       Irp,
3286                       &uniFullName);
3287
3288         if( uniFullName.Length > 0 &&
3289             uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] == L'\\')
3290         {
3291
3292             uniFullName.Length -= sizeof( WCHAR);
3293         }
3294
3295         //
3296         // Be sure we are online and ready to go
3297         //
3298
3299         AFSAcquireShared( AFSGlobalRoot->VolumeLock,
3300                           TRUE);
3301
3302         if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3303             BooleanFlagOn( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3304         {
3305
3306             //
3307             // The volume has been taken off line so fail the access
3308             //
3309
3310             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3311                           AFS_TRACE_LEVEL_ERROR,
3312                           "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3313                           Irp,
3314                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3315                           AFSGlobalRoot->ObjectInformation.FileId.Volume);
3316
3317             AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3318
3319             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3320         }
3321
3322         if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3323         {
3324
3325             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3326                           AFS_TRACE_LEVEL_VERBOSE,
3327                           "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
3328                           Irp,
3329                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3330                           AFSGlobalRoot->ObjectInformation.FileId.Volume);
3331
3332             ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3333                                         AFSGlobalRoot);
3334
3335             if( !NT_SUCCESS( ntStatus))
3336             {
3337
3338                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3339                               AFS_TRACE_LEVEL_ERROR,
3340                               "AFSParseName (%p) Failed verification of root Status %08lX\n",
3341                               Irp,
3342                               ntStatus);
3343
3344                 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3345
3346                 try_return( ntStatus);
3347             }
3348         }
3349
3350         AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3351
3352         if( !BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3353         {
3354
3355             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3356                           AFS_TRACE_LEVEL_VERBOSE,
3357                           "AFSParseName (%p) Enumerating global root of volume %08lX:%08lX\n",
3358                           Irp,
3359                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3360                           AFSGlobalRoot->ObjectInformation.FileId.Volume);
3361
3362             ntStatus = AFSEnumerateGlobalRoot( AuthGroup);
3363
3364             if( !NT_SUCCESS( ntStatus))
3365             {
3366
3367                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3368                               AFS_TRACE_LEVEL_ERROR,
3369                               "AFSParseName (%p) Failed enumeraiton of root Status %08lX\n",
3370                               Irp,
3371                               ntStatus);
3372
3373                 try_return( ntStatus);
3374             }
3375         }
3376
3377         //
3378         // Check for the \\Server access and return it as though it were \\Server\Globalroot
3379         //
3380
3381         if( uniRemainingPath.Buffer == NULL ||
3382             ( uniRemainingPath.Length == sizeof( WCHAR) &&
3383               uniRemainingPath.Buffer[ 0] == L'\\'))
3384         {
3385
3386             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3387                           AFS_TRACE_LEVEL_VERBOSE_2,
3388                           "AFSParseName (%p) Returning global root access\n",
3389                           Irp);
3390
3391             lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3392
3393             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3394                           AFS_TRACE_LEVEL_VERBOSE,
3395                           "AFSParseName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3396                           &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3397                           AFSGlobalRoot->DirectoryCB,
3398                           NULL,
3399                           lCount);
3400
3401             *VolumeCB = NULL;
3402
3403             FileName->Length = 0;
3404             FileName->MaximumLength = 0;
3405             FileName->Buffer = NULL;
3406
3407             try_return( ntStatus = STATUS_SUCCESS);
3408         }
3409
3410         *RootFileName = uniFullName;
3411
3412         //
3413         // Include the starting \ in the root name
3414         //
3415
3416         if( RootFileName->Buffer[ 0] != L'\\')
3417         {
3418             RootFileName->Buffer--;
3419             RootFileName->Length += sizeof( WCHAR);
3420             RootFileName->MaximumLength += sizeof( WCHAR);
3421         }
3422
3423         //
3424         // Get the 'share' name
3425         //
3426
3427         FsRtlDissectName( uniFullName,
3428                           &uniComponentName,
3429                           &uniRemainingPath);
3430
3431         if( FsRtlDoesNameContainWildCards( &uniFullName))
3432         {
3433
3434             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3435                           AFS_TRACE_LEVEL_ERROR,
3436                           "AFSParseName (%p) Component %wZ contains wild cards\n",
3437                           Irp,
3438                           &uniComponentName);
3439
3440             try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3441         }
3442
3443         //
3444         // If this is the ALL access then perform some additional processing
3445         //
3446
3447         if( uniComponentName.Length == 0 ||
3448             RtlCompareUnicodeString( &uniComponentName,
3449                                      &AFSGlobalRootName,
3450                                      TRUE) == 0)
3451         {
3452
3453             bIsAllShare = TRUE;
3454
3455             //
3456             // If there is nothing else then get out
3457             //
3458
3459             if( uniRemainingPath.Buffer == NULL ||
3460                 uniRemainingPath.Length == 0 ||
3461                 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3462                   uniRemainingPath.Buffer[ 0] == L'\\'))
3463             {
3464
3465                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3466                               AFS_TRACE_LEVEL_VERBOSE_2,
3467                               "AFSParseName (%p) Returning global root access\n",
3468                               Irp);
3469
3470                 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3471
3472                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3473                               AFS_TRACE_LEVEL_VERBOSE,
3474                               "AFSParseName Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
3475                               &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3476                               AFSGlobalRoot->DirectoryCB,
3477                               NULL,
3478                               lCount);
3479
3480                 *VolumeCB = NULL;
3481
3482                 FileName->Length = 0;
3483                 FileName->MaximumLength = 0;
3484                 FileName->Buffer = NULL;
3485
3486                 try_return( ntStatus = STATUS_SUCCESS);
3487             }
3488
3489             //
3490             // Process the name again to strip off the ALL portion
3491             //
3492
3493             uniFullName = uniRemainingPath;
3494
3495             FsRtlDissectName( uniFullName,
3496                               &uniComponentName,
3497                               &uniRemainingPath);
3498
3499             //
3500             // Check for the PIOCtl name
3501             //
3502
3503             if( RtlCompareUnicodeString( &uniComponentName,
3504                                          &AFSPIOCtlName,
3505                                          TRUE) == 0)
3506             {
3507
3508                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3509                               AFS_TRACE_LEVEL_VERBOSE_2,
3510                               "AFSParseName (%p) Returning root PIOCtl access\n",
3511                               Irp);
3512
3513                 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3514
3515                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3516                               AFS_TRACE_LEVEL_VERBOSE,
3517                               "AFSParseName Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
3518                               &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3519                               AFSGlobalRoot->DirectoryCB,
3520                               NULL,
3521                               lCount);
3522
3523                 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3524
3525                 *VolumeCB = NULL;
3526
3527                 *FileName = AFSPIOCtlName;
3528
3529                 try_return( ntStatus = STATUS_SUCCESS);
3530             }
3531         }
3532         else if( (pDirEntry = AFSGetSpecialShareNameEntry( &uniComponentName,
3533                                                            &uniRemainingPath)) != NULL)
3534         {
3535
3536             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3537                           AFS_TRACE_LEVEL_VERBOSE_2,
3538                           "AFSParseName (%p) Returning root share name %wZ access\n",
3539                           Irp,
3540                           &uniComponentName);
3541
3542             //
3543             // Add in the full share name to pass back
3544             //
3545
3546             if( uniRemainingPath.Buffer != NULL)
3547             {
3548
3549                 //
3550                 // This routine strips off the leading slash so add it back in
3551                 //
3552
3553                 uniRemainingPath.Buffer--;
3554                 uniRemainingPath.Length += sizeof( WCHAR);
3555                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3556
3557                 //
3558                 // And the cell name
3559                 //
3560
3561                 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3562                 uniRemainingPath.Length += uniComponentName.Length;
3563                 uniRemainingPath.MaximumLength += uniComponentName.Length;
3564
3565                 uniComponentName = uniRemainingPath;
3566             }
3567
3568             *VolumeCB = NULL;
3569
3570             *FileName = uniComponentName;
3571
3572             ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3573
3574             *ParentDirectoryCB = pDirEntry;
3575
3576             try_return( ntStatus = STATUS_SUCCESS);
3577         }
3578
3579         //
3580         // Determine the 'share' we are accessing
3581         //
3582
3583         ulCRC = AFSGenerateCRC( &uniComponentName,
3584                                 FALSE);
3585
3586         AFSAcquireShared( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3587                           TRUE);
3588
3589         bReleaseTreeLock = TRUE;
3590
3591         AFSLocateCaseSensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
3592                                         ulCRC,
3593                                         &pDirEntry);
3594
3595         if( pDirEntry == NULL)
3596         {
3597
3598             ulCRC = AFSGenerateCRC( &uniComponentName,
3599                                     TRUE);
3600
3601             AFSLocateCaseInsensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
3602                                               ulCRC,
3603                                               &pDirEntry);
3604
3605             if( pDirEntry == NULL)
3606             {
3607
3608                 //
3609                 // OK, if this component is a valid short name then try
3610                 // a lookup in the short name tree
3611                 //
3612
3613                 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3614                     RtlIsNameLegalDOS8Dot3( &uniComponentName,
3615                                             NULL,
3616                                             NULL))
3617                 {
3618
3619                     AFSLocateShortNameDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.ShortNameTree,
3620                                                 ulCRC,
3621                                                 &pDirEntry);
3622                 }
3623
3624                 if( pDirEntry == NULL)
3625                 {
3626
3627                     //
3628                     // Check with the service whether it is a valid cell name
3629                     //
3630
3631                     AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3632
3633                     bReleaseTreeLock = FALSE;
3634
3635                     ntStatus = AFSCheckCellName( AuthGroup,
3636                                                  &uniComponentName,
3637                                                  &pDirEntry);
3638
3639                     if( !NT_SUCCESS( ntStatus))
3640                     {
3641
3642                         if ( bIsAllShare &&
3643                              uniRemainingPath.Length == 0 &&
3644                              ntStatus == STATUS_OBJECT_PATH_NOT_FOUND)
3645                         {
3646
3647                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3648                                           AFS_TRACE_LEVEL_VERBOSE,
3649                                           "AFSParseName (%p) AFSCheckCellName %wZ returned path not found; ntStatus %08X\n",
3650                                           Irp,
3651                                           &uniComponentName,
3652                                           STATUS_OBJECT_NAME_NOT_FOUND);
3653
3654                             ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
3655                         }
3656
3657                         try_return( ntStatus);
3658                     }
3659                 }
3660             }
3661         }
3662
3663         if( bReleaseTreeLock)
3664         {
3665             AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3666         }
3667
3668
3669         //
3670         // Be sure we are starting from the correct volume
3671         //
3672
3673         if( pDirEntry->ObjectInformation->VolumeCB != AFSGlobalRoot)
3674         {
3675
3676             //
3677             // We dropped the global root in the CheckCellName routine which is the
3678             // only way we can be here
3679             //
3680
3681             pVolumeCB = pDirEntry->ObjectInformation->VolumeCB;
3682
3683             //
3684             // Init our name array
3685             //
3686
3687             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
3688                                            0);
3689
3690             if( pNameArray == NULL)
3691             {
3692
3693                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3694                               AFS_TRACE_LEVEL_VERBOSE,
3695                               "AFSParseName (%p) Failed to initialize name array\n",
3696                               Irp);
3697
3698                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3699             }
3700
3701             ntStatus = AFSInsertNextElement( pNameArray,
3702                                              pVolumeCB->DirectoryCB);
3703
3704             if ( ntStatus)
3705             {
3706
3707                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3708                               AFS_TRACE_LEVEL_VERBOSE,
3709                               "AFSParseName (%p) Failed to insert name array element\n",
3710                               Irp);
3711
3712                 try_return( ntStatus);
3713             }
3714
3715             //
3716             // In this case don't add back in the 'share' name since that is where we are
3717             // starting. Just put the leading slash back in
3718             //
3719
3720             if( uniRemainingPath.Buffer != NULL)
3721             {
3722
3723                 uniRemainingPath.Buffer--;
3724                 uniRemainingPath.Length += sizeof( WCHAR);
3725                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3726
3727                 if( uniRemainingPath.Length > sizeof( WCHAR))
3728                 {
3729
3730                     ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3731                 }
3732
3733                 //
3734                 // Pass back the parent being the root of the volume
3735                 //
3736
3737                 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3738             }
3739             else
3740             {
3741
3742                 //
3743                 // Pass back a root slash
3744                 //
3745
3746                 uniRemainingPath = uniComponentName;
3747
3748                 uniRemainingPath.Buffer--;
3749                 uniRemainingPath.Length = sizeof( WCHAR);
3750                 uniRemainingPath.MaximumLength = sizeof( WCHAR);
3751
3752                 //
3753                 // This is a root open so pass back no parent
3754                 //
3755             }
3756         }
3757         else
3758         {
3759
3760             pVolumeCB = AFSGlobalRoot;
3761
3762             //
3763             // Init our name array
3764             //
3765
3766             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
3767                                            0);
3768             if( pNameArray == NULL)
3769             {
3770
3771                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3772                               AFS_TRACE_LEVEL_VERBOSE,
3773                               "AFSParseName (%p) Failed to initialize name array\n",
3774                               Irp);
3775
3776                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3777             }
3778
3779             //
3780             // Add back in the 'share' portion of the name since we will parse it out on return
3781             //
3782
3783             if( uniRemainingPath.Buffer != NULL)
3784             {
3785
3786                 //
3787                 // This routine strips off the leading slash so add it back in
3788                 //
3789
3790                 uniRemainingPath.Buffer--;
3791                 uniRemainingPath.Length += sizeof( WCHAR);
3792                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3793
3794                 if( uniRemainingPath.Length > sizeof( WCHAR))
3795                 {
3796
3797                     ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3798                 }
3799
3800                 //
3801                 // And the cell name
3802                 //
3803
3804                 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3805                 uniRemainingPath.Length += uniComponentName.Length;
3806                 uniRemainingPath.MaximumLength += uniComponentName.Length;
3807             }
3808             else
3809             {
3810
3811                 uniRemainingPath = uniComponentName;
3812             }
3813
3814             //
3815             // And the leading slash again ...
3816             //
3817
3818             uniRemainingPath.Buffer--;
3819             uniRemainingPath.Length += sizeof( WCHAR);
3820             uniRemainingPath.MaximumLength += sizeof( WCHAR);
3821
3822             //
3823             // Pass back the parent being the volume root
3824             //
3825
3826             *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3827         }
3828
3829         //
3830         // Return the remaining portion as the file name
3831         //
3832
3833         *FileName = uniRemainingPath;
3834
3835         *ParsedFileName = uniRemainingPath;
3836
3837         *NameArray = pNameArray;
3838
3839         *VolumeCB = pVolumeCB;
3840
3841         //
3842         // Increment our reference on the volume
3843         //
3844
3845         lCount = AFSVolumeIncrement( pVolumeCB,
3846                                      AFS_VOLUME_REFERENCE_PARSE_NAME);
3847
3848         AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3849                       AFS_TRACE_LEVEL_VERBOSE,
3850                       "AFSParseName Increment2 count on global volume %p Cnt %d\n",
3851                       pVolumeCB,
3852                       lCount);
3853
3854 try_exit:
3855
3856         if( NT_SUCCESS( ntStatus))
3857         {
3858
3859             if( *ParentDirectoryCB != NULL)
3860             {
3861
3862                 lCount = InterlockedIncrement( &(*ParentDirectoryCB)->DirOpenReferenceCount);
3863
3864                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3865                               AFS_TRACE_LEVEL_VERBOSE,
3866                               "AFSParseName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
3867                               &(*ParentDirectoryCB)->NameInformation.FileName,
3868                               (*ParentDirectoryCB),
3869                               NULL,
3870                               lCount);
3871             }
3872         }
3873
3874         if( *VolumeCB != NULL)
3875         {
3876             ASSERT( (*VolumeCB)->VolumeReferenceCount > 0);
3877         }
3878
3879         if( ntStatus != STATUS_SUCCESS)
3880         {
3881
3882             if( pNameArray != NULL)
3883             {
3884
3885                 AFSFreeNameArray( pNameArray);
3886             }
3887         }
3888     }
3889
3890     return ntStatus;
3891 }
3892
3893 NTSTATUS
3894 AFSCheckCellName( IN GUID *AuthGroup,
3895                   IN UNICODE_STRING *CellName,
3896                   OUT AFSDirectoryCB **ShareDirEntry)
3897 {
3898
3899     NTSTATUS ntStatus = STATUS_SUCCESS;
3900     UNICODE_STRING uniName;
3901     AFSDirEnumEntry *pDirEnumEntry = NULL;
3902     AFSDirHdr *pDirHdr = &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr;
3903     AFSDirectoryCB *pDirNode = NULL;
3904     UNICODE_STRING uniDirName, uniTargetName;
3905     AFSVolumeCB *pVolumeCB = NULL;
3906     LONG lCount;
3907
3908     __Enter
3909     {
3910
3911         //
3912         // Look for some default names we will not handle
3913         //
3914
3915         RtlInitUnicodeString( &uniName,
3916                               L"IPC$");
3917
3918         if( RtlCompareUnicodeString( &uniName,
3919                                      CellName,
3920                                      TRUE) == 0)
3921         {
3922
3923             try_return( ntStatus = STATUS_NO_SUCH_FILE);
3924         }
3925
3926         RtlInitUnicodeString( &uniName,
3927                               L"wkssvc");
3928
3929         if( RtlCompareUnicodeString( &uniName,
3930                                      CellName,
3931                                      TRUE) == 0)
3932         {
3933
3934             try_return( ntStatus = STATUS_NO_SUCH_FILE);
3935         }
3936
3937         RtlInitUnicodeString( &uniName,
3938                               L"srvsvc");
3939
3940         if( RtlCompareUnicodeString( &uniName,
3941                                      CellName,
3942                                      TRUE) == 0)
3943         {
3944
3945             try_return( ntStatus = STATUS_NO_SUCH_FILE);
3946         }
3947
3948         RtlInitUnicodeString( &uniName,
3949                               L"PIPE");
3950
3951         if( RtlCompareUnicodeString( &uniName,
3952                                      CellName,
3953                                      TRUE) == 0)
3954         {
3955
3956             try_return( ntStatus = STATUS_NO_SUCH_FILE);
3957         }
3958
3959         //
3960         // OK, ask the CM about this component name
3961         //
3962
3963         ntStatus = AFSEvaluateTargetByName( AuthGroup,
3964                                             &AFSGlobalRoot->ObjectInformation,
3965                                             CellName,
3966                                             &pDirEnumEntry);
3967
3968         if( !NT_SUCCESS( ntStatus))
3969         {
3970
3971             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3972                           AFS_TRACE_LEVEL_WARNING,
3973                           "AFSCheckCellName entry %wZ does not exist parent FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3974                           CellName,
3975                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3976                           AFSGlobalRoot->ObjectInformation.FileId.Volume,
3977                           AFSGlobalRoot->ObjectInformation.FileId.Vnode,
3978                           AFSGlobalRoot->ObjectInformation.FileId.Unique,
3979                           ntStatus);
3980
3981             try_return( ntStatus);
3982         }
3983
3984         //
3985         // OK, we have a dir enum entry back so add it to the root node
3986         //
3987
3988         uniDirName = *CellName;
3989
3990         uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
3991         uniTargetName.MaximumLength = uniTargetName.Length;
3992         uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
3993
3994         //
3995         // Is this entry a root volume entry?
3996         //
3997
3998         if( pDirEnumEntry->FileId.Cell != AFSGlobalRoot->ObjectInformation.FileId.Cell ||
3999             pDirEnumEntry->FileId.Volume != AFSGlobalRoot->ObjectInformation.FileId.Volume)
4000         {
4001
4002             //
4003             // Build the root volume entry
4004             //
4005
4006             ntStatus = AFSBuildRootVolume( AuthGroup,
4007                                            &pDirEnumEntry->FileId,
4008                                            &pVolumeCB);
4009
4010             //
4011             // On success returns with a volume reference count held
4012             //
4013
4014             if( !NT_SUCCESS( ntStatus))
4015             {
4016                 try_return( ntStatus);
4017             }
4018
4019             *ShareDirEntry = pVolumeCB->DirectoryCB;
4020
4021             lCount = InterlockedIncrement( &pVolumeCB->DirectoryCB->DirOpenReferenceCount);
4022
4023             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4024                           AFS_TRACE_LEVEL_VERBOSE,
4025                           "AFSCheckCellName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4026                           &pVolumeCB->DirectoryCB->NameInformation.FileName,
4027                           pVolumeCB->DirectoryCB,
4028                           NULL,
4029                           lCount);
4030
4031             lCount = AFSVolumeDecrement( pVolumeCB,
4032                                          AFS_VOLUME_REFERENCE_BUILD_ROOT);
4033
4034             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4035                           AFS_TRACE_LEVEL_VERBOSE,
4036                           "AFSCheckCellName Decrement count on volume %p Cnt %d\n",
4037                           pVolumeCB,
4038                           lCount);
4039         }
4040         else
4041         {
4042
4043             lCount = InterlockedIncrement( &pDirHdr->ContentIndex);
4044
4045             pDirNode = AFSInitDirEntry( &AFSGlobalRoot->ObjectInformation,
4046                                         &uniDirName,
4047                                         &uniTargetName,
4048                                         pDirEnumEntry,
4049                                         (ULONG)lCount);
4050
4051             if( pDirNode == NULL)
4052             {
4053
4054                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4055             }
4056
4057             //
4058             // Init the short name if we have one
4059             //
4060
4061             if( pDirEnumEntry->ShortNameLength > 0)
4062             {
4063
4064                 pDirNode->NameInformation.ShortNameLength = pDirEnumEntry->ShortNameLength;
4065
4066                 RtlCopyMemory( pDirNode->NameInformation.ShortName,
4067                                pDirEnumEntry->ShortName,
4068                                pDirNode->NameInformation.ShortNameLength);
4069             }
4070
4071             AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4072                             TRUE);
4073
4074             //
4075             // Insert the node into the name tree
4076             //
4077
4078             ASSERT( ExIsResourceAcquiredExclusiveLite( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock));
4079
4080             if( pDirHdr->CaseSensitiveTreeHead == NULL)
4081             {
4082
4083                 pDirHdr->CaseSensitiveTreeHead = pDirNode;
4084             }
4085             else
4086             {
4087
4088                 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( pDirHdr->CaseSensitiveTreeHead,
4089                                                                  pDirNode)))
4090                 {
4091
4092                     AFSDeleteDirEntry( &AFSGlobalRoot->ObjectInformation,
4093                                        pDirNode);
4094
4095                     AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4096
4097                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4098                 }
4099             }
4100
4101             ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
4102
4103             if( pDirHdr->CaseInsensitiveTreeHead == NULL)
4104             {
4105
4106                 pDirHdr->CaseInsensitiveTreeHead = pDirNode;
4107
4108                 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
4109             }
4110             else
4111             {
4112
4113                 AFSInsertCaseInsensitiveDirEntry( pDirHdr->CaseInsensitiveTreeHead,
4114                                                   pDirNode);
4115             }
4116
4117             if( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead == NULL)
4118             {
4119
4120                 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead = pDirNode;
4121             }
4122             else
4123             {
4124
4125                 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
4126
4127                 pDirNode->ListEntry.bLink = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail;
4128             }
4129
4130             AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail = pDirNode;
4131
4132             SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
4133
4134             lCount = InterlockedIncrement( &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeCount);
4135
4136             AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
4137                           AFS_TRACE_LEVEL_VERBOSE,
4138                           "AFSCheckCellName Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
4139                           &pDirNode->NameInformation.FileName,
4140                           lCount,
4141                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
4142                           AFSGlobalRoot->ObjectInformation.FileId.Volume,
4143                           AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4144                           AFSGlobalRoot->ObjectInformation.FileId.Unique);
4145
4146             lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
4147
4148             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4149                           AFS_TRACE_LEVEL_VERBOSE,
4150                           "AFSCheckCellName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
4151                           &pDirNode->NameInformation.FileName,
4152                           pDirNode,
4153                           NULL,
4154                           lCount);
4155
4156             AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4157
4158             //
4159             // Pass back the dir node
4160             //
4161
4162             *ShareDirEntry = pDirNode;
4163         }
4164
4165 try_exit:
4166
4167         if( pDirEnumEntry != NULL)
4168         {
4169
4170             AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_31_TAG);
4171         }
4172     }
4173
4174     return ntStatus;
4175 }
4176
4177 NTSTATUS
4178 AFSBuildMountPointTarget( IN GUID *AuthGroup,
4179                           IN AFSDirectoryCB  *DirectoryCB,
4180                           OUT AFSVolumeCB **TargetVolumeCB)
4181 {
4182
4183     NTSTATUS ntStatus = STATUS_SUCCESS;
4184     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4185     AFSDirEnumEntry *pDirEntry = NULL;
4186     ULONGLONG       ullIndex = 0;
4187     AFSVolumeCB *pVolumeCB = NULL;
4188     AFSFileID stTargetFileID;
4189     LONG lCount;
4190     BOOLEAN bReleaseVolumeLock = FALSE;
4191
4192     __Enter
4193     {
4194
4195         //
4196         // Loop on each entry, building the chain until we encounter the final target
4197         //
4198
4199         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4200                       AFS_TRACE_LEVEL_VERBOSE_2,
4201                       "AFSBuildMountPointTarget Building target directory for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4202                       &DirectoryCB->NameInformation.FileName,
4203                       DirectoryCB->ObjectInformation->FileId.Cell,
4204                       DirectoryCB->ObjectInformation->FileId.Volume,
4205                       DirectoryCB->ObjectInformation->FileId.Vnode,
4206                       DirectoryCB->ObjectInformation->FileId.Unique);
4207
4208         //
4209         // Do we need to evaluate the node?
4210         //
4211
4212         //if( DirectoryCB->ObjectInformation->TargetFileId.Vnode == 0 &&
4213         //    DirectoryCB->ObjectInformation->TargetFileId.Unique == 0)
4214         {
4215
4216             //
4217             // Go evaluate the current target to get the target fid
4218             //
4219
4220             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4221                           AFS_TRACE_LEVEL_VERBOSE_2,
4222                           "AFSBuildMountPointTarget Evaluating target %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4223                               &DirectoryCB->NameInformation.FileName,
4224                               DirectoryCB->ObjectInformation->FileId.Cell,
4225                               DirectoryCB->ObjectInformation->FileId.Volume,
4226                               DirectoryCB->ObjectInformation->FileId.Vnode,
4227                               DirectoryCB->ObjectInformation->FileId.Unique);
4228
4229             ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
4230                                               AuthGroup,
4231                                               FALSE,
4232                                               &pDirEntry);
4233
4234             if( !NT_SUCCESS( ntStatus))
4235             {
4236
4237                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4238                               AFS_TRACE_LEVEL_ERROR,
4239                               "AFSBuildMountPointTarget Failed to evaluate target %wZ Status %08lX\n",
4240                               &DirectoryCB->NameInformation.FileName,
4241                               ntStatus);
4242                 try_return( ntStatus);
4243             }
4244
4245             if( pDirEntry->TargetFileId.Vnode == 0 &&
4246                 pDirEntry->TargetFileId.Unique == 0)
4247             {
4248
4249                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4250                               AFS_TRACE_LEVEL_ERROR,
4251                               "AFSBuildMountPointTarget Target %wZ FID %08lX-%08lX-%08lX-%08lX service returned zero FID\n",
4252                               &DirectoryCB->NameInformation.FileName,
4253                               DirectoryCB->ObjectInformation->FileId.Cell,
4254                               DirectoryCB->ObjectInformation->FileId.Volume,
4255                               DirectoryCB->ObjectInformation->FileId.Vnode,
4256                               DirectoryCB->ObjectInformation->FileId.Unique);
4257
4258                 try_return( ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED);
4259             }
4260
4261             AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
4262                             TRUE);
4263
4264             ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
4265                                             &DirectoryCB->Flags,
4266                                             (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4267                                             (USHORT)pDirEntry->TargetNameLength);
4268
4269             if( !NT_SUCCESS( ntStatus))
4270             {
4271
4272                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4273
4274                 try_return( ntStatus);
4275             }
4276
4277             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4278
4279             DirectoryCB->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
4280         }
4281
4282         stTargetFileID = DirectoryCB->ObjectInformation->TargetFileId;
4283
4284         //
4285         // Try to locate this FID. First the volume then the
4286         // entry itself
4287         //
4288
4289         ullIndex = AFSCreateHighIndex( &stTargetFileID);
4290
4291         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4292                       AFS_TRACE_LEVEL_VERBOSE,
4293                       "AFSBuildMountPointTarget Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4294                       &pDevExt->Specific.RDR.VolumeTreeLock,
4295                       PsGetCurrentThread());
4296
4297         AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4298                           TRUE);
4299
4300         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4301                       AFS_TRACE_LEVEL_VERBOSE_2,
4302                       "AFSBuildMountPointTarget Locating volume for target %I64X\n",
4303                       ullIndex);
4304
4305         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4306                                        ullIndex,
4307                                        (AFSBTreeEntry **)&pVolumeCB);
4308
4309         //
4310         // We can be processing a request for a target that is on a volume
4311         // we have never seen before.
4312         //
4313
4314         if( pVolumeCB == NULL)
4315         {
4316
4317             //
4318             // Locking is held correctly in init routine
4319             //
4320
4321             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4322
4323             //
4324             // Go init the root of the volume
4325             //
4326
4327             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4328                           AFS_TRACE_LEVEL_VERBOSE_2,
4329                           "AFSBuildMountPointTarget Initializing root for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4330                           &DirectoryCB->NameInformation.FileName,
4331                           DirectoryCB->ObjectInformation->FileId.Cell,
4332                           DirectoryCB->ObjectInformation->FileId.Volume,
4333                           DirectoryCB->ObjectInformation->FileId.Vnode,
4334                           DirectoryCB->ObjectInformation->FileId.Unique);
4335
4336             ntStatus = AFSInitVolume( AuthGroup,
4337                                       &stTargetFileID,
4338                                       AFS_VOLUME_REFERENCE_MOUNTPT,
4339                                       &pVolumeCB);
4340
4341             if( !NT_SUCCESS( ntStatus))
4342             {
4343
4344                 try_return( ntStatus);
4345             }
4346
4347             //
4348             // pVolumeCB->VolumeLock held exclusive and
4349             // pVolumeCB->VolumeReferenceCount has been incremented
4350             // pVolumeCB->RootFcb == NULL
4351             //
4352
4353             bReleaseVolumeLock = TRUE;
4354         }
4355         else
4356         {
4357
4358             //
4359             // AFSInitVolume returns with a VolumeReferenceCount
4360             // obtain one to match
4361             //
4362
4363             lCount = AFSVolumeIncrement( pVolumeCB,
4364                                          AFS_VOLUME_REFERENCE_MOUNTPT);
4365
4366             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4367                           AFS_TRACE_LEVEL_VERBOSE,
4368                           "AFSBuildMountPointTarget Increment count on volume %p Cnt %d\n",
4369                           pVolumeCB,
4370                           lCount);
4371
4372             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4373         }
4374
4375         if( pVolumeCB->RootFcb == NULL)
4376         {
4377
4378             if ( bReleaseVolumeLock == FALSE)
4379             {
4380
4381                 AFSAcquireExcl( pVolumeCB->VolumeLock,
4382                                 TRUE);
4383
4384                 bReleaseVolumeLock = TRUE;
4385             }
4386
4387             //
4388             // Initialize the root fcb for this volume
4389             //
4390
4391             ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4392                                        pVolumeCB);
4393
4394             if( !NT_SUCCESS( ntStatus))
4395             {
4396
4397                 lCount = AFSVolumeDecrement( pVolumeCB,
4398                                              AFS_VOLUME_REFERENCE_MOUNTPT);
4399
4400                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4401                               AFS_TRACE_LEVEL_VERBOSE,
4402                               "AFSBuildMountPoint Decrement count on volume %p Cnt %d\n",
4403                               pVolumeCB,
4404                               lCount);
4405
4406                 AFSReleaseResource( pVolumeCB->VolumeLock);
4407
4408                 try_return( ntStatus);
4409             }
4410
4411             //
4412             // Drop the lock acquired above
4413             //
4414
4415             AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4416         }
4417
4418         if ( bReleaseVolumeLock == TRUE)
4419         {
4420
4421             AFSReleaseResource( pVolumeCB->VolumeLock);
4422         }
4423
4424         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4425                       AFS_TRACE_LEVEL_VERBOSE_2,
4426                       "AFSBuildMountPointTarget Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4427                       &pVolumeCB->DirectoryCB->NameInformation.FileName,
4428                       pVolumeCB->ObjectInformation.FileId.Cell,
4429                       pVolumeCB->ObjectInformation.FileId.Volume,
4430                       pVolumeCB->ObjectInformation.FileId.Vnode,
4431                       pVolumeCB->ObjectInformation.FileId.Unique);
4432
4433         *TargetVolumeCB = pVolumeCB;
4434
4435 try_exit:
4436
4437         if( pDirEntry)
4438         {
4439
4440             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
4441         }
4442     }
4443
4444     return ntStatus;
4445 }
4446
4447 NTSTATUS
4448 AFSBuildRootVolume( IN GUID *AuthGroup,
4449                     IN AFSFileID *FileId,
4450                     OUT AFSVolumeCB **TargetVolumeCB)
4451 {
4452
4453     NTSTATUS ntStatus = STATUS_SUCCESS;
4454     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4455     ULONGLONG       ullIndex = 0;
4456     AFSVolumeCB *pVolumeCB = NULL;
4457     LONG lCount;
4458     BOOLEAN bReleaseVolumeLock = FALSE;
4459
4460     __Enter
4461     {
4462
4463         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4464                       AFS_TRACE_LEVEL_VERBOSE_2,
4465                       "AFSBuildRootVolume Building target volume for FID %08lX-%08lX-%08lX-%08lX\n",
4466                       FileId->Cell,
4467                       FileId->Volume,
4468                       FileId->Vnode,
4469                       FileId->Unique);
4470
4471         ullIndex = AFSCreateHighIndex( FileId);
4472
4473         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4474                       AFS_TRACE_LEVEL_VERBOSE,
4475                       "AFSBuildRootVolume Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4476                       &pDevExt->Specific.RDR.VolumeTreeLock,
4477                       PsGetCurrentThread());
4478
4479         AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4480                           TRUE);
4481
4482         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4483                       AFS_TRACE_LEVEL_VERBOSE_2,
4484                       "AFSBuildRootVolume Locating volume for target %I64X\n",
4485                       ullIndex);
4486
4487         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4488                                        ullIndex,
4489                                        (AFSBTreeEntry **)&pVolumeCB);
4490
4491         //
4492         // We can be processing a request for a target that is on a volume
4493         // we have never seen before.
4494         //
4495
4496         if( pVolumeCB == NULL)
4497         {
4498
4499             //
4500             // Locking is held correctly in init routine
4501             //
4502
4503             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4504
4505             //
4506             // Go init the root of the volume
4507             //
4508
4509             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4510                          AFS_TRACE_LEVEL_VERBOSE_2,
4511                           "AFSBuildRootVolume Initializing root for FID %08lX-%08lX-%08lX-%08lX\n",
4512                           FileId->Cell,
4513                           FileId->Volume,
4514                           FileId->Vnode,
4515                           FileId->Unique);
4516
4517             ntStatus = AFSInitVolume( AuthGroup,
4518                                       FileId,
4519                                       AFS_VOLUME_REFERENCE_BUILD_ROOT,
4520                                       &pVolumeCB);
4521
4522             if( !NT_SUCCESS( ntStatus))
4523             {
4524
4525                 try_return( ntStatus);
4526             }
4527
4528             //
4529             // pVolumeCB->VolumeLock is held exclusive
4530             // pVolumeCB->VolumeReferenceCount has been incremented
4531             // pVolumeCB->RootFcb == NULL
4532             //
4533
4534             bReleaseVolumeLock = TRUE;
4535         }
4536         else
4537         {
4538
4539             //
4540             // AFSInitVolume returns with a VolumeReferenceCount
4541             // obtain one to match
4542             //
4543
4544             lCount = AFSVolumeIncrement( pVolumeCB,
4545                                          AFS_VOLUME_REFERENCE_BUILD_ROOT);
4546
4547             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4548                           AFS_TRACE_LEVEL_VERBOSE,
4549                           "AFSBuildRootVolume Increment count on volume %p Cnt %d\n",
4550                           pVolumeCB,
4551                           lCount);
4552
4553             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4554         }
4555
4556
4557         if( pVolumeCB->RootFcb == NULL)
4558         {
4559
4560             if ( bReleaseVolumeLock == FALSE)
4561             {
4562
4563                 AFSAcquireExcl( pVolumeCB->VolumeLock,
4564                                 TRUE);
4565
4566                 bReleaseVolumeLock = TRUE;
4567             }
4568
4569             //
4570             // Initialize the root fcb for this volume
4571             //
4572
4573             ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4574                                        pVolumeCB);
4575
4576             if( !NT_SUCCESS( ntStatus))
4577             {
4578
4579                 lCount = AFSVolumeDecrement( pVolumeCB,
4580                                              AFS_VOLUME_REFERENCE_BUILD_ROOT);
4581
4582                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4583                               AFS_TRACE_LEVEL_VERBOSE,
4584                               "AFSBuildRootVolume Decrement count on volume %p Cnt %d\n",
4585                               pVolumeCB,
4586                               lCount);
4587
4588                 AFSReleaseResource( pVolumeCB->VolumeLock);
4589
4590                 try_return( ntStatus);
4591             }
4592
4593             //
4594             // Drop the lock acquired above
4595             //
4596
4597             AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4598         }
4599
4600         if ( bReleaseVolumeLock == TRUE)
4601         {
4602
4603             AFSReleaseResource( pVolumeCB->VolumeLock);
4604         }
4605
4606         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4607                       AFS_TRACE_LEVEL_VERBOSE_2,
4608                       "AFSBuildRootVolume Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4609                       &pVolumeCB->DirectoryCB->NameInformation.FileName,
4610                       pVolumeCB->ObjectInformation.FileId.Cell,
4611                       pVolumeCB->ObjectInformation.FileId.Volume,
4612                       pVolumeCB->ObjectInformation.FileId.Vnode,
4613                       pVolumeCB->ObjectInformation.FileId.Unique);
4614
4615         *TargetVolumeCB = pVolumeCB;
4616
4617 try_exit:
4618
4619         NOTHING;
4620     }
4621
4622     return ntStatus;
4623 }
4624
4625 NTSTATUS
4626 AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
4627                    IN PFILE_OBJECT FileObject,
4628                    IN UNICODE_STRING *RemainingPath,
4629                    IN GUID *AuthGroup)
4630 {
4631
4632     NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
4633     UNICODE_STRING uniReparseName;
4634     UNICODE_STRING uniMUPDeviceName;
4635     UNICODE_STRING uniIOMgrDeviceName;
4636     AFSDirEnumEntry *pDirEntry = NULL;
4637
4638     __Enter
4639     {
4640
4641         //
4642         // Build up the name to reparse
4643         //
4644
4645         RtlInitUnicodeString( &uniMUPDeviceName,
4646                               L"\\Device\\MUP");
4647
4648         RtlInitUnicodeString( &uniIOMgrDeviceName,
4649                               L"\\??\\");
4650
4651         uniReparseName.Length = 0;
4652         uniReparseName.Buffer = NULL;
4653
4654         //
4655         // Be sure we have a target name
4656         //
4657
4658         if( DirEntry->NameInformation.TargetName.Length == 0)
4659         {
4660
4661             ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
4662                                               AuthGroup,
4663                                               FALSE,
4664                                               &pDirEntry);
4665
4666             if( !NT_SUCCESS( ntStatus) ||
4667                 pDirEntry->TargetNameLength == 0)
4668             {
4669
4670                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4671                               AFS_TRACE_LEVEL_ERROR,
4672                               "AFSProcessDFSLink EvaluateTargetByID failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4673                               &DirEntry->NameInformation.FileName,
4674                               DirEntry->ObjectInformation->FileId.Cell,
4675                               DirEntry->ObjectInformation->FileId.Volume,
4676                               DirEntry->ObjectInformation->FileId.Vnode,
4677                               DirEntry->ObjectInformation->FileId.Unique,
4678                               ntStatus);
4679
4680                 if( NT_SUCCESS( ntStatus))
4681                 {
4682
4683                     ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
4684                 }
4685
4686                 try_return( ntStatus);
4687             }
4688
4689             //
4690             // Update the target name
4691             //
4692
4693             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
4694                             TRUE);
4695
4696             ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
4697                                             &DirEntry->Flags,
4698                                             (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4699                                             (USHORT)pDirEntry->TargetNameLength);
4700
4701             if( !NT_SUCCESS( ntStatus))
4702             {
4703
4704                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4705                               AFS_TRACE_LEVEL_ERROR,
4706                               "AFSProcessDFSLink UpdateTargetName failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4707                               &DirEntry->NameInformation.FileName,
4708                               DirEntry->ObjectInformation->FileId.Cell,
4709                               DirEntry->ObjectInformation->FileId.Volume,
4710                               DirEntry->ObjectInformation->FileId.Vnode,
4711                               DirEntry->ObjectInformation->FileId.Unique,
4712                               ntStatus);
4713
4714                 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4715
4716                 try_return( ntStatus);
4717             }
4718
4719             AFSConvertToShared( &DirEntry->NonPaged->Lock);
4720         }
4721         else
4722         {
4723             AFSAcquireShared( &DirEntry->NonPaged->Lock,
4724                               TRUE);
4725         }
4726
4727         uniReparseName.MaximumLength = uniMUPDeviceName.Length +
4728                                                    sizeof( WCHAR) +
4729                                                    DirEntry->NameInformation.TargetName.Length +
4730                                                    sizeof( WCHAR);
4731
4732         if( RemainingPath != NULL &&
4733             RemainingPath->Length > 0)
4734         {
4735
4736             uniReparseName.MaximumLength += RemainingPath->Length;
4737         }
4738
4739         //
4740         // Allocate the reparse buffer
4741         //
4742
4743         uniReparseName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4744                                                                    uniReparseName.MaximumLength,
4745                                                                    AFS_REPARSE_NAME_TAG);
4746
4747         if( uniReparseName.Buffer == NULL)
4748         {
4749
4750             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4751                           AFS_TRACE_LEVEL_ERROR,
4752                           "AFSProcessDFSLink uniReparseName.Buffer == NULL Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4753                           &DirEntry->NameInformation.FileName,
4754                           DirEntry->ObjectInformation->FileId.Cell,
4755                           DirEntry->ObjectInformation->FileId.Volume,
4756                           DirEntry->ObjectInformation->FileId.Vnode,
4757                           DirEntry->ObjectInformation->FileId.Unique,
4758                           STATUS_INSUFFICIENT_RESOURCES);
4759
4760             AFSReleaseResource( &DirEntry->NonPaged->Lock);
4761
4762             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4763         }
4764
4765         //
4766         // Start building the name
4767         //
4768
4769         if ( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\' &&
4770              DirEntry->NameInformation.TargetName.Buffer[ 1] == L':')
4771         {
4772
4773             RtlCopyMemory( uniReparseName.Buffer,
4774                            uniIOMgrDeviceName.Buffer,
4775                            uniIOMgrDeviceName.Length);
4776
4777             uniReparseName.Length = uniIOMgrDeviceName.Length;
4778         }
4779         else
4780         {
4781
4782             RtlCopyMemory( uniReparseName.Buffer,
4783                            uniMUPDeviceName.Buffer,
4784                            uniMUPDeviceName.Length);
4785
4786             uniReparseName.Length = uniMUPDeviceName.Length;
4787
4788             if( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\')
4789             {
4790
4791                 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
4792
4793                 uniReparseName.Length += sizeof( WCHAR);
4794             }
4795         }
4796
4797         RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
4798                        DirEntry->NameInformation.TargetName.Buffer,
4799                        DirEntry->NameInformation.TargetName.Length);
4800
4801         uniReparseName.Length += DirEntry->NameInformation.TargetName.Length;
4802
4803         AFSReleaseResource( &DirEntry->NonPaged->Lock);
4804
4805         if( RemainingPath != NULL &&
4806             RemainingPath->Length > 0)
4807         {
4808
4809             if( uniReparseName.Buffer[ (uniReparseName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
4810                 RemainingPath->Buffer[ 0] != L'\\')
4811             {
4812
4813                 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
4814
4815                 uniReparseName.Length += sizeof( WCHAR);
4816             }
4817
4818             RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
4819                            RemainingPath->Buffer,
4820                            RemainingPath->Length);
4821
4822             uniReparseName.Length += RemainingPath->Length;
4823         }
4824
4825         //
4826         // Update the name in the file object
4827         //
4828
4829         if( FileObject->FileName.Buffer != NULL)
4830         {
4831
4832             AFSExFreePoolWithTag( FileObject->FileName.Buffer, 0);
4833         }
4834
4835         FileObject->FileName = uniReparseName;
4836
4837         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4838                       AFS_TRACE_LEVEL_VERBOSE,
4839                       "AFSProcessDFSLink Reparsing access to Fcb %wZ FID %08lX-%08lX-%08lX-%08lX to %wZ\n",
4840                       &DirEntry->NameInformation.FileName,
4841                       DirEntry->ObjectInformation->FileId.Cell,
4842                       DirEntry->ObjectInformation->FileId.Volume,
4843                       DirEntry->ObjectInformation->FileId.Vnode,
4844                       DirEntry->ObjectInformation->FileId.Unique,
4845                       &uniReparseName);
4846
4847         //
4848         // Return status reparse ...
4849         //
4850
4851         ntStatus = STATUS_REPARSE;
4852
4853 try_exit:
4854
4855         if ( pDirEntry)
4856         {
4857
4858             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
4859         }
4860     }
4861
4862     return ntStatus;
4863 }