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