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