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