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