42bb7510f707db546bebbbc176159e0cd9727893
[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 NTSTATUS
42 AFSLocateNameEntry( IN GUID *AuthGroup,
43                     IN PFILE_OBJECT FileObject,
44                     IN UNICODE_STRING *RootPathName,
45                     IN UNICODE_STRING *ParsedPathName,
46                     IN AFSNameArrayHdr *NameArray,
47                     IN ULONG Flags,
48                     IN OUT AFSVolumeCB **VolumeCB,
49                     IN OUT AFSDirectoryCB **ParentDirectoryCB,
50                     OUT AFSDirectoryCB **DirectoryCB,
51                     OUT PUNICODE_STRING ComponentName)
52 {
53
54     NTSTATUS          ntStatus = STATUS_SUCCESS;
55     UNICODE_STRING    uniPathName, uniComponentName, uniRemainingPath, uniSearchName, uniFullPathName;
56     ULONG             ulCRC = 0;
57     AFSDirectoryCB   *pDirEntry = NULL, *pParentDirEntry = NULL;
58     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
59     UNICODE_STRING    uniSysName;
60     ULONG             ulSubstituteIndex = 0;
61     BOOLEAN           bSubstituteName = FALSE;
62     AFSNameArrayHdr  *pNameArray = NameArray;
63     BOOLEAN           bAllocatedSymLinkBuffer = FALSE;
64     UNICODE_STRING    uniRelativeName, uniNoOpName;
65     AFSObjectInfoCB  *pCurrentObject = NULL;
66     AFSObjectInfoCB  *pParentObjectInfo = NULL;
67     AFSVolumeCB      *pCurrentVolume = *VolumeCB;
68     BOOLEAN           bReleaseCurrentVolume = TRUE;
69     BOOLEAN           bSubstitutedName = FALSE;
70     LONG              lCount;
71
72     __Enter
73     {
74
75         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
76                       AFS_TRACE_LEVEL_VERBOSE_2,
77                       "AFSLocateNameEntry (FO: %p) Processing full name %wZ\n",
78                       FileObject,
79                       RootPathName);
80
81         RtlInitUnicodeString( &uniSysName,
82                               L"*@SYS");
83
84         RtlInitUnicodeString( &uniRelativeName,
85                               L"..");
86
87         RtlInitUnicodeString( &uniNoOpName,
88                               L".");
89
90         //
91         // Cleanup some parameters
92         //
93
94         if( ComponentName != NULL)
95         {
96
97             ComponentName->Length = 0;
98             ComponentName->MaximumLength = 0;
99             ComponentName->Buffer = NULL;
100         }
101
102         //
103         // We will parse through the filename, locating the directory nodes until we encounter a cache miss
104         // Starting at the root node
105         //
106
107         pParentDirEntry = NULL;
108
109         pDirEntry = *ParentDirectoryCB;
110
111         uniPathName = *ParsedPathName;
112
113         uniFullPathName = *RootPathName;
114
115         uniComponentName.Length = uniComponentName.MaximumLength = 0;
116         uniComponentName.Buffer = NULL;
117
118         uniRemainingPath.Length = uniRemainingPath.MaximumLength = 0;
119         uniRemainingPath.Buffer = NULL;
120
121         uniSearchName.Length = uniSearchName.MaximumLength = 0;
122         uniSearchName.Buffer = NULL;
123
124         while( TRUE)
125         {
126
127             ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
128
129             ASSERT( pDirEntry->DirOpenReferenceCount > 0);
130
131             //
132             // Check our total link count for this name array
133             //
134
135             if( pNameArray->LinkCount >= (LONG)pDevExt->Specific.RDR.MaxLinkCount)
136             {
137
138                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
139             }
140
141             pCurrentObject = pDirEntry->ObjectInformation;
142
143             KeQueryTickCount( &pCurrentObject->LastAccessCount);
144
145             //
146             // Check that the directory entry is not deleted or pending delete
147             //
148
149             if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
150             {
151
152                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
153                               AFS_TRACE_LEVEL_ERROR,
154                               "AFSLocateNameEntry (FO: %p) Deleted parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
155                               FileObject,
156                               &pDirEntry->NameInformation.FileName,
157                               pCurrentObject->FileId.Cell,
158                               pCurrentObject->FileId.Volume,
159                               pCurrentObject->FileId.Vnode,
160                               pCurrentObject->FileId.Unique,
161                               STATUS_FILE_DELETED);
162
163                 try_return( ntStatus = STATUS_FILE_DELETED);
164             }
165
166             if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
167             {
168
169                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
170                               AFS_TRACE_LEVEL_ERROR,
171                               "AFSLocateNameEntry (FO: %p) Delete pending on %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
172                               FileObject,
173                               &pDirEntry->NameInformation.FileName,
174                               pCurrentObject->FileId.Cell,
175                               pCurrentObject->FileId.Volume,
176                               pCurrentObject->FileId.Vnode,
177                               pCurrentObject->FileId.Unique,
178                               STATUS_DELETE_PENDING);
179
180                 try_return( ntStatus = STATUS_DELETE_PENDING);
181             }
182
183             //
184             // Check if the directory requires verification
185             //
186
187             if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
188                 ( pCurrentObject->FileType != AFS_FILE_TYPE_DIRECTORY ||
189                   !AFSIsEnumerationInProcess( pCurrentObject)))
190             {
191
192                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
193                               AFS_TRACE_LEVEL_VERBOSE,
194                               "AFSLocateNameEntry (FO: %p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
195                               FileObject,
196                               &pDirEntry->NameInformation.FileName,
197                               pCurrentObject->FileId.Cell,
198                               pCurrentObject->FileId.Volume,
199                               pCurrentObject->FileId.Vnode,
200                               pCurrentObject->FileId.Unique);
201
202                 //
203                 // Directory TreeLock should be exclusively held
204                 //
205
206                 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
207                                 TRUE);
208
209                 ntStatus = AFSVerifyEntry( AuthGroup,
210                                            pDirEntry);
211
212                 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
213
214                 if( !NT_SUCCESS( ntStatus))
215                 {
216
217                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
218                                   AFS_TRACE_LEVEL_ERROR,
219                                   "AFSLocateNameEntry (FO: %p) Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
220                                   FileObject,
221                                   &pDirEntry->NameInformation.FileName,
222                                   pCurrentObject->FileId.Cell,
223                                   pCurrentObject->FileId.Volume,
224                                   pCurrentObject->FileId.Vnode,
225                                   pCurrentObject->FileId.Unique,
226                                   ntStatus);
227
228                     try_return( ntStatus);
229                 }
230             }
231
232             //
233             // Ensure the parent node has been evaluated, if not then go do it now
234             //
235
236             if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) ||
237                 pCurrentObject->FileType == AFS_FILE_TYPE_UNKNOWN)
238             {
239
240                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
241                               AFS_TRACE_LEVEL_VERBOSE,
242                               "AFSLocateNameEntry (FO: %p) Evaluating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
243                               FileObject,
244                               &pDirEntry->NameInformation.FileName,
245                               pCurrentObject->FileId.Cell,
246                               pCurrentObject->FileId.Volume,
247                               pCurrentObject->FileId.Vnode,
248                               pCurrentObject->FileId.Unique);
249
250                 ntStatus = AFSEvaluateNode( AuthGroup,
251                                             pDirEntry);
252
253                 if( !NT_SUCCESS( ntStatus))
254                 {
255
256                     if ( ntStatus == STATUS_NOT_A_DIRECTORY)
257                     {
258
259                         if ( pCurrentObject->ParentObjectInformation == NULL)
260                         {
261
262                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
263                                           AFS_TRACE_LEVEL_ERROR,
264                                           "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT NULL Status %08lX\n",
265                                           FileObject,
266                                           &pDirEntry->NameInformation.FileName,
267                                           pCurrentObject->FileId.Cell,
268                                           pCurrentObject->FileId.Volume,
269                                           pCurrentObject->FileId.Vnode,
270                                           pCurrentObject->FileId.Unique,
271                                           ntStatus);
272                         }
273                         else
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 %08lX-%08lX-%08lX-%08lX 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                                           pCurrentObject->ParentObjectInformation->FileId.Cell,
286                                           pCurrentObject->ParentObjectInformation->FileId.Volume,
287                                           pCurrentObject->ParentObjectInformation->FileId.Vnode,
288                                           pCurrentObject->ParentObjectInformation->FileId.Unique,
289                                           ntStatus);
290                         }
291                     }
292                     else
293                     {
294                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
295                                       AFS_TRACE_LEVEL_ERROR,
296                                       "AFSLocateNameEntry (FO: %p) Failed to evaluate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
297                                       FileObject,
298                                       &pDirEntry->NameInformation.FileName,
299                                       pCurrentObject->FileId.Cell,
300                                       pCurrentObject->FileId.Volume,
301                                       pCurrentObject->FileId.Vnode,
302                                       pCurrentObject->FileId.Unique,
303                                       ntStatus);
304                     }
305
306                     try_return( ntStatus);
307                 }
308
309                 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
310             }
311
312             //
313             // If this is a mount point or symlink then go get the real directory node
314             //
315
316             switch( pCurrentObject->FileType)
317             {
318
319                 case AFS_FILE_TYPE_SYMLINK:
320                 {
321
322                     UNICODE_STRING uniTempName;
323                     WCHAR *pTmpBuffer = NULL;
324                     LONG lLinkCount = 0;
325
326                     //
327                     // Check if the flag is set to NOT evaluate a symlink
328                     // and we are done with the parsing
329                     //
330
331                     if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL) &&
332                         uniRemainingPath.Length == 0)
333                     {
334
335                         //
336                         // Pass back the directory entries
337                         //
338
339                         *ParentDirectoryCB = pParentDirEntry;
340
341                         *DirectoryCB = pDirEntry;
342
343                         *VolumeCB = pCurrentVolume;
344
345                         *RootPathName = uniFullPathName;
346
347                         try_return( ntStatus);
348                     }
349
350                     AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
351                                     TRUE);
352
353                     AFSAcquireExcl( &pDirEntry->NonPaged->Lock,
354                                     TRUE);
355
356                     if( pDirEntry->NameInformation.TargetName.Length == 0)
357                     {
358
359                         //
360                         // We'll reset the DV to ensure we validate the metadata content
361                         //
362
363                         pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
364
365                         SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
366
367                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
368                                       AFS_TRACE_LEVEL_VERBOSE,
369                                       "AFSLocateNameEntry (FO: %p) Verifying symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
370                                       FileObject,
371                                       &pDirEntry->NameInformation.FileName,
372                                       pCurrentObject->FileId.Cell,
373                                       pCurrentObject->FileId.Volume,
374                                       pCurrentObject->FileId.Vnode,
375                                       pCurrentObject->FileId.Unique);
376
377                         //
378                         // Directory TreeLock should be exclusively held
379                         //
380
381                         ntStatus = AFSVerifyEntry( AuthGroup,
382                                                    pDirEntry);
383
384                         AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
385
386                         if( !NT_SUCCESS( ntStatus))
387                         {
388
389                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
390                                           AFS_TRACE_LEVEL_ERROR,
391                                           "AFSLocateNameEntry (FO: %p) Failed to verify symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
392                                           FileObject,
393                                           &pDirEntry->NameInformation.FileName,
394                                           pCurrentObject->FileId.Cell,
395                                           pCurrentObject->FileId.Volume,
396                                           pCurrentObject->FileId.Vnode,
397                                           pCurrentObject->FileId.Unique,
398                                           ntStatus);
399
400                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
401
402                             try_return( ntStatus);
403                         }
404
405                         //
406                         // If the type changed then reprocess this entry
407                         //
408
409                         if( pCurrentObject->FileType != AFS_FILE_TYPE_SYMLINK)
410                         {
411
412                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
413
414                             continue;
415                         }
416                     }
417                     else
418                     {
419
420                         AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
421                     }
422
423                     //
424                     // If we were given a zero length target name then deny access to the entry
425                     //
426
427                     if( pDirEntry->NameInformation.TargetName.Length == 0)
428                     {
429
430                         ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
431
432                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
433                                       AFS_TRACE_LEVEL_ERROR,
434                                       "AFSLocateNameEntry (FO: %p) Failed to retrieve target name for symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
435                                       FileObject,
436                                       &pDirEntry->NameInformation.FileName,
437                                       pCurrentObject->FileId.Cell,
438                                       pCurrentObject->FileId.Volume,
439                                       pCurrentObject->FileId.Vnode,
440                                       pCurrentObject->FileId.Unique,
441                                       ntStatus);
442
443                         AFSReleaseResource( &pDirEntry->NonPaged->Lock);
444
445                         try_return( ntStatus);
446                     }
447
448                     if( AFSIsRelativeName( &pDirEntry->NameInformation.TargetName))
449                     {
450
451                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
452                                       AFS_TRACE_LEVEL_VERBOSE,
453                                       "AFSLocateNameEntry (FO: %p) Processing relative symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
454                                       FileObject,
455                                       &pDirEntry->NameInformation.TargetName,
456                                       &pDirEntry->NameInformation.FileName,
457                                       pCurrentObject->FileId.Cell,
458                                       pCurrentObject->FileId.Volume,
459                                       pCurrentObject->FileId.Vnode,
460                                       pCurrentObject->FileId.Unique);
461
462                         //
463                         // We'll substitute this name into the current process name
464                         // starting at where we sit in the path
465                         //
466
467                         uniTempName.Length = 0;
468                         uniTempName.MaximumLength = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer) +
469                                                                     pDirEntry->NameInformation.TargetName.Length +
470                                                                     sizeof( WCHAR) +
471                                                                     uniRemainingPath.Length;
472
473                         uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
474                                                                                 uniTempName.MaximumLength,
475                                                                                 AFS_NAME_BUFFER_ONE_TAG);
476
477                         if( uniTempName.Buffer == NULL)
478                         {
479
480                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
481
482                             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
483                         }
484
485                         //
486                         // We have so first copy in the portion up to the component
487                         // name
488                         //
489
490                         RtlCopyMemory( uniTempName.Buffer,
491                                        uniFullPathName.Buffer,
492                                        (ULONG)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer));
493
494                         uniTempName.Length = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer);
495
496                         if( bAllocatedSymLinkBuffer ||
497                             bSubstitutedName)
498                         {
499
500                             pTmpBuffer = uniFullPathName.Buffer;
501                         }
502
503                         bAllocatedSymLinkBuffer = TRUE;
504
505                         //
506                         // Have we parsed this name yet? Better have at least once ...
507                         //
508
509                         if( uniComponentName.Length == 0)
510                         {
511                             ASSERT( FALSE);
512                         }
513
514                         //
515                         // Copy in the target name ...
516                         //
517
518                         RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
519                                        pDirEntry->NameInformation.TargetName.Buffer,
520                                        pDirEntry->NameInformation.TargetName.Length);
521
522                         uniPathName.Buffer = &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)];
523
524                         uniPathName.Length += pDirEntry->NameInformation.TargetName.Length;
525                         uniPathName.MaximumLength = uniTempName.MaximumLength;
526
527                         uniTempName.Length += pDirEntry->NameInformation.TargetName.Length;
528
529                         //
530                         // And now any remaining portion of the name
531                         //
532
533                         if( uniRemainingPath.Length > 0)
534                         {
535
536                             if( uniRemainingPath.Buffer[ 0] != L'\\')
537                             {
538
539                                 uniRemainingPath.Buffer--;
540                                 uniRemainingPath.Length += sizeof( WCHAR);
541
542                                 uniPathName.Length += sizeof( WCHAR);
543                             }
544
545                             RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
546                                            uniRemainingPath.Buffer,
547                                            uniRemainingPath.Length);
548
549                             uniTempName.Length += uniRemainingPath.Length;
550                         }
551
552                         uniFullPathName = uniTempName;
553
554                         if( pTmpBuffer != NULL)
555                         {
556
557                             AFSExFreePoolWithTag( pTmpBuffer, 0);
558                         }
559
560                         AFSReleaseResource( &pDirEntry->NonPaged->Lock);
561
562                         //
563                         // Dereference the current entry ..
564                         //
565
566                         lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
567
568                         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
569                                       AFS_TRACE_LEVEL_VERBOSE,
570                                       "AFSLocateNameEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
571                                       &pDirEntry->NameInformation.FileName,
572                                       pDirEntry,
573                                       NULL,
574                                       lCount);
575
576                         ASSERT( lCount >= 0);
577
578                         //
579                         // OK, need to back up one entry for the correct parent since the current
580                         // entry we are on is the symlink itself
581                         //
582
583                         pDirEntry = AFSBackupEntry( pNameArray);
584
585                         //
586                         // Increment our reference on this dir entry
587                         //
588
589                         lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
590
591                         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
592                                       AFS_TRACE_LEVEL_VERBOSE,
593                                       "AFSLocateNameEntry Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
594                                       &pDirEntry->NameInformation.FileName,
595                                       pDirEntry,
596                                       NULL,
597                                       lCount);
598
599                         if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
600                         {
601
602                             pParentDirEntry = NULL;
603                         }
604                         else
605                         {
606
607                             pParentDirEntry = AFSGetParentEntry( pNameArray);
608
609                             ASSERT( pParentDirEntry != pDirEntry);
610                         }
611                     }
612                     else
613                     {
614
615                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
616                                       AFS_TRACE_LEVEL_VERBOSE,
617                                       "AFSLocateNameEntry (FO: %p) Processing absolute symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
618                                       FileObject,
619                                       &pDirEntry->NameInformation.TargetName,
620                                       &pDirEntry->NameInformation.FileName,
621                                       pCurrentObject->FileId.Cell,
622                                       pCurrentObject->FileId.Volume,
623                                       pCurrentObject->FileId.Vnode,
624                                       pCurrentObject->FileId.Unique);
625
626                         if ( !AFSIsAbsoluteAFSName( &pDirEntry->NameInformation.TargetName))
627                         {
628
629                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
630                                           AFS_TRACE_LEVEL_ERROR,
631                                           "AFSLocateNameEntry Name %wZ contains invalid server name\n",
632                                           &pDirEntry->NameInformation.TargetName);
633
634                             //
635                             // The correct response would be STATUS_OBJECT_PATH_INVALID
636                             // but that prevents cmd.exe from performing a recursive
637                             // directory enumeration when opening a directory entry
638                             // that represents a symlink to an invalid path is discovered.
639                             //
640
641                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
642
643                             try_return( ntStatus = STATUS_OBJECT_PATH_NOT_FOUND);
644                         }
645
646                         //
647                         // We'll substitute this name into the current process name
648                         // starting at where we sit in the path
649                         //
650
651                         uniTempName.Length = 0;
652                         uniTempName.MaximumLength = pDirEntry->NameInformation.TargetName.Length +
653                                                                     sizeof( WCHAR) +
654                                                                     uniRemainingPath.Length;
655
656                         uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
657                                                                                 uniTempName.MaximumLength,
658                                                                                 AFS_NAME_BUFFER_TWO_TAG);
659
660                         if( uniTempName.Buffer == NULL)
661                         {
662
663                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
664
665                             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
666                         }
667
668                         if( bAllocatedSymLinkBuffer ||
669                             bSubstitutedName)
670                         {
671
672                             pTmpBuffer = uniFullPathName.Buffer;
673                         }
674
675                         bAllocatedSymLinkBuffer = TRUE;
676
677                         //
678                         // Have we parsed this name yet? Better have at least once ...
679                         //
680
681                         if( uniComponentName.Length == 0)
682                         {
683                             ASSERT( FALSE);
684                         }
685
686                         //
687                         // Copy in the target name ...
688                         //
689
690                         RtlCopyMemory( uniTempName.Buffer,
691                                        &pDirEntry->NameInformation.TargetName.Buffer[ AFSMountRootName.Length/sizeof( WCHAR)],
692                                        pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length);
693
694                         uniTempName.Length = pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length;
695
696                         //
697                         // And now any remaining portion of the name
698                         //
699
700                         if( uniRemainingPath.Length > 0)
701                         {
702
703                             if( uniRemainingPath.Buffer[ 0] != L'\\')
704                             {
705
706                                 uniRemainingPath.Buffer--;
707                                 uniRemainingPath.Length += sizeof( WCHAR);
708                             }
709
710                             RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
711                                            uniRemainingPath.Buffer,
712                                            uniRemainingPath.Length);
713
714                             uniTempName.Length += uniRemainingPath.Length;
715                         }
716
717                         uniFullPathName = uniTempName;
718
719                         uniPathName = uniTempName;
720
721                         if( pTmpBuffer != NULL)
722                         {
723
724                             AFSExFreePoolWithTag( pTmpBuffer, 0);
725                         }
726
727                         AFSReleaseResource( &pDirEntry->NonPaged->Lock);
728
729                         //
730                         // If our current volume is not the global root then make it so ...
731                         //
732
733                         if( pCurrentVolume != AFSGlobalRoot)
734                         {
735
736                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
737                                           AFS_TRACE_LEVEL_VERBOSE,
738                                           "AFSLocateNameEntry (FO: %p) Current volume not global, resetting for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
739                                           FileObject,
740                                           &pDirEntry->NameInformation.FileName,
741                                           pCurrentObject->FileId.Cell,
742                                           pCurrentObject->FileId.Volume,
743                                           pCurrentObject->FileId.Vnode,
744                                           pCurrentObject->FileId.Unique);
745
746                             lCount = InterlockedDecrement( &pCurrentVolume->VolumeReferenceCount);
747
748                             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
749                                           AFS_TRACE_LEVEL_VERBOSE,
750                                           "AFSLocateNameEntry Decrement count on volume %p Cnt %d\n",
751                                           pCurrentVolume,
752                                           lCount);
753
754                             pCurrentVolume = AFSGlobalRoot;
755
756                             lCount = InterlockedIncrement( &pCurrentVolume->VolumeReferenceCount);
757
758                             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
759                                           AFS_TRACE_LEVEL_VERBOSE,
760                                           "AFSLocateNameEntry Increment count on volume %p Cnt %d\n",
761                                           pCurrentVolume,
762                                           lCount);
763                         }
764
765                         //
766                         // Dereference our current dir entry
767                         //
768
769                         lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
770
771                         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
772                                       AFS_TRACE_LEVEL_VERBOSE,
773                                       "AFSLocateNameEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
774                                       &pDirEntry->NameInformation.FileName,
775                                       pDirEntry,
776                                       NULL,
777                                       lCount);
778
779                         ASSERT( lCount >= 0);
780
781                         pDirEntry = pCurrentVolume->DirectoryCB;
782
783                         //
784                         // Reference the new dir entry
785                         //
786
787                         lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
788
789                         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
790                                       AFS_TRACE_LEVEL_VERBOSE,
791                                       "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
792                                       &pDirEntry->NameInformation.FileName,
793                                       pDirEntry,
794                                       NULL,
795                                       lCount);
796
797                         //
798                         // Reset the name array
799                         // Persist the link count in the name array
800                         //
801
802                         lLinkCount = pNameArray->LinkCount;
803
804                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
805                                       AFS_TRACE_LEVEL_VERBOSE,
806                                       "AFSLocateNameEntry (FO: %p) Resetting name array for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
807                                       FileObject,
808                                       &pDirEntry->NameInformation.FileName,
809                                       pCurrentObject->FileId.Cell,
810                                       pCurrentObject->FileId.Volume,
811                                       pCurrentObject->FileId.Vnode,
812                                       pCurrentObject->FileId.Unique);
813
814                         AFSResetNameArray( pNameArray,
815                                            pDirEntry);
816
817                         pNameArray->LinkCount = lLinkCount;
818
819                         pParentDirEntry = NULL;
820                     }
821
822                     //
823                     // Increment our link count
824                     //
825
826                     lCount = InterlockedIncrement( &pNameArray->LinkCount);
827
828                     continue;
829                 }
830
831                 case AFS_FILE_TYPE_MOUNTPOINT:
832                 {
833
834                     //
835                     // Check if the flag is set to NOT evaluate a mount point
836                     // and we are done with the parsing
837                     //
838
839                     if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL) &&
840                         uniRemainingPath.Length == 0)
841                     {
842
843                         //
844                         // Pass back the directory entries
845                         //
846
847                         *ParentDirectoryCB = pParentDirEntry;
848
849                         *DirectoryCB = pDirEntry;
850
851                         *VolumeCB = pCurrentVolume;
852
853                         *RootPathName = uniFullPathName;
854
855                         try_return( ntStatus);
856                     }
857
858                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
859                                   AFS_TRACE_LEVEL_VERBOSE,
860                                   "AFSLocateNameEntry (FO: %p) Building MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
861                                   FileObject,
862                                   &pDirEntry->NameInformation.FileName,
863                                   pCurrentObject->FileId.Cell,
864                                   pCurrentObject->FileId.Volume,
865                                   pCurrentObject->FileId.Vnode,
866                                   pCurrentObject->FileId.Unique);
867
868                     //
869                     // Go retrieve the target entry for this node
870                     // Release the current volume cb entry since we would
871                     // have lock inversion in the following call
872                     // Also decrement the ref count on the volume
873                     //
874
875                     ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
876
877                     lCount = InterlockedDecrement( &pCurrentVolume->VolumeReferenceCount);
878
879                     AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
880                                   AFS_TRACE_LEVEL_VERBOSE,
881                                   "AFSLocateNameEntry Decrement2 count on volume %p Cnt %d\n",
882                                   pCurrentVolume,
883                                   lCount);
884
885                     ntStatus = AFSBuildMountPointTarget( AuthGroup,
886                                                          pDirEntry,
887                                                          &pCurrentVolume);
888
889                     if( !NT_SUCCESS( ntStatus))
890                     {
891
892                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
893                                       AFS_TRACE_LEVEL_ERROR,
894                                       "AFSLocateNameEntry (FO: %p) Failed to build MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
895                                       FileObject,
896                                       &pDirEntry->NameInformation.FileName,
897                                       pCurrentObject->FileId.Cell,
898                                       pCurrentObject->FileId.Volume,
899                                       pCurrentObject->FileId.Vnode,
900                                       pCurrentObject->FileId.Unique,
901                                       ntStatus);
902
903                         //
904                         // We already decremented the current volume above
905                         //
906
907                         bReleaseCurrentVolume = FALSE;
908
909                         try_return( ntStatus);
910                     }
911
912                     ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
913
914                     //
915                     // We want to restart processing here on the new parent ...
916                     // Deref and ref count the entries
917                     //
918
919                     lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
920
921                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
922                                   AFS_TRACE_LEVEL_VERBOSE,
923                                   "AFSLocateNameEntry Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
924                                   &pDirEntry->NameInformation.FileName,
925                                   pDirEntry,
926                                   NULL,
927                                   lCount);
928
929                     ASSERT( lCount >= 0);
930
931                     pDirEntry = pCurrentVolume->DirectoryCB;
932
933                     lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
934
935                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
936                                   AFS_TRACE_LEVEL_VERBOSE,
937                                   "AFSLocateNameEntry Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
938                                   &pDirEntry->NameInformation.FileName,
939                                   pDirEntry,
940                                   NULL,
941                                   lCount);
942
943                     //
944                     // The name array stores both the mount point and the target.
945                     // Insert the target.
946                     //
947
948                     AFSInsertNextElement( pNameArray,
949                                           pDirEntry);
950
951                     pParentDirEntry = NULL;
952
953                     //
954                     // Increment our link count
955                     //
956
957                     lCount = InterlockedIncrement( &pNameArray->LinkCount);
958
959                     continue;
960                 }
961
962                 case AFS_FILE_TYPE_DFSLINK:
963                 {
964
965                     if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL))
966                     {
967
968                         //
969                         // Pass back the directory entries
970                         //
971
972                         *ParentDirectoryCB = pParentDirEntry;
973
974                         *DirectoryCB = pDirEntry;
975
976                         *VolumeCB = pCurrentVolume;
977
978                         *RootPathName = uniFullPathName;
979
980                         try_return( ntStatus);
981                     }
982
983                     //
984                     // This is a DFS link so we need to update the file name and return STATUS_REPARSE to the
985                     // system for it to reevaluate it
986                     //
987
988                     if( FileObject != NULL)
989                     {
990
991                         ntStatus = AFSProcessDFSLink( pDirEntry,
992                                                       FileObject,
993                                                       &uniRemainingPath,
994                                                       AuthGroup);
995                     }
996                     else
997                     {
998
999                         //
1000                         // This is where we have been re-entered from an NP evaluation call via the BuildBranch()
1001                         // routine.
1002                         //
1003
1004                         ntStatus = STATUS_INVALID_PARAMETER;
1005                     }
1006
1007                     if( ntStatus != STATUS_SUCCESS &&
1008                         ntStatus != STATUS_REPARSE)
1009                     {
1010
1011                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1012                                       AFS_TRACE_LEVEL_ERROR,
1013                                       "AFSLocateNameEntry (FO: %p) Failed to process DFSLink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1014                                       FileObject,
1015                                       &pDirEntry->NameInformation.FileName,
1016                                       pCurrentObject->FileId.Cell,
1017                                       pCurrentObject->FileId.Volume,
1018                                       pCurrentObject->FileId.Vnode,
1019                                       pCurrentObject->FileId.Unique,
1020                                       ntStatus);
1021                     }
1022
1023                     try_return( ntStatus);
1024                 }
1025
1026                 case AFS_FILE_TYPE_UNKNOWN:
1027                 case AFS_FILE_TYPE_INVALID:
1028                 {
1029
1030                     //
1031                     // Something was not processed ...
1032                     //
1033
1034                     try_return( ntStatus = STATUS_ACCESS_DENIED);
1035                 }
1036
1037             }   /* end of switch */
1038
1039             //
1040             // If the parent is not initialized then do it now
1041             //
1042
1043             if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1044                 !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1045             {
1046
1047                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1048                               AFS_TRACE_LEVEL_VERBOSE,
1049                               "AFSLocateNameEntry (FO: %p) Enumerating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1050                               FileObject,
1051                               &pDirEntry->NameInformation.FileName,
1052                               pCurrentObject->FileId.Cell,
1053                               pCurrentObject->FileId.Volume,
1054                               pCurrentObject->FileId.Vnode,
1055                               pCurrentObject->FileId.Unique);
1056
1057                 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1058                                 TRUE);
1059
1060                 if( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1061                 {
1062
1063                     ntStatus = AFSEnumerateDirectory( AuthGroup,
1064                                                       pCurrentObject,
1065                                                       TRUE);
1066
1067                     if( !NT_SUCCESS( ntStatus))
1068                     {
1069
1070                         AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1071
1072                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1073                                       AFS_TRACE_LEVEL_ERROR,
1074                                       "AFSLocateNameEntry (FO: %p) Failed to enumerate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1075                                       FileObject,
1076                                       &pDirEntry->NameInformation.FileName,
1077                                       pCurrentObject->FileId.Cell,
1078                                       pCurrentObject->FileId.Volume,
1079                                       pCurrentObject->FileId.Vnode,
1080                                       pCurrentObject->FileId.Unique,
1081                                       ntStatus);
1082
1083                         try_return( ntStatus);
1084                     }
1085
1086                     SetFlag( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1087                 }
1088
1089                 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1090             }
1091             else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1092             {
1093
1094                 if( uniPathName.Length > 0)
1095                 {
1096
1097                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1098                                   AFS_TRACE_LEVEL_ERROR,
1099                                   "AFSLocateNameEntry (FO: %p) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1100                                   FileObject,
1101                                   &pDirEntry->NameInformation.FileName,
1102                                   pCurrentObject->FileId.Cell,
1103                                   pCurrentObject->FileId.Volume,
1104                                   pCurrentObject->FileId.Vnode,
1105                                   pCurrentObject->FileId.Unique);
1106
1107                     // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1108                     // one of the components of the path is not a directory.  However, returning
1109                     // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1110                     // Instead IIS insists on treating the target file as if it is a directory containing
1111                     // a potential web.config file.  NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1112                     // AFS will follow suit.
1113
1114                     ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1115                 }
1116                 else
1117                 {
1118
1119                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1120                                   AFS_TRACE_LEVEL_VERBOSE,
1121                                   "AFSLocateNameEntry (FO: %p) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\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                     //
1130                     // Pass back the directory entries
1131                     //
1132
1133                     *ParentDirectoryCB = pParentDirEntry;
1134
1135                     *DirectoryCB = pDirEntry;
1136
1137                     *VolumeCB = pCurrentVolume;
1138
1139                     *RootPathName = uniFullPathName;
1140                 }
1141
1142                 try_return( ntStatus);
1143             }
1144
1145             //
1146             // If we are at the end of the processing, set our returned information and get out
1147             //
1148
1149             if( uniPathName.Length == 0)
1150             {
1151
1152                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1153                               AFS_TRACE_LEVEL_VERBOSE,
1154                               "AFSLocateNameEntry (FO: %p) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1155                               FileObject,
1156                               &pDirEntry->NameInformation.FileName,
1157                               pCurrentObject->FileId.Cell,
1158                               pCurrentObject->FileId.Volume,
1159                               pCurrentObject->FileId.Vnode,
1160                               pCurrentObject->FileId.Unique);
1161
1162                 //
1163                 // Pass back the directory entries
1164                 //
1165
1166                 *ParentDirectoryCB = pParentDirEntry;
1167
1168                 *DirectoryCB = pDirEntry;
1169
1170                 *VolumeCB = pCurrentVolume;
1171
1172                 *RootPathName = uniFullPathName;
1173
1174                 try_return( ntStatus);
1175             }
1176
1177             //
1178             // We may have returned to the top of the while( TRUE)
1179             //
1180             if( bSubstituteName &&
1181                 uniSearchName.Buffer != NULL)
1182             {
1183
1184                 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1185
1186                 bSubstituteName = FALSE;
1187
1188                 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1189                 uniSearchName.Buffer = NULL;
1190             }
1191
1192             ulSubstituteIndex = 1;
1193
1194             ntStatus = STATUS_SUCCESS;
1195
1196             //
1197             // Get the next component name
1198             //
1199
1200             FsRtlDissectName( uniPathName,
1201                               &uniComponentName,
1202                               &uniRemainingPath);
1203
1204             //
1205             // Check for the . and .. in the path
1206             //
1207
1208             if( RtlCompareUnicodeString( &uniComponentName,
1209                                          &uniNoOpName,
1210                                          TRUE) == 0)
1211             {
1212
1213                 uniPathName = uniRemainingPath;
1214
1215                 continue;
1216             }
1217
1218             if( RtlCompareUnicodeString( &uniComponentName,
1219                                          &uniRelativeName,
1220                                          TRUE) == 0)
1221             {
1222
1223                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1224                               AFS_TRACE_LEVEL_VERBOSE,
1225                               "AFSLocateNameEntry (FO: %p) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1226                               FileObject,
1227                               &pDirEntry->NameInformation.FileName,
1228                               pCurrentObject->FileId.Cell,
1229                               pCurrentObject->FileId.Volume,
1230                               pCurrentObject->FileId.Vnode,
1231                               pCurrentObject->FileId.Unique);
1232
1233                 //
1234                 // Need to back up one entry in the name array
1235                 //
1236                 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1237
1238                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1239                               AFS_TRACE_LEVEL_VERBOSE,
1240                               "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1241                               &pDirEntry->NameInformation.FileName,
1242                               pDirEntry,
1243                               NULL,
1244                               lCount);
1245
1246                 ASSERT( lCount >= 0);
1247
1248                 pDirEntry = AFSBackupEntry( NameArray);
1249
1250                 if( pDirEntry == NULL)
1251                 {
1252
1253                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1254                                   AFS_TRACE_LEVEL_ERROR,
1255                                   "AFSLocateNameEntry AFSBackupEntry failed\n");
1256
1257                     try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1258                 }
1259
1260                 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1261
1262                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1263                               AFS_TRACE_LEVEL_VERBOSE,
1264                               "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1265                               &pDirEntry->NameInformation.FileName,
1266                               pDirEntry,
1267                               NULL,
1268                               lCount);
1269
1270                 if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1271                 {
1272
1273                     pParentDirEntry = NULL;
1274                 }
1275                 else
1276                 {
1277
1278                     pParentDirEntry = AFSGetParentEntry( pNameArray);
1279
1280                     ASSERT( pParentDirEntry != pDirEntry);
1281                 }
1282
1283                 uniPathName = uniRemainingPath;
1284
1285                 continue;
1286             }
1287
1288             //
1289             // Update our pointers
1290             //
1291
1292             pParentDirEntry = pDirEntry;
1293
1294             pDirEntry = NULL;
1295
1296             uniSearchName = uniComponentName;
1297
1298             while( pDirEntry == NULL)
1299             {
1300
1301                 //
1302                 // If the SearchName contains @SYS then we perform the substitution.
1303                 // If there is no substitution we give up.
1304                 //
1305
1306                 if( !bSubstituteName &&
1307                     FsRtlIsNameInExpression( &uniSysName,
1308                                              &uniSearchName,
1309                                              TRUE,
1310                                              NULL))
1311                 {
1312
1313                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1314                                   AFS_TRACE_LEVEL_VERBOSE_2,
1315                                   "AFSLocateNameEntry (FO: %p) Processing @SYS substitution for %wZ Index %08lX\n",
1316                                   FileObject,
1317                                   &uniComponentName,
1318                                   ulSubstituteIndex);
1319
1320                     ntStatus = AFSSubstituteSysName( &uniComponentName,
1321                                                      &uniSearchName,
1322                                                      ulSubstituteIndex);
1323
1324                     if ( NT_SUCCESS( ntStatus))
1325                     {
1326
1327                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1328                                       AFS_TRACE_LEVEL_VERBOSE_2,
1329                                       "AFSLocateNameEntry (FO: %p) Located substitution %wZ for %wZ Index %08lX\n",
1330                                       FileObject,
1331                                       &uniSearchName,
1332                                       &uniComponentName,
1333                                       ulSubstituteIndex);
1334
1335                         //
1336                         // Go reparse the name again
1337                         //
1338
1339                         bSubstituteName = TRUE;
1340
1341                         ulSubstituteIndex++; // For the next entry, if needed
1342
1343                         continue;   // while( pDirEntry == NULL)
1344                     }
1345                     else
1346                     {
1347
1348                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1349                                       AFS_TRACE_LEVEL_ERROR,
1350                                       "AFSLocateNameEntry (FO: %p) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1351                                       FileObject,
1352                                       &uniComponentName,
1353                                       ulSubstituteIndex,
1354                                       ntStatus);
1355
1356                         if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1357                         {
1358
1359                             //
1360                             // Pass back the directory entries
1361                             //
1362
1363                             *ParentDirectoryCB = pParentDirEntry;
1364
1365                             *DirectoryCB = NULL;
1366
1367                             *VolumeCB = pCurrentVolume;
1368
1369                             if( ComponentName != NULL)
1370                             {
1371
1372                                 *ComponentName = uniComponentName;
1373                             }
1374
1375                             *RootPathName = uniFullPathName;
1376                         }
1377
1378                         //
1379                         // We can't possibly have a pDirEntry since the lookup failed
1380                         //
1381                         try_return( ntStatus);
1382                     }
1383                 }
1384
1385                 //
1386                 // Generate the CRC on the node and perform a case sensitive lookup
1387                 //
1388
1389                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1390                               AFS_TRACE_LEVEL_VERBOSE_2,
1391                               "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case sensitive\n",
1392                               FileObject,
1393                               &uniSearchName);
1394
1395                 ulCRC = AFSGenerateCRC( &uniSearchName,
1396                                         FALSE);
1397
1398                 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1399                                   TRUE);
1400
1401                 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1402                                                 ulCRC,
1403                                                 &pDirEntry);
1404
1405                 if( pDirEntry == NULL)
1406                 {
1407
1408                     //
1409                     // Missed so perform a case insensitive lookup
1410                     //
1411
1412                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1413                                   AFS_TRACE_LEVEL_VERBOSE_2,
1414                                   "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case insensitive\n",
1415                                   FileObject,
1416                                   &uniSearchName);
1417
1418                     ulCRC = AFSGenerateCRC( &uniSearchName,
1419                                             TRUE);
1420
1421                     AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1422                                                       ulCRC,
1423                                                       &pDirEntry);
1424
1425                     if( pDirEntry == NULL)
1426                     {
1427
1428                         //
1429                         // OK, if this component is a valid short name then try
1430                         // a lookup in the short name tree
1431                         //
1432
1433                         if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1434                             RtlIsNameLegalDOS8Dot3( &uniSearchName,
1435                                                     NULL,
1436                                                     NULL))
1437                         {
1438
1439                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1440                                           AFS_TRACE_LEVEL_VERBOSE_2,
1441                                           "AFSLocateNameEntry (FO: %p) Searching for entry %wZ short name\n",
1442                                           FileObject,
1443                                           &uniSearchName);
1444
1445                             AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1446                                                         ulCRC,
1447                                                         &pDirEntry);
1448                         }
1449
1450                         if ( pDirEntry == NULL &&
1451                              pParentDirEntry->ObjectInformation->VolumeCB == AFSGlobalRoot)
1452                         {
1453
1454                             //
1455                             // Check with the service to see if this is a valid cell name
1456                             // that can be automatically resolved.  Drop the shared TreeLock
1457                             // since AFSCheckCellName must acquire it exclusively.
1458                             //
1459
1460                             AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1461
1462                             ntStatus = AFSCheckCellName( AuthGroup,
1463                                                          &uniSearchName,
1464                                                          &pDirEntry);
1465
1466                             AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1467                                               TRUE);
1468                         }
1469
1470                         if( pDirEntry == NULL)
1471                         {
1472
1473                             //
1474                             // If we substituted a name then reset our search name and try again
1475                             //
1476
1477                             if( bSubstituteName)
1478                             {
1479
1480                                 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1481
1482                                 uniSearchName = uniComponentName;
1483
1484                                 bSubstituteName = FALSE;
1485
1486                                 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1487
1488                                 continue;       // while( pDirEntry == NULL)
1489                             }
1490
1491                             if( uniRemainingPath.Length > 0)
1492                             {
1493
1494                                 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1495                             }
1496                             else
1497                             {
1498
1499                                 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1500
1501                                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1502                                               AFS_TRACE_LEVEL_VERBOSE,
1503                                               "AFSLocateNameEntry (FO: %p) Returning name not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1504                                               FileObject,
1505                                               &uniSearchName,
1506                                               pCurrentObject->FileId.Cell,
1507                                               pCurrentObject->FileId.Volume,
1508                                               pCurrentObject->FileId.Vnode,
1509                                               pCurrentObject->FileId.Unique);
1510
1511                                 //
1512                                 // Pass back the directory entries
1513                                 //
1514
1515                                 *ParentDirectoryCB = pParentDirEntry;
1516
1517                                 *DirectoryCB = NULL;
1518
1519                                 *VolumeCB = pCurrentVolume;
1520
1521                                 if( ComponentName != NULL)
1522                                 {
1523
1524                                     *ComponentName = uniComponentName;
1525                                 }
1526
1527                                 *RootPathName = uniFullPathName;
1528                             }
1529
1530                             AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1531
1532                             //
1533                             // Node name not found so get out
1534                             //
1535
1536                             try_return( ntStatus);  // while( pDirEntry == NULL)
1537                         }
1538                     }
1539                     else
1540                     {
1541
1542                         //
1543                         // Here we have a match on the case insensitive lookup for the name. If there
1544                         // Is more than one link entry for this node then fail the lookup request
1545                         //
1546
1547                         if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1548                             pDirEntry->CaseInsensitiveList.fLink != NULL)
1549                         {
1550
1551                             //
1552                             // Increment our dir entry ref count since we will decrement it on exit
1553                             //
1554
1555                             lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1556
1557                             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1558                                           AFS_TRACE_LEVEL_VERBOSE,
1559                                           "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1560                                           &pDirEntry->NameInformation.FileName,
1561                                           pDirEntry,
1562                                           NULL,
1563                                           lCount);
1564
1565                             AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1566
1567                             try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1568                         }
1569                     }
1570                 }
1571
1572                 if( pDirEntry != NULL)
1573                 {
1574
1575                     //
1576                     // If the verify flag is set on the parent and the current entry is deleted
1577                     // revalidate the parent and search again.
1578                     //
1579
1580                     if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1581                         BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1582                     {
1583
1584                         AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1585
1586                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1587                                       AFS_TRACE_LEVEL_VERBOSE,
1588                                       "AFSLocateNameEntry (FO: %p) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1589                                       FileObject,
1590                                       &pParentDirEntry->NameInformation.FileName,
1591                                       pParentDirEntry->ObjectInformation->FileId.Cell,
1592                                       pParentDirEntry->ObjectInformation->FileId.Volume,
1593                                       pParentDirEntry->ObjectInformation->FileId.Vnode,
1594                                       pParentDirEntry->ObjectInformation->FileId.Unique);
1595
1596                         //
1597                         // Directory TreeLock should be exclusively held
1598                         //
1599
1600                         AFSAcquireExcl( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1601                                         TRUE);
1602
1603                         ntStatus = AFSVerifyEntry( AuthGroup,
1604                                                    pParentDirEntry);
1605
1606                         AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1607
1608                         if( !NT_SUCCESS( ntStatus))
1609                         {
1610
1611                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1612                                           AFS_TRACE_LEVEL_ERROR,
1613                                           "AFSLocateNameEntry (FO: %p) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1614                                           FileObject,
1615                                           &pParentDirEntry->NameInformation.FileName,
1616                                           pParentDirEntry->ObjectInformation->FileId.Cell,
1617                                           pParentDirEntry->ObjectInformation->FileId.Volume,
1618                                           pParentDirEntry->ObjectInformation->FileId.Vnode,
1619                                           pParentDirEntry->ObjectInformation->FileId.Unique,
1620                                           ntStatus);
1621
1622                             try_return( ntStatus);
1623                         }
1624
1625                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1626                                       AFS_TRACE_LEVEL_VERBOSE,
1627                                       "AFSLocateNameEntry (FO: %p) Reprocessing component %wZ in parent %wZ\n",
1628                                       FileObject,
1629                                       &uniSearchName,
1630                                       &pParentDirEntry->NameInformation.FileName);
1631
1632
1633                         pDirEntry = NULL;
1634
1635                         continue;
1636                     }
1637
1638                     //
1639                     // Increment our dir entry ref count
1640                     //
1641
1642                     lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1643
1644                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1645                                   AFS_TRACE_LEVEL_VERBOSE,
1646                                   "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1647                                   &pDirEntry->NameInformation.FileName,
1648                                   pDirEntry,
1649                                   NULL,
1650                                   lCount);
1651                 }
1652
1653                 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1654
1655             } // End while( pDirEntry == NULL)
1656
1657             //
1658             // If we have a dirEntry for this component, perform some basic validation on it
1659             //
1660
1661             if( pDirEntry != NULL &&
1662                 BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1663             {
1664
1665                 pCurrentObject = pDirEntry->ObjectInformation;
1666
1667                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1668                               AFS_TRACE_LEVEL_ERROR,
1669                               "AFSLocateNameEntry (FO: %p) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1670                               FileObject,
1671                               &pDirEntry->NameInformation.FileName,
1672                               pCurrentObject->FileId.Cell,
1673                               pCurrentObject->FileId.Volume,
1674                               pCurrentObject->FileId.Vnode,
1675                               pCurrentObject->FileId.Unique);
1676
1677                 //
1678                 // This entry was deleted through the invalidation call back so perform cleanup
1679                 // on the entry
1680                 //
1681
1682                 pParentObjectInfo = pCurrentObject->ParentObjectInformation;
1683
1684                 ASSERT( pParentObjectInfo != NULL);
1685
1686                 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1687                                 TRUE);
1688
1689                 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1690                                 TRUE);
1691
1692                 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1693
1694                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1695                               AFS_TRACE_LEVEL_VERBOSE,
1696                               "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1697                               &pDirEntry->NameInformation.FileName,
1698                               pDirEntry,
1699                               NULL,
1700                               lCount);
1701
1702                 ASSERT( lCount >= 0);
1703
1704                 if( lCount <= 0)
1705                 {
1706
1707                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1708                                   AFS_TRACE_LEVEL_VERBOSE,
1709                                   "AFSLocateNameEntry Deleting dir entry %p (%p) for %wZ\n",
1710                                   pDirEntry,
1711                                   pCurrentObject,
1712                                   &pDirEntry->NameInformation.FileName);
1713
1714                     //
1715                     // Remove and delete the directory entry from the parent list
1716                     //
1717
1718                     AFSDeleteDirEntry( pParentObjectInfo,
1719                                        pDirEntry);
1720
1721                     AFSAcquireShared( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1722                                       TRUE);
1723
1724                     if( pCurrentObject->ObjectReferenceCount <= 0)
1725                     {
1726
1727                         if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
1728                         {
1729
1730                             AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1731                                           AFS_TRACE_LEVEL_VERBOSE,
1732                                           "AFSLocateNameEntry Removing object %p from volume tree\n",
1733                                           pCurrentObject);
1734
1735                             AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
1736                                                 &pCurrentObject->TreeEntry);
1737
1738                             ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
1739                         }
1740                     }
1741
1742                     AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1743                 }
1744                 else
1745                 {
1746
1747                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1748                                   AFS_TRACE_LEVEL_VERBOSE,
1749                                   "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
1750                                   pDirEntry,
1751                                   &pDirEntry->NameInformation.FileName);
1752
1753                     SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
1754
1755                     AFSRemoveNameEntry( pParentObjectInfo,
1756                                         pDirEntry);
1757                 }
1758
1759                 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1760
1761                 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
1762
1763                 //
1764                 // We deleted the dir entry so check if there is any remaining portion
1765                 // of the name to process.
1766                 //
1767
1768                 if( uniRemainingPath.Length > 0)
1769                 {
1770                     ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1771                 }
1772                 else
1773                 {
1774
1775                     ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1776
1777                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1778                                   AFS_TRACE_LEVEL_VERBOSE,
1779                                   "AFSLocateNameEntry (FO: %p) Returning name not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1780                                   FileObject,
1781                                   &uniComponentName,
1782                                   pCurrentObject->FileId.Cell,
1783                                   pCurrentObject->FileId.Volume,
1784                                   pCurrentObject->FileId.Vnode,
1785                                   pCurrentObject->FileId.Unique);
1786
1787                     //
1788                     // Pass back the directory entries
1789                     //
1790
1791                     *ParentDirectoryCB = pParentDirEntry;
1792
1793                     *DirectoryCB = NULL;
1794
1795                     *VolumeCB = pCurrentVolume;
1796
1797                     if( ComponentName != NULL)
1798                     {
1799
1800                         *ComponentName = uniComponentName;
1801                     }
1802
1803                     *RootPathName = uniFullPathName;
1804                 }
1805             }
1806
1807             if( ntStatus != STATUS_SUCCESS)
1808             {
1809
1810                 try_return( ntStatus);
1811             }
1812
1813             //
1814             // Decrement the previous parent
1815             //
1816
1817             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1818
1819             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1820                           AFS_TRACE_LEVEL_VERBOSE,
1821                           "AFSLocateNameEntry Decrement5 count on Parent %wZ DE %p Ccb %p Cnt %d\n",
1822                           &pParentDirEntry->NameInformation.FileName,
1823                           pParentDirEntry,
1824                           NULL,
1825                           lCount);
1826
1827             ASSERT( lCount >= 0);
1828
1829             //
1830             // If we ended up substituting a name in the component then update
1831             // the full path and update the pointers
1832             //
1833
1834             if( bSubstituteName)
1835             {
1836
1837                 BOOLEAN bRelativeOpen = FALSE;
1838
1839                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1840                               AFS_TRACE_LEVEL_VERBOSE_2,
1841                               "AFSLocateNameEntry (FO: %p) Substituting %wZ into %wZ Index %08lX\n",
1842                               FileObject,
1843                               &uniSearchName,
1844                               &uniComponentName,
1845                               ulSubstituteIndex);
1846
1847                 if( FileObject != NULL &&
1848                     FileObject->RelatedFileObject != NULL)
1849                 {
1850
1851                     bRelativeOpen = TRUE;
1852                 }
1853
1854                 //
1855                 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
1856                 // and free the prior Buffer contents but only if the fourth
1857                 // parameter is TRUE.
1858                 //
1859
1860                 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
1861                                                     &uniComponentName,
1862                                                     &uniSearchName,
1863                                                     &uniRemainingPath,
1864                                                     bRelativeOpen ||
1865                                                             bAllocatedSymLinkBuffer ||
1866                                                             bSubstitutedName);
1867
1868                 if( !NT_SUCCESS( ntStatus))
1869                 {
1870
1871                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1872                                   AFS_TRACE_LEVEL_ERROR,
1873                                   "AFSLocateNameEntry (FO: %p) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
1874                                   FileObject,
1875                                   &uniSearchName,
1876                                   &uniComponentName,
1877                                   ulSubstituteIndex,
1878                                   ntStatus);
1879
1880                     try_return( ntStatus);
1881                 }
1882
1883                 //
1884                 // We have substituted a name into the buffer so if we do this again for this
1885                 // path, we need to free up the buffer we allocated.
1886                 //
1887
1888                 bSubstitutedName = TRUE;
1889             }
1890
1891             //
1892             // Update the search parameters
1893             //
1894
1895             uniPathName = uniRemainingPath;
1896
1897             //
1898             // Check if the is a SymLink entry but has no Target FileID or Name. In this
1899             // case it might be a DFS Link so let's go and evaluate it to be sure
1900             //
1901
1902             if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
1903                 ( pCurrentObject->TargetFileId.Vnode == 0 ||
1904                   pDirEntry->NameInformation.TargetName.Length == 0))
1905             {
1906
1907                 ntStatus = AFSValidateSymLink( AuthGroup,
1908                                                pDirEntry);
1909
1910                 if( !NT_SUCCESS( ntStatus))
1911                 {
1912
1913                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1914                                   AFS_TRACE_LEVEL_ERROR,
1915                                   "AFSLocateNameEntry (FO: %p) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1916                                   FileObject,
1917                                   &pDirEntry->NameInformation.FileName,
1918                                   pCurrentObject->FileId.Cell,
1919                                   pCurrentObject->FileId.Volume,
1920                                   pCurrentObject->FileId.Vnode,
1921                                   pCurrentObject->FileId.Unique,
1922                                   ntStatus);
1923
1924                     try_return( ntStatus);
1925                 }
1926             }
1927
1928             //
1929             // Update the name array
1930             //
1931
1932             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1933                           AFS_TRACE_LEVEL_VERBOSE,
1934                           "AFSLocateNameEntry (FO: %p) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1935                           FileObject,
1936                           &pDirEntry->NameInformation.FileName,
1937                           pCurrentObject->FileId.Cell,
1938                           pCurrentObject->FileId.Volume,
1939                           pCurrentObject->FileId.Vnode,
1940                           pCurrentObject->FileId.Unique);
1941
1942             ntStatus = AFSInsertNextElement( pNameArray,
1943                                              pDirEntry);
1944
1945             if( !NT_SUCCESS( ntStatus))
1946             {
1947
1948                 try_return( ntStatus);
1949             }
1950         }       // while (TRUE)
1951
1952 try_exit:
1953
1954         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1955                       AFS_TRACE_LEVEL_VERBOSE,
1956                       "AFSLocateNameEntry (FO: %p) Completed processing %wZ Status %08lX\n",
1957                       FileObject,
1958                       RootPathName,
1959                       ntStatus);
1960
1961         if( ( !NT_SUCCESS( ntStatus) &&
1962               ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
1963             ntStatus == STATUS_REPARSE)
1964         {
1965
1966             if( pDirEntry != NULL)
1967             {
1968
1969                 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1970
1971                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1972                               AFS_TRACE_LEVEL_VERBOSE,
1973                               "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
1974                               &pDirEntry->NameInformation.FileName,
1975                               pDirEntry,
1976                               NULL,
1977                               lCount);
1978
1979                 ASSERT( lCount >= 0);
1980             }
1981             else if( pParentDirEntry != NULL)
1982             {
1983
1984                 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1985
1986                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1987                               AFS_TRACE_LEVEL_VERBOSE,
1988                               "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
1989                               &pParentDirEntry->NameInformation.FileName,
1990                               pParentDirEntry,
1991                               NULL,
1992                               lCount);
1993
1994                 ASSERT( lCount >= 0);
1995             }
1996
1997             if( bReleaseCurrentVolume)
1998             {
1999
2000                 ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
2001
2002                 lCount = InterlockedDecrement( &pCurrentVolume->VolumeReferenceCount);
2003
2004                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2005                               AFS_TRACE_LEVEL_VERBOSE,
2006                               "AFSLocateNameEntry Decrement3 count on volume %p Cnt %d\n",
2007                               pCurrentVolume,
2008                               lCount);
2009             }
2010
2011             if( RootPathName->Buffer != uniFullPathName.Buffer)
2012             {
2013
2014                 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
2015             }
2016         }
2017         else
2018         {
2019
2020             if( *ParentDirectoryCB != NULL)
2021             {
2022
2023                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2024                               AFS_TRACE_LEVEL_VERBOSE,
2025                               "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
2026                               &(*ParentDirectoryCB)->NameInformation.FileName,
2027                               *ParentDirectoryCB,
2028                               NULL,
2029                               (*ParentDirectoryCB)->DirOpenReferenceCount);
2030             }
2031
2032             if( *DirectoryCB != NULL)
2033             {
2034
2035                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2036                               AFS_TRACE_LEVEL_VERBOSE,
2037                               "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
2038                               &(*DirectoryCB)->NameInformation.FileName,
2039                               *DirectoryCB,
2040                               NULL,
2041                               (*DirectoryCB)->DirOpenReferenceCount);
2042             }
2043         }
2044
2045         if( bSubstituteName &&
2046             uniSearchName.Buffer != NULL)
2047         {
2048
2049             AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
2050         }
2051     }
2052
2053     return ntStatus;
2054 }
2055
2056 NTSTATUS
2057 AFSCreateDirEntry( IN GUID            *AuthGroup,
2058                    IN AFSObjectInfoCB *ParentObjectInfo,
2059                    IN AFSDirectoryCB *ParentDirCB,
2060                    IN PUNICODE_STRING FileName,
2061                    IN PUNICODE_STRING ComponentName,
2062                    IN ULONG Attributes,
2063                    IN OUT AFSDirectoryCB **DirEntry)
2064 {
2065
2066     UNREFERENCED_PARAMETER(FileName);
2067     NTSTATUS ntStatus = STATUS_SUCCESS;
2068     AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
2069     LARGE_INTEGER liFileSize = {0,0};
2070     LONG lCount;
2071
2072     __Enter
2073     {
2074
2075         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2076                       AFS_TRACE_LEVEL_VERBOSE_2,
2077                       "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
2078                       &ParentDirCB->NameInformation.FileName,
2079                       ParentObjectInfo->FileId.Cell,
2080                       ParentObjectInfo->FileId.Volume,
2081                       ParentObjectInfo->FileId.Vnode,
2082                       ParentObjectInfo->FileId.Unique,
2083                       ComponentName,
2084                       Attributes);
2085
2086         //
2087         // OK, before inserting the node into the parent tree, issue
2088         // the request to the service for node creation
2089         // We will need to drop the lock on the parent node since the create
2090         // could cause a callback into the file system to invalidate it's cache
2091         //
2092
2093         ntStatus = AFSNotifyFileCreate( AuthGroup,
2094                                         ParentObjectInfo,
2095                                         &liFileSize,
2096                                         Attributes,
2097                                         ComponentName,
2098                                         &pDirNode);
2099
2100         //
2101         // If the returned status is STATUS_REPARSE then the entry exists
2102         // and we raced, get out.
2103
2104         if( ntStatus == STATUS_REPARSE)
2105         {
2106
2107             *DirEntry = pDirNode;
2108
2109             try_return( ntStatus = STATUS_SUCCESS);
2110         }
2111
2112         if( !NT_SUCCESS( ntStatus))
2113         {
2114
2115             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2116                           AFS_TRACE_LEVEL_ERROR,
2117                           "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
2118                           &ParentDirCB->NameInformation.FileName,
2119                           ParentObjectInfo->FileId.Cell,
2120                           ParentObjectInfo->FileId.Volume,
2121                           ParentObjectInfo->FileId.Vnode,
2122                           ParentObjectInfo->FileId.Unique,
2123                           ComponentName,
2124                           Attributes,
2125                           ntStatus);
2126
2127             try_return( ntStatus);
2128         }
2129
2130         AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2131                         TRUE);
2132
2133         //
2134         // Before attempting to insert the new entry, check if we need to validate the parent
2135         //
2136
2137         if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2138         {
2139
2140             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2141                           AFS_TRACE_LEVEL_VERBOSE,
2142                           "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2143                           &ParentDirCB->NameInformation.FileName,
2144                           ParentObjectInfo->FileId.Cell,
2145                           ParentObjectInfo->FileId.Volume,
2146                           ParentObjectInfo->FileId.Vnode,
2147                           ParentObjectInfo->FileId.Unique);
2148
2149             ntStatus = AFSVerifyEntry( AuthGroup,
2150                                        ParentDirCB);
2151
2152             if( !NT_SUCCESS( ntStatus))
2153             {
2154
2155                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2156                               AFS_TRACE_LEVEL_ERROR,
2157                               "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2158                               &ParentDirCB->NameInformation.FileName,
2159                               ParentObjectInfo->FileId.Cell,
2160                               ParentObjectInfo->FileId.Volume,
2161                               ParentObjectInfo->FileId.Vnode,
2162                               ParentObjectInfo->FileId.Unique,
2163                               ntStatus);
2164
2165                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2166
2167                 try_return( ntStatus);
2168             }
2169         }
2170
2171         //
2172         // Check for the entry in the event we raced with some other thread
2173         //
2174
2175         AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2176                                         (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2177                                         &pExistingDirNode);
2178
2179         if( pExistingDirNode != NULL)
2180         {
2181             if (AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2182                                &pExistingDirNode->ObjectInformation->FileId))
2183             {
2184
2185                 AFSDeleteDirEntry( ParentObjectInfo,
2186                                    pDirNode);
2187
2188                 lCount = InterlockedIncrement( &pExistingDirNode->DirOpenReferenceCount);
2189
2190                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2191                               AFS_TRACE_LEVEL_VERBOSE,
2192                               "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2193                               &pExistingDirNode->NameInformation.FileName,
2194                               pExistingDirNode,
2195                               lCount);
2196
2197                 *DirEntry = pExistingDirNode;
2198
2199                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2200
2201                 try_return( ntStatus = STATUS_SUCCESS);
2202             }
2203             else
2204             {
2205
2206                 //
2207                 // Need to tear down this entry and rebuild it below
2208                 //
2209
2210                 if( pExistingDirNode->DirOpenReferenceCount <= 0)
2211                 {
2212
2213                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2214                                   AFS_TRACE_LEVEL_VERBOSE,
2215                                   "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2216                                   pExistingDirNode,
2217                                   &pExistingDirNode->NameInformation.FileName,
2218                                   pExistingDirNode->ObjectInformation->FileId.Cell,
2219                                   pExistingDirNode->ObjectInformation->FileId.Volume,
2220                                   pExistingDirNode->ObjectInformation->FileId.Vnode,
2221                                   pExistingDirNode->ObjectInformation->FileId.Unique,
2222                                   pDirNode->ObjectInformation->FileId.Cell,
2223                                   pDirNode->ObjectInformation->FileId.Volume,
2224                                   pDirNode->ObjectInformation->FileId.Vnode,
2225                                   pDirNode->ObjectInformation->FileId.Unique);
2226
2227                     AFSDeleteDirEntry( ParentObjectInfo,
2228                                        pExistingDirNode);
2229                 }
2230                 else
2231                 {
2232
2233                     SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2234
2235                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2236                                   AFS_TRACE_LEVEL_VERBOSE,
2237                                   "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2238                                   pExistingDirNode,
2239                                   &pExistingDirNode->NameInformation.FileName,
2240                                   pExistingDirNode->ObjectInformation->FileId.Cell,
2241                                   pExistingDirNode->ObjectInformation->FileId.Volume,
2242                                   pExistingDirNode->ObjectInformation->FileId.Vnode,
2243                                   pExistingDirNode->ObjectInformation->FileId.Unique,
2244                                   pDirNode->ObjectInformation->FileId.Cell,
2245                                   pDirNode->ObjectInformation->FileId.Volume,
2246                                   pDirNode->ObjectInformation->FileId.Vnode,
2247                                   pDirNode->ObjectInformation->FileId.Unique);
2248
2249                     AFSRemoveNameEntry( ParentObjectInfo,
2250                                         pExistingDirNode);
2251                 }
2252
2253             }
2254         }
2255
2256         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2257                       AFS_TRACE_LEVEL_VERBOSE_2,
2258                       "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2259                       &ParentDirCB->NameInformation.FileName,
2260                       ParentObjectInfo->FileId.Cell,
2261                       ParentObjectInfo->FileId.Volume,
2262                       ParentObjectInfo->FileId.Vnode,
2263                       ParentObjectInfo->FileId.Unique,
2264                       ComponentName);
2265
2266         //
2267         // Insert the directory node
2268         //
2269
2270         AFSInsertDirectoryNode( ParentObjectInfo,
2271                                 pDirNode,
2272                                 TRUE);
2273
2274         lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
2275
2276         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2277                       AFS_TRACE_LEVEL_VERBOSE,
2278                       "AFSCreateDirEntry Increment2 count on %wZ DE %p Cnt %d\n",
2279                       &pDirNode->NameInformation.FileName,
2280                       pDirNode,
2281                       lCount);
2282
2283         //
2284         // Pass back the dir entry
2285         //
2286
2287         *DirEntry = pDirNode;
2288
2289         AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2290
2291 try_exit:
2292
2293         NOTHING;
2294     }
2295
2296     return ntStatus;
2297 }
2298
2299 void
2300 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2301                         IN AFSDirectoryCB *DirEntry,
2302                         IN BOOLEAN InsertInEnumList)
2303 {
2304
2305     LONG lCount;
2306
2307     __Enter
2308     {
2309
2310         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2311
2312         //
2313         // Insert the node into the directory node tree
2314         //
2315
2316         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2317                       AFS_TRACE_LEVEL_VERBOSE,
2318                       "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2319                       DirEntry,
2320                       &DirEntry->NameInformation.FileName);
2321
2322         ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2323
2324         if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2325         {
2326
2327             ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2328
2329             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2330                           AFS_TRACE_LEVEL_VERBOSE,
2331                           "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2332                           DirEntry,
2333                           &DirEntry->NameInformation.FileName);
2334         }
2335         else
2336         {
2337
2338             AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2339                                             DirEntry);
2340
2341             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2342                           AFS_TRACE_LEVEL_VERBOSE,
2343                           "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2344                           DirEntry,
2345                           &DirEntry->NameInformation.FileName);
2346         }
2347
2348         if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2349         {
2350
2351             ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2352
2353             SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2354
2355             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2356                           AFS_TRACE_LEVEL_VERBOSE,
2357                           "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2358                           DirEntry,
2359                           &DirEntry->NameInformation.FileName);
2360         }
2361         else
2362         {
2363
2364             AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2365                                               DirEntry);
2366
2367             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2368                           AFS_TRACE_LEVEL_VERBOSE,
2369                           "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2370                           DirEntry,
2371                           &DirEntry->NameInformation.FileName);
2372         }
2373
2374         //
2375         // Into the shortname tree
2376         //
2377
2378         if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2379         {
2380
2381             if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2382             {
2383
2384                 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2385
2386                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2387                               AFS_TRACE_LEVEL_VERBOSE,
2388                               "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2389                               DirEntry,
2390                               &DirEntry->NameInformation.FileName);
2391
2392                 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2393             }
2394             else
2395             {
2396
2397                 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2398                                                              DirEntry)))
2399                 {
2400                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2401                                   AFS_TRACE_LEVEL_VERBOSE,
2402                                   "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2403                                   DirEntry,
2404                                   &DirEntry->NameInformation.FileName);
2405                 }
2406                 else
2407                 {
2408                     SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2409
2410                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2411                                   AFS_TRACE_LEVEL_VERBOSE,
2412                                   "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2413                                   DirEntry,
2414                                   &DirEntry->NameInformation.FileName);
2415                 }
2416             }
2417         }
2418
2419         if( InsertInEnumList)
2420         {
2421
2422             //
2423             // And insert the node into the directory list
2424             //
2425
2426             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2427                           AFS_TRACE_LEVEL_VERBOSE,
2428                           "AFSInsertDirectoryNode Inserting entry %p %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2429                           DirEntry,
2430                           &DirEntry->NameInformation.FileName,
2431                           DirEntry->ObjectInformation->FileId.Cell,
2432                           DirEntry->ObjectInformation->FileId.Volume,
2433                           DirEntry->ObjectInformation->FileId.Vnode,
2434                           DirEntry->ObjectInformation->FileId.Unique);
2435
2436             if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2437             {
2438
2439                 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2440             }
2441             else
2442             {
2443
2444                 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2445
2446                 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2447             }
2448
2449             ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2450
2451             SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2452
2453             lCount = InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2454
2455             AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2456                           AFS_TRACE_LEVEL_VERBOSE,
2457                           "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2458                           &DirEntry->NameInformation.FileName,
2459                           lCount,
2460                           ParentObjectInfo->FileId.Cell,
2461                           ParentObjectInfo->FileId.Volume,
2462                           ParentObjectInfo->FileId.Vnode,
2463                           ParentObjectInfo->FileId.Unique);
2464         }
2465     }
2466
2467     return;
2468 }
2469
2470 NTSTATUS
2471 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2472                    IN AFSDirectoryCB *DirEntry)
2473 {
2474
2475     NTSTATUS ntStatus = STATUS_SUCCESS;
2476     LONG lCount;
2477
2478     __Enter
2479     {
2480
2481         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2482                       AFS_TRACE_LEVEL_VERBOSE,
2483                       "AFSDeleteDirEntry Deleting dir entry in parent %08lX Entry %p %wZ FID %08lX-%08lX-%08lX-%08lX RefCount %d\n",
2484                       ParentObjectInfo,
2485                       DirEntry,
2486                       &DirEntry->NameInformation.FileName,
2487                       DirEntry->ObjectInformation->FileId.Cell,
2488                       DirEntry->ObjectInformation->FileId.Volume,
2489                       DirEntry->ObjectInformation->FileId.Vnode,
2490                       DirEntry->ObjectInformation->FileId.Unique,
2491                       DirEntry->DirOpenReferenceCount);
2492
2493         ASSERT( DirEntry->DirOpenReferenceCount == 0);
2494
2495         AFSRemoveDirNodeFromParent( ParentObjectInfo,
2496                                     DirEntry,
2497                                     TRUE);
2498
2499         //
2500         // Free up the name buffer if it was reallocated
2501         //
2502
2503         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2504         {
2505
2506             AFSExFreePoolWithTag( DirEntry->NameInformation.FileName.Buffer, 0);
2507         }
2508
2509         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2510         {
2511
2512             AFSExFreePoolWithTag( DirEntry->NameInformation.TargetName.Buffer, 0);
2513         }
2514
2515         //
2516         // Dereference the object for this dir entry
2517         //
2518
2519         ASSERT( DirEntry->ObjectInformation->ObjectReferenceCount > 0);
2520
2521         lCount = AFSObjectInfoDecrement( DirEntry->ObjectInformation);
2522
2523         AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2524                       AFS_TRACE_LEVEL_VERBOSE,
2525                       "AFSDeleteDirEntry Decrement count on object %p Cnt %d\n",
2526                       DirEntry->ObjectInformation,
2527                       lCount);
2528
2529         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
2530             DirEntry->ObjectInformation->Links == 0)
2531         {
2532
2533             SetFlag( DirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2534         }
2535
2536         ExDeleteResourceLite( &DirEntry->NonPaged->Lock);
2537
2538         AFSExFreePoolWithTag( DirEntry->NonPaged, AFS_DIR_ENTRY_NP_TAG);
2539
2540         //
2541         // Free up the dir entry
2542         //
2543
2544         AFSExFreePoolWithTag( DirEntry, AFS_DIR_ENTRY_TAG);
2545     }
2546
2547     return ntStatus;
2548 }
2549
2550 NTSTATUS
2551 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2552                             IN AFSDirectoryCB *DirEntry,
2553                             IN BOOLEAN RemoveFromEnumList)
2554 {
2555
2556     NTSTATUS ntStatus = STATUS_SUCCESS;
2557     LONG lCount;
2558
2559     __Enter
2560     {
2561
2562
2563         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2564
2565         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2566                       AFS_TRACE_LEVEL_VERBOSE,
2567                       "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %p\n",
2568                       DirEntry,
2569                       &DirEntry->NameInformation.FileName,
2570                       DirEntry->ObjectInformation->FileId.Cell,
2571                       DirEntry->ObjectInformation->FileId.Volume,
2572                       DirEntry->ObjectInformation->FileId.Vnode,
2573                       DirEntry->ObjectInformation->FileId.Unique,
2574                       ParentObjectInfo);
2575
2576         if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2577         {
2578
2579             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2580                           AFS_TRACE_LEVEL_VERBOSE,
2581                           "AFSRemoveDirNodeFromParent Removing DirEntry %p name %wZ\n",
2582                           DirEntry,
2583                           &DirEntry->NameInformation.FileName);
2584
2585             AFSRemoveNameEntry( ParentObjectInfo,
2586                                 DirEntry);
2587         }
2588         else
2589         {
2590
2591             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2592                           AFS_TRACE_LEVEL_VERBOSE,
2593                           "AFSRemoveDirNodeFromParent DE %p for %wZ NOT removing entry due to flag set\n",
2594                           DirEntry,
2595                           &DirEntry->NameInformation.FileName);
2596
2597         }
2598
2599         if( RemoveFromEnumList &&
2600             BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST))
2601         {
2602
2603             //
2604             // And remove the entry from the enumeration list
2605             //
2606
2607             if( DirEntry->ListEntry.fLink == NULL)
2608             {
2609
2610                 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = (AFSDirectoryCB *)DirEntry->ListEntry.bLink;
2611             }
2612             else
2613             {
2614
2615                 ((AFSDirectoryCB *)DirEntry->ListEntry.fLink)->ListEntry.bLink = DirEntry->ListEntry.bLink;
2616             }
2617
2618             if( DirEntry->ListEntry.bLink == NULL)
2619             {
2620
2621                 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = (AFSDirectoryCB *)DirEntry->ListEntry.fLink;
2622             }
2623             else
2624             {
2625
2626                 ((AFSDirectoryCB *)DirEntry->ListEntry.bLink)->ListEntry.fLink = DirEntry->ListEntry.fLink;
2627             }
2628
2629             ASSERT( ParentObjectInfo->Specific.Directory.DirectoryNodeCount > 0);
2630
2631             lCount = InterlockedDecrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2632
2633             ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2634
2635             AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2636                           AFS_TRACE_LEVEL_VERBOSE,
2637                           "AFSRemoveDirNodeFromParent Removing entry %wZ Dec Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2638                           &DirEntry->NameInformation.FileName,
2639                           lCount,
2640                           ParentObjectInfo->FileId.Cell,
2641                           ParentObjectInfo->FileId.Volume,
2642                           ParentObjectInfo->FileId.Vnode,
2643                           ParentObjectInfo->FileId.Unique);
2644
2645             DirEntry->ListEntry.fLink = NULL;
2646             DirEntry->ListEntry.bLink = NULL;
2647         }
2648     }
2649
2650     return ntStatus;
2651 }
2652
2653 NTSTATUS
2654 AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
2655                     IN OUT PUNICODE_STRING TargetFileName)
2656 {
2657
2658     NTSTATUS ntStatus = STATUS_SUCCESS;
2659     UNICODE_STRING uniFileName;
2660
2661     __Enter
2662     {
2663
2664         //
2665         // We will process backwards from the end of the name looking
2666         // for the first \ we encounter
2667         //
2668
2669         uniFileName.Length = FileName->Length;
2670         uniFileName.MaximumLength = FileName->MaximumLength;
2671
2672         uniFileName.Buffer = FileName->Buffer;
2673
2674         while( TRUE)
2675         {
2676
2677             if( uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
2678             {
2679
2680                 //
2681                 // Subtract one more character off of the filename if it is not the root
2682                 //
2683
2684                 if( uniFileName.Length > sizeof( WCHAR))
2685                 {
2686
2687                     uniFileName.Length -= sizeof( WCHAR);
2688                 }
2689
2690                 //
2691                 // Now build up the target name
2692                 //
2693
2694                 TargetFileName->Length = FileName->Length - uniFileName.Length;
2695
2696                 //
2697                 // If we are not on the root then fixup the name
2698                 //
2699
2700                 if( uniFileName.Length > sizeof( WCHAR))
2701                 {
2702
2703                     TargetFileName->Length -= sizeof( WCHAR);
2704
2705                     TargetFileName->Buffer = &uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) + 1];
2706                 }
2707                 else
2708                 {
2709
2710                     TargetFileName->Buffer = &uniFileName.Buffer[ uniFileName.Length/sizeof( WCHAR)];
2711                 }
2712
2713                 //
2714                 // Fixup the passed back filename length
2715                 //
2716
2717                 FileName->Length = uniFileName.Length;
2718
2719                 TargetFileName->MaximumLength = TargetFileName->Length;
2720
2721                 break;
2722             }
2723
2724             uniFileName.Length -= sizeof( WCHAR);
2725         }
2726     }
2727
2728     return ntStatus;
2729 }
2730
2731 NTSTATUS
2732 AFSParseName( IN PIRP Irp,
2733               IN GUID *AuthGroup,
2734               OUT PUNICODE_STRING FileName,
2735               OUT PUNICODE_STRING ParsedFileName,
2736               OUT PUNICODE_STRING RootFileName,
2737               OUT ULONG *ParseFlags,
2738               OUT AFSVolumeCB   **VolumeCB,
2739               OUT AFSDirectoryCB **ParentDirectoryCB,
2740               OUT AFSNameArrayHdr **NameArray)
2741 {
2742
2743     NTSTATUS            ntStatus = STATUS_SUCCESS;
2744     PIO_STACK_LOCATION  pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2745     AFSDeviceExt       *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2746     UNICODE_STRING      uniFullName, uniComponentName, uniRemainingPath;
2747     ULONG               ulCRC = 0;
2748     AFSDirectoryCB     *pDirEntry = NULL;
2749     USHORT              usIndex = 0, usDriveIndex = 0;
2750     AFSCcb             *pRelatedCcb = NULL;
2751     AFSNameArrayHdr    *pNameArray = NULL, *pRelatedNameArray = NULL;
2752     USHORT              usComponentIndex = 0;
2753     USHORT              usComponentLength = 0;
2754     AFSVolumeCB        *pVolumeCB = NULL;
2755     AFSFcb             *pRelatedFcb = NULL;
2756     BOOLEAN             bReleaseTreeLock = FALSE;
2757     BOOLEAN             bIsAllShare = FALSE;
2758     LONG                lCount;
2759
2760     __Enter
2761     {
2762
2763         //
2764         // Indicate we are opening a root ...
2765         //
2766
2767         *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
2768
2769         if( pIrpSp->FileObject->RelatedFileObject != NULL)
2770         {
2771
2772             pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
2773
2774             pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
2775
2776             pRelatedNameArray = pRelatedCcb->NameArray;
2777
2778             uniFullName = pIrpSp->FileObject->FileName;
2779
2780             ASSERT( pRelatedFcb != NULL);
2781
2782             //
2783             // No wild cards in the name
2784             //
2785
2786             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2787                           AFS_TRACE_LEVEL_VERBOSE_2,
2788                           "AFSParseName (%p) Relative open for %wZ FID %08lX-%08lX-%08lX-%08lX component %wZ\n",
2789                           Irp,
2790                           &pRelatedCcb->DirectoryCB->NameInformation.FileName,
2791                           pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Cell,
2792                           pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Volume,
2793                           pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
2794                           pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Unique,
2795                           &uniFullName);
2796
2797             if( FsRtlDoesNameContainWildCards( &uniFullName))
2798             {
2799
2800                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2801                               AFS_TRACE_LEVEL_ERROR,
2802                               "AFSParseName (%p) Component %wZ contains wild cards\n",
2803                               Irp,
2804                               &uniFullName);
2805
2806                 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
2807             }
2808
2809             pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
2810
2811             pDirEntry = pRelatedCcb->DirectoryCB;
2812
2813             *FileName = pIrpSp->FileObject->FileName;
2814
2815             //
2816             // Grab the root node while checking state
2817             //
2818
2819             AFSAcquireShared( pVolumeCB->VolumeLock,
2820                               TRUE);
2821
2822             if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
2823                 BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
2824             {
2825
2826                 //
2827                 // The volume has been taken off line so fail the access
2828                 //
2829
2830                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2831                               AFS_TRACE_LEVEL_ERROR,
2832                               "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
2833                               Irp,
2834                               pVolumeCB->ObjectInformation.FileId.Cell,
2835                               pVolumeCB->ObjectInformation.FileId.Volume);
2836
2837                 AFSReleaseResource( pVolumeCB->VolumeLock);
2838
2839                 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
2840             }
2841
2842             if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
2843             {
2844
2845                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2846                               AFS_TRACE_LEVEL_VERBOSE,
2847                               "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
2848                               Irp,
2849                               pVolumeCB->ObjectInformation.FileId.Cell,
2850                               pVolumeCB->ObjectInformation.FileId.Volume);
2851
2852                 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
2853                                             pVolumeCB);
2854
2855                 if( !NT_SUCCESS( ntStatus))
2856                 {
2857
2858                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2859                                   AFS_TRACE_LEVEL_ERROR,
2860                                   "AFSParseName (%p) Failed verification of root Status %08lX\n",
2861                                   Irp,
2862                                   ntStatus);
2863
2864                     AFSReleaseResource( pVolumeCB->VolumeLock);
2865
2866                     try_return( ntStatus);
2867                 }
2868             }
2869
2870             AFSReleaseResource( pVolumeCB->VolumeLock);
2871
2872             if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
2873             {
2874
2875                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2876                               AFS_TRACE_LEVEL_VERBOSE,
2877                               "AFSParseName (%p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2878                               Irp,
2879                               &pDirEntry->NameInformation.FileName,
2880                               pDirEntry->ObjectInformation->FileId.Cell,
2881                               pDirEntry->ObjectInformation->FileId.Volume,
2882                               pDirEntry->ObjectInformation->FileId.Vnode,
2883                               pDirEntry->ObjectInformation->FileId.Unique);
2884
2885                 //
2886                 // Directory TreeLock should be exclusively held
2887                 //
2888
2889                 AFSAcquireExcl( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
2890                                 TRUE);
2891
2892                 ntStatus = AFSVerifyEntry( AuthGroup,
2893                                            pDirEntry);
2894
2895                 AFSReleaseResource( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2896
2897                 if( !NT_SUCCESS( ntStatus))
2898                 {
2899
2900                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2901                                   AFS_TRACE_LEVEL_VERBOSE,
2902                                   "AFSParseName (%p) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2903                                   Irp,
2904                                   &pDirEntry->NameInformation.FileName,
2905                                   pDirEntry->ObjectInformation->FileId.Cell,
2906                                   pDirEntry->ObjectInformation->FileId.Volume,
2907                                   pDirEntry->ObjectInformation->FileId.Vnode,
2908                                   pDirEntry->ObjectInformation->FileId.Unique,
2909                                   ntStatus);
2910
2911                     try_return( ntStatus);
2912                 }
2913             }
2914
2915             //
2916             // Create our full path name buffer
2917             //
2918
2919             uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length +
2920                                                     sizeof( WCHAR) +
2921                                                     pIrpSp->FileObject->FileName.Length +
2922                                                     sizeof( WCHAR);
2923
2924             uniFullName.Length = 0;
2925
2926             uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2927                                                                     uniFullName.MaximumLength,
2928                                                                     AFS_NAME_BUFFER_THREE_TAG);
2929
2930             if( uniFullName.Buffer == NULL)
2931             {
2932
2933                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2934                               AFS_TRACE_LEVEL_ERROR,
2935                               "AFSParseName (%p) Failed to allocate full name buffer\n",
2936                               Irp);
2937
2938                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2939             }
2940
2941             RtlZeroMemory( uniFullName.Buffer,
2942                            uniFullName.MaximumLength);
2943
2944             RtlCopyMemory( uniFullName.Buffer,
2945                            pRelatedCcb->FullFileName.Buffer,
2946                            pRelatedCcb->FullFileName.Length);
2947
2948             uniFullName.Length = pRelatedCcb->FullFileName.Length;
2949
2950             usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
2951
2952             usComponentLength = pIrpSp->FileObject->FileName.Length;
2953
2954             if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
2955                 pIrpSp->FileObject->FileName.Length > 0 &&
2956                 pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
2957                 pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
2958             {
2959
2960                 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
2961
2962                 uniFullName.Length += sizeof( WCHAR);
2963
2964                 usComponentLength += sizeof( WCHAR);
2965             }
2966
2967             if( pIrpSp->FileObject->FileName.Length > 0)
2968             {
2969
2970                 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
2971                                pIrpSp->FileObject->FileName.Buffer,
2972                                pIr\epSp->FileObject->FileName.Length);
2973
2974                 uniFullName.Length += pIrpSp->FileObject->FileName.Length;
2975             }
2976
2977             *RootFileName = uniFullName;
2978
2979             //
2980             // We populate up to the current parent
2981             //
2982
2983             if( pRelatedNameArray == NULL)
2984             {
2985
2986                 //
2987                 // Init and populate our name array
2988                 //
2989
2990                 pNameArray = AFSInitNameArray( NULL,
2991                                                0);
2992
2993                 if( pNameArray == NULL)
2994                 {
2995
2996                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2997                                   AFS_TRACE_LEVEL_VERBOSE,
2998                                   "AFSParseName (%p) Failed to initialize name array\n",
2999                                   Irp);
3000
3001                     AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3002
3003                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3004                 }
3005
3006                 ntStatus = AFSPopulateNameArray( pNameArray,
3007                                                  NULL,
3008                                                  pRelatedCcb->DirectoryCB);
3009             }
3010             else
3011             {
3012
3013                 //
3014                 // Init and populate our name array
3015                 //
3016
3017                 pNameArray = AFSInitNameArray( NULL,
3018                                                pRelatedNameArray->MaxElementCount);
3019
3020                 if( pNameArray == NULL)
3021                 {
3022
3023                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3024                                   AFS_TRACE_LEVEL_VERBOSE,
3025                                   "AFSParseName (%p) Failed to initialize name array\n",
3026                                   Irp);
3027
3028                     AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3029
3030                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3031                 }
3032
3033                 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
3034                                                                  pRelatedNameArray,
3035                                                                  pRelatedCcb->DirectoryCB);
3036             }
3037
3038             if( !NT_SUCCESS( ntStatus))
3039             {
3040
3041                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3042                               AFS_TRACE_LEVEL_VERBOSE,
3043                               "AFSParseName (%p) Failed to populate name array\n",
3044                               Irp);
3045
3046                 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3047
3048                 try_return( ntStatus);
3049             }
3050
3051             ParsedFileName->Length = usComponentLength;
3052             ParsedFileName->MaximumLength = uniFullName.MaximumLength;
3053
3054             ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
3055
3056             //
3057             // Indicate to caller that RootFileName must be freed
3058             //
3059
3060             SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
3061
3062             *NameArray = pNameArray;
3063
3064             *VolumeCB = pVolumeCB;
3065
3066             //
3067             // Increment our volume reference count
3068             //
3069
3070             lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
3071
3072             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3073                           AFS_TRACE_LEVEL_VERBOSE,
3074                           "AFSParseName Increment count on volume %p Cnt %d\n",
3075                           pVolumeCB,
3076                           lCount);
3077
3078             *ParentDirectoryCB = pDirEntry;
3079
3080             lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
3081
3082             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3083                           AFS_TRACE_LEVEL_VERBOSE,
3084                           "AFSParseName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
3085                           &pDirEntry->NameInformation.FileName,
3086                           pDirEntry,
3087                           NULL,
3088                           lCount);
3089
3090             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3091                           AFS_TRACE_LEVEL_VERBOSE_2,
3092                           "AFSParseName (%p) Returning full name %wZ\n",
3093                           Irp,
3094                           &uniFullName);
3095
3096             try_return( ntStatus);
3097         }
3098
3099         //
3100         // No wild cards in the name
3101         //
3102
3103         uniFullName = pIrpSp->FileObject->FileName;
3104
3105         if( FsRtlDoesNameContainWildCards( &uniFullName) ||
3106             uniFullName.Length < AFSServerName.Length)
3107         {
3108
3109             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3110                           AFS_TRACE_LEVEL_ERROR,
3111                           "AFSParseName (%p) Name %wZ contains wild cards or too short\n",
3112                           Irp,
3113                           &uniFullName);
3114
3115             try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3116         }
3117
3118         //
3119         // The name is a fully qualified name. Parse out the server/share names and
3120         // point to the root qualified name
3121         // First thing is to locate the server name
3122         //
3123
3124         FsRtlDissectName( uniFullName,
3125                           &uniComponentName,
3126                           &uniRemainingPath);
3127
3128         uniFullName = uniRemainingPath;
3129
3130         //
3131         // This component is the server name we are serving
3132         //
3133
3134         if( RtlCompareUnicodeString( &uniComponentName,
3135                                      &AFSServerName,
3136                                      TRUE) != 0)
3137         {
3138
3139             //
3140             // Drive letter based name?
3141             //
3142
3143             uniFullName = pIrpSp->FileObject->FileName;
3144
3145             while( usIndex < uniFullName.Length/sizeof( WCHAR))
3146             {
3147
3148                 if( uniFullName.Buffer[ usIndex] == L':')
3149                 {
3150
3151                     uniFullName.Buffer = &uniFullName.Buffer[ usIndex + 2];
3152
3153                     uniFullName.Length -= (usIndex + 2) * sizeof( WCHAR);
3154
3155                     usDriveIndex = usIndex - 1;
3156
3157                     break;
3158                 }
3159
3160                 usIndex++;
3161             }
3162
3163             //
3164             // Do we have the right server name now?
3165             //
3166
3167             FsRtlDissectName( uniFullName,
3168                               &uniComponentName,
3169                               &uniRemainingPath);
3170
3171             uniFullName = uniRemainingPath;
3172
3173             //
3174             // This component is the server name we are serving
3175             //
3176
3177             if( RtlCompareUnicodeString( &uniComponentName,
3178                                          &AFSServerName,
3179                                          TRUE) != 0)
3180             {
3181
3182                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3183                               AFS_TRACE_LEVEL_ERROR,
3184                               "AFSParseName (%p) Name %wZ does not have server name\n",
3185                               Irp,
3186                               &pIrpSp->FileObject->FileName);
3187
3188                 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3189             }
3190
3191             //
3192             // Validate this drive letter is actively mapped
3193             //
3194
3195             if( usDriveIndex > 0 &&
3196                 !AFSIsDriveMapped( pIrpSp->FileObject->FileName.Buffer[ usDriveIndex]))
3197             {
3198
3199                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3200                               AFS_TRACE_LEVEL_ERROR,
3201                               "AFSParseName (%p) Name %wZ contains invalid drive mapping\n",
3202                               Irp,
3203                               &pIrpSp->FileObject->FileName);
3204
3205                 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3206             }
3207         }
3208
3209         if( FsRtlDoesNameContainWildCards( &uniFullName))
3210         {
3211
3212             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3213                           AFS_TRACE_LEVEL_ERROR,
3214                           "AFSParseName (%p) Component %wZ contains wild cards\n",
3215                           Irp,
3216                           &uniFullName);
3217
3218             try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3219         }
3220
3221         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3222                       AFS_TRACE_LEVEL_VERBOSE_2,
3223                       "AFSParseName (%p) Processing full name %wZ\n",
3224                       Irp,
3225                       &uniFullName);
3226
3227         if( uniFullName.Length > 0 &&
3228             uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] == L'\\')
3229         {
3230
3231             uniFullName.Length -= sizeof( WCHAR);
3232         }
3233
3234         //
3235         // Be sure we are online and ready to go
3236         //
3237
3238         AFSAcquireShared( AFSGlobalRoot->VolumeLock,
3239                           TRUE);
3240
3241         if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3242             BooleanFlagOn( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3243         {
3244
3245             //
3246             // The volume has been taken off line so fail the access
3247             //
3248
3249             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3250                           AFS_TRACE_LEVEL_ERROR,
3251                           "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3252                           Irp,
3253                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3254                           AFSGlobalRoot->ObjectInformation.FileId.Volume);
3255
3256             AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3257
3258             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3259         }