f924c5a21b6a543081602ce382d39b79ca5ee7c3
[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                         {
1452
1453                             //
1454                             // If we substituted a name then reset our search name and try again
1455                             //
1456
1457                             if( bSubstituteName)
1458                             {
1459
1460                                 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1461
1462                                 uniSearchName = uniComponentName;
1463
1464                                 bSubstituteName = FALSE;
1465
1466                                 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1467
1468                                 continue;       // while( pDirEntry == NULL)
1469                             }
1470
1471                             if( uniRemainingPath.Length > 0)
1472                             {
1473
1474                                 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1475                             }
1476                             else
1477                             {
1478
1479                                 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1480
1481                                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1482                                               AFS_TRACE_LEVEL_VERBOSE,
1483                                               "AFSLocateNameEntry (FO: %08lX) Returning name not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1484                                               FileObject,
1485                                               &uniSearchName,
1486                                               pCurrentObject->FileId.Cell,
1487                                               pCurrentObject->FileId.Volume,
1488                                               pCurrentObject->FileId.Vnode,
1489                                               pCurrentObject->FileId.Unique);
1490
1491                                 //
1492                                 // Pass back the directory entries
1493                                 //
1494
1495                                 *ParentDirectoryCB = pParentDirEntry;
1496
1497                                 *DirectoryCB = NULL;
1498
1499                                 *VolumeCB = pCurrentVolume;
1500
1501                                 if( ComponentName != NULL)
1502                                 {
1503
1504                                     *ComponentName = uniComponentName;
1505                                 }
1506
1507                                 *RootPathName = uniFullPathName;
1508                             }
1509
1510                             AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1511
1512                             //
1513                             // Node name not found so get out
1514                             //
1515
1516                             try_return( ntStatus);  // while( pDirEntry == NULL)
1517                         }
1518                     }
1519                     else
1520                     {
1521
1522                         //
1523                         // Here we have a match on the case insensitive lookup for the name. If there
1524                         // Is more than one link entry for this node then fail the lookup request
1525                         //
1526
1527                         if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1528                             pDirEntry->CaseInsensitiveList.fLink != NULL)
1529                         {
1530
1531                             //
1532                             // Increment our dir entry ref count since we will decrement it on exit
1533                             //
1534
1535                             lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1536
1537                             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1538                                           AFS_TRACE_LEVEL_VERBOSE,
1539                                           "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1540                                           &pDirEntry->NameInformation.FileName,
1541                                           pDirEntry,
1542                                           NULL,
1543                                           lCount);
1544
1545                             AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1546
1547                             try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1548                         }
1549                     }
1550                 }
1551
1552                 if( pDirEntry != NULL)
1553                 {
1554
1555                     //
1556                     // If the verify flag is set on the parent and the current entry is deleted
1557                     // revalidate the parent and search again.
1558                     //
1559
1560                     if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1561                         BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1562                     {
1563
1564                         AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1565
1566                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1567                                       AFS_TRACE_LEVEL_VERBOSE,
1568                                       "AFSLocateNameEntry (FO: %08lX) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1569                                       FileObject,
1570                                       &pParentDirEntry->NameInformation.FileName,
1571                                       pParentDirEntry->ObjectInformation->FileId.Cell,
1572                                       pParentDirEntry->ObjectInformation->FileId.Volume,
1573                                       pParentDirEntry->ObjectInformation->FileId.Vnode,
1574                                       pParentDirEntry->ObjectInformation->FileId.Unique);
1575
1576                         //
1577                         // Directory TreeLock should be exclusively held
1578                         //
1579
1580                         AFSAcquireExcl( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1581                                         TRUE);
1582
1583                         ntStatus = AFSVerifyEntry( AuthGroup,
1584                                                    pParentDirEntry);
1585
1586                         AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1587
1588                         if( !NT_SUCCESS( ntStatus))
1589                         {
1590
1591                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1592                                           AFS_TRACE_LEVEL_ERROR,
1593                                           "AFSLocateNameEntry (FO: %08lX) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1594                                           FileObject,
1595                                           &pParentDirEntry->NameInformation.FileName,
1596                                           pParentDirEntry->ObjectInformation->FileId.Cell,
1597                                           pParentDirEntry->ObjectInformation->FileId.Volume,
1598                                           pParentDirEntry->ObjectInformation->FileId.Vnode,
1599                                           pParentDirEntry->ObjectInformation->FileId.Unique,
1600                                           ntStatus);
1601
1602                             try_return( ntStatus);
1603                         }
1604
1605                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1606                                       AFS_TRACE_LEVEL_VERBOSE,
1607                                       "AFSLocateNameEntry (FO: %08lX) Reprocessing component %wZ in parent %wZ\n",
1608                                       FileObject,
1609                                       &uniSearchName,
1610                                       &pParentDirEntry->NameInformation.FileName);
1611
1612
1613                         pDirEntry = NULL;
1614
1615                         continue;
1616                     }
1617
1618                     //
1619                     // Increment our dir entry ref count
1620                     //
1621
1622                     lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1623
1624                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1625                                   AFS_TRACE_LEVEL_VERBOSE,
1626                                   "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1627                                   &pDirEntry->NameInformation.FileName,
1628                                   pDirEntry,
1629                                   NULL,
1630                                   lCount);
1631                 }
1632
1633                 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1634
1635             } // End while( pDirEntry == NULL)
1636
1637             //
1638             // If we have a dirEntry for this component, perform some basic validation on it
1639             //
1640
1641             if( pDirEntry != NULL &&
1642                 BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1643             {
1644
1645                 pCurrentObject = pDirEntry->ObjectInformation;
1646
1647                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1648                               AFS_TRACE_LEVEL_ERROR,
1649                               "AFSLocateNameEntry (FO: %08lX) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1650                               FileObject,
1651                               &pDirEntry->NameInformation.FileName,
1652                               pCurrentObject->FileId.Cell,
1653                               pCurrentObject->FileId.Volume,
1654                               pCurrentObject->FileId.Vnode,
1655                               pCurrentObject->FileId.Unique);
1656
1657                 //
1658                 // This entry was deleted through the invalidation call back so perform cleanup
1659                 // on the entry
1660                 //
1661
1662                 pParentObjectInfo = pCurrentObject->ParentObjectInformation;
1663
1664                 ASSERT( pParentObjectInfo != NULL);
1665
1666                 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1667                                 TRUE);
1668
1669                 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1670                                 TRUE);
1671
1672                 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1673
1674                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1675                               AFS_TRACE_LEVEL_VERBOSE,
1676                               "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1677                               &pDirEntry->NameInformation.FileName,
1678                               pDirEntry,
1679                               NULL,
1680                               lCount);
1681
1682                 ASSERT( lCount >= 0);
1683
1684                 if( lCount <= 0)
1685                 {
1686
1687                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1688                                   AFS_TRACE_LEVEL_VERBOSE,
1689                                   "AFSLocateNameEntry Deleting dir entry %08lX (%08lX) for %wZ\n",
1690                                   pDirEntry,
1691                                   pCurrentObject,
1692                                   &pDirEntry->NameInformation.FileName);
1693
1694                     //
1695                     // Remove and delete the directory entry from the parent list
1696                     //
1697
1698                     AFSDeleteDirEntry( pParentObjectInfo,
1699                                        pDirEntry);
1700
1701                     AFSAcquireShared( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1702                                       TRUE);
1703
1704                     if( pCurrentObject->ObjectReferenceCount <= 0)
1705                     {
1706
1707                         if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
1708                         {
1709
1710                             AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1711                                           AFS_TRACE_LEVEL_VERBOSE,
1712                                           "AFSLocateNameEntry Removing object %08lX from volume tree\n",
1713                                           pCurrentObject);
1714
1715                             AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
1716                                                 &pCurrentObject->TreeEntry);
1717
1718                             ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
1719                         }
1720                     }
1721
1722                     AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1723                 }
1724                 else
1725                 {
1726
1727                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1728                                   AFS_TRACE_LEVEL_VERBOSE,
1729                                   "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
1730                                   pDirEntry,
1731                                   &pDirEntry->NameInformation.FileName);
1732
1733                     SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
1734
1735                     AFSRemoveNameEntry( pParentObjectInfo,
1736                                         pDirEntry);
1737                 }
1738
1739                 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1740
1741                 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
1742
1743                 //
1744                 // We deleted the dir entry so check if there is any remaining portion
1745                 // of the name to process.
1746                 //
1747
1748                 if( uniRemainingPath.Length > 0)
1749                 {
1750                     ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1751                 }
1752                 else
1753                 {
1754
1755                     ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1756
1757                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1758                                   AFS_TRACE_LEVEL_VERBOSE,
1759                                   "AFSLocateNameEntry (FO: %08lX) Returning name not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1760                                   FileObject,
1761                                   &uniComponentName,
1762                                   pCurrentObject->FileId.Cell,
1763                                   pCurrentObject->FileId.Volume,
1764                                   pCurrentObject->FileId.Vnode,
1765                                   pCurrentObject->FileId.Unique);
1766
1767                     //
1768                     // Pass back the directory entries
1769                     //
1770
1771                     *ParentDirectoryCB = pParentDirEntry;
1772
1773                     *DirectoryCB = NULL;
1774
1775                     *VolumeCB = pCurrentVolume;
1776
1777                     if( ComponentName != NULL)
1778                     {
1779
1780                         *ComponentName = uniComponentName;
1781                     }
1782
1783                     *RootPathName = uniFullPathName;
1784                 }
1785             }
1786
1787             if( ntStatus != STATUS_SUCCESS)
1788             {
1789
1790                 try_return( ntStatus);
1791             }
1792
1793             //
1794             // Decrement the previous parent
1795             //
1796
1797             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1798
1799             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1800                           AFS_TRACE_LEVEL_VERBOSE,
1801                           "AFSLocateNameEntry Decrement5 count on Parent %wZ DE %p Ccb %p Cnt %d\n",
1802                           &pParentDirEntry->NameInformation.FileName,
1803                           pParentDirEntry,
1804                           NULL,
1805                           lCount);
1806
1807             ASSERT( lCount >= 0);
1808
1809             //
1810             // If we ended up substituting a name in the component then update
1811             // the full path and update the pointers
1812             //
1813
1814             if( bSubstituteName)
1815             {
1816
1817                 BOOLEAN bRelativeOpen = FALSE;
1818
1819                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1820                               AFS_TRACE_LEVEL_VERBOSE_2,
1821                               "AFSLocateNameEntry (FO: %08lX) Substituting %wZ into %wZ Index %08lX\n",
1822                               FileObject,
1823                               &uniSearchName,
1824                               &uniComponentName,
1825                               ulSubstituteIndex);
1826
1827                 if( FileObject != NULL &&
1828                     FileObject->RelatedFileObject != NULL)
1829                 {
1830
1831                     bRelativeOpen = TRUE;
1832                 }
1833
1834                 //
1835                 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
1836                 // and free the prior Buffer contents but only if the fourth
1837                 // parameter is TRUE.
1838                 //
1839
1840                 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
1841                                                     &uniComponentName,
1842                                                     &uniSearchName,
1843                                                     &uniRemainingPath,
1844                                                     bRelativeOpen ||
1845                                                             bAllocatedSymLinkBuffer ||
1846                                                             bSubstitutedName);
1847
1848                 if( !NT_SUCCESS( ntStatus))
1849                 {
1850
1851                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1852                                   AFS_TRACE_LEVEL_ERROR,
1853                                   "AFSLocateNameEntry (FO: %08lX) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
1854                                   FileObject,
1855                                   &uniSearchName,
1856                                   &uniComponentName,
1857                                   ulSubstituteIndex,
1858                                   ntStatus);
1859
1860                     try_return( ntStatus);
1861                 }
1862
1863                 //
1864                 // We have substituted a name into the buffer so if we do this again for this
1865                 // path, we need to free up the buffer we allocated.
1866                 //
1867
1868                 bSubstitutedName = TRUE;
1869             }
1870
1871             //
1872             // Update the search parameters
1873             //
1874
1875             uniPathName = uniRemainingPath;
1876
1877             //
1878             // Check if the is a SymLink entry but has no Target FileID or Name. In this
1879             // case it might be a DFS Link so let's go and evaluate it to be sure
1880             //
1881
1882             if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
1883                 pCurrentObject->TargetFileId.Vnode == 0 &&
1884                 pCurrentObject->TargetFileId.Unique == 0 &&
1885                 pDirEntry->NameInformation.TargetName.Length == 0)
1886             {
1887
1888                 ntStatus = AFSValidateSymLink( AuthGroup,
1889                                                pDirEntry);
1890
1891                 if( !NT_SUCCESS( ntStatus))
1892                 {
1893
1894                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1895                                   AFS_TRACE_LEVEL_ERROR,
1896                                   "AFSLocateNameEntry (FO: %08lX) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1897                                   FileObject,
1898                                   &pDirEntry->NameInformation.FileName,
1899                                   pCurrentObject->FileId.Cell,
1900                                   pCurrentObject->FileId.Volume,
1901                                   pCurrentObject->FileId.Vnode,
1902                                   pCurrentObject->FileId.Unique,
1903                                   ntStatus);
1904
1905                     try_return( ntStatus);
1906                 }
1907             }
1908
1909             //
1910             // Update the name array
1911             //
1912
1913             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1914                           AFS_TRACE_LEVEL_VERBOSE,
1915                           "AFSLocateNameEntry (FO: %08lX) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%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
1923             ntStatus = AFSInsertNextElement( pNameArray,
1924                                              pDirEntry);
1925
1926             if( !NT_SUCCESS( ntStatus))
1927             {
1928
1929                 try_return( ntStatus);
1930             }
1931         }       // while (TRUE)
1932
1933 try_exit:
1934
1935         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1936                       AFS_TRACE_LEVEL_VERBOSE,
1937                       "AFSLocateNameEntry (FO: %08lX) Completed processing %wZ Status %08lX\n",
1938                       FileObject,
1939                       RootPathName,
1940                       ntStatus);
1941
1942         if( ( !NT_SUCCESS( ntStatus) &&
1943               ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
1944             ntStatus == STATUS_REPARSE)
1945         {
1946
1947             if( pDirEntry != NULL)
1948             {
1949
1950                 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1951
1952                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1953                               AFS_TRACE_LEVEL_VERBOSE,
1954                               "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
1955                               &pDirEntry->NameInformation.FileName,
1956                               pDirEntry,
1957                               NULL,
1958                               lCount);
1959
1960                 ASSERT( lCount >= 0);
1961             }
1962             else if( pParentDirEntry != NULL)
1963             {
1964
1965                 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1966
1967                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1968                               AFS_TRACE_LEVEL_VERBOSE,
1969                               "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
1970                               &pParentDirEntry->NameInformation.FileName,
1971                               pParentDirEntry,
1972                               NULL,
1973                               lCount);
1974
1975                 ASSERT( lCount >= 0);
1976             }
1977
1978             if( bReleaseCurrentVolume)
1979             {
1980
1981                 ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
1982
1983                 lCount = InterlockedDecrement( &pCurrentVolume->VolumeReferenceCount);
1984
1985                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1986                               AFS_TRACE_LEVEL_VERBOSE,
1987                               "AFSLocateNameEntry Decrement3 count on volume %08lX Cnt %d\n",
1988                               pCurrentVolume,
1989                               lCount);
1990             }
1991
1992             if( RootPathName->Buffer != uniFullPathName.Buffer)
1993             {
1994
1995                 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
1996             }
1997         }
1998         else
1999         {
2000
2001             if( *ParentDirectoryCB != NULL)
2002             {
2003
2004                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2005                               AFS_TRACE_LEVEL_VERBOSE,
2006                               "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
2007                               &(*ParentDirectoryCB)->NameInformation.FileName,
2008                               *ParentDirectoryCB,
2009                               NULL,
2010                               (*ParentDirectoryCB)->DirOpenReferenceCount);
2011             }
2012
2013             if( *DirectoryCB != NULL)
2014             {
2015
2016                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2017                               AFS_TRACE_LEVEL_VERBOSE,
2018                               "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
2019                               &(*DirectoryCB)->NameInformation.FileName,
2020                               *DirectoryCB,
2021                               NULL,
2022                               (*DirectoryCB)->DirOpenReferenceCount);
2023             }
2024         }
2025
2026         if( bSubstituteName &&
2027             uniSearchName.Buffer != NULL)
2028         {
2029
2030             AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
2031         }
2032     }
2033
2034     return ntStatus;
2035 }
2036
2037 NTSTATUS
2038 AFSCreateDirEntry( IN GUID            *AuthGroup,
2039                    IN AFSObjectInfoCB *ParentObjectInfo,
2040                    IN AFSDirectoryCB *ParentDirCB,
2041                    IN PUNICODE_STRING FileName,
2042                    IN PUNICODE_STRING ComponentName,
2043                    IN ULONG Attributes,
2044                    IN OUT AFSDirectoryCB **DirEntry)
2045 {
2046
2047     NTSTATUS ntStatus = STATUS_SUCCESS;
2048     AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
2049     UNICODE_STRING uniShortName;
2050     LARGE_INTEGER liFileSize = {0,0};
2051     LONG lCount;
2052
2053     __Enter
2054     {
2055
2056         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2057                       AFS_TRACE_LEVEL_VERBOSE_2,
2058                       "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
2059                       &ParentDirCB->NameInformation.FileName,
2060                       ParentObjectInfo->FileId.Cell,
2061                       ParentObjectInfo->FileId.Volume,
2062                       ParentObjectInfo->FileId.Vnode,
2063                       ParentObjectInfo->FileId.Unique,
2064                       ComponentName,
2065                       Attributes);
2066
2067         //
2068         // OK, before inserting the node into the parent tree, issue
2069         // the request to the service for node creation
2070         // We will need to drop the lock on the parent node since the create
2071         // could cause a callback into the file system to invalidate it's cache
2072         //
2073
2074         ntStatus = AFSNotifyFileCreate( AuthGroup,
2075                                         ParentObjectInfo,
2076                                         &liFileSize,
2077                                         Attributes,
2078                                         ComponentName,
2079                                         &pDirNode);
2080
2081         //
2082         // If the returned status is STATUS_REPARSE then the entry exists
2083         // and we raced, get out.
2084
2085         if( ntStatus == STATUS_REPARSE)
2086         {
2087
2088             *DirEntry = pDirNode;
2089
2090             try_return( ntStatus = STATUS_SUCCESS);
2091         }
2092
2093         if( !NT_SUCCESS( ntStatus))
2094         {
2095
2096             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2097                           AFS_TRACE_LEVEL_ERROR,
2098                           "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
2099                           &ParentDirCB->NameInformation.FileName,
2100                           ParentObjectInfo->FileId.Cell,
2101                           ParentObjectInfo->FileId.Volume,
2102                           ParentObjectInfo->FileId.Vnode,
2103                           ParentObjectInfo->FileId.Unique,
2104                           ComponentName,
2105                           Attributes,
2106                           ntStatus);
2107
2108             try_return( ntStatus);
2109         }
2110
2111         AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2112                         TRUE);
2113
2114         //
2115         // Before attempting to insert the new entry, check if we need to validate the parent
2116         //
2117
2118         if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2119         {
2120
2121             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2122                           AFS_TRACE_LEVEL_VERBOSE,
2123                           "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2124                           &ParentDirCB->NameInformation.FileName,
2125                           ParentObjectInfo->FileId.Cell,
2126                           ParentObjectInfo->FileId.Volume,
2127                           ParentObjectInfo->FileId.Vnode,
2128                           ParentObjectInfo->FileId.Unique);
2129
2130             ntStatus = AFSVerifyEntry( AuthGroup,
2131                                        ParentDirCB);
2132
2133             if( !NT_SUCCESS( ntStatus))
2134             {
2135
2136                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2137                               AFS_TRACE_LEVEL_ERROR,
2138                               "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2139                               &ParentDirCB->NameInformation.FileName,
2140                               ParentObjectInfo->FileId.Cell,
2141                               ParentObjectInfo->FileId.Volume,
2142                               ParentObjectInfo->FileId.Vnode,
2143                               ParentObjectInfo->FileId.Unique,
2144                               ntStatus);
2145
2146                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2147
2148                 try_return( ntStatus);
2149             }
2150         }
2151
2152         //
2153         // Check for the entry in the event we raced with some other thread
2154         //
2155
2156         AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2157                                         (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2158                                         &pExistingDirNode);
2159
2160         if( pExistingDirNode != NULL)
2161         {
2162             if (AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2163                                &pExistingDirNode->ObjectInformation->FileId))
2164             {
2165
2166                 AFSDeleteDirEntry( ParentObjectInfo,
2167                                    pDirNode);
2168
2169                 lCount = InterlockedIncrement( &pExistingDirNode->DirOpenReferenceCount);
2170
2171                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2172                               AFS_TRACE_LEVEL_VERBOSE,
2173                               "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2174                               &pExistingDirNode->NameInformation.FileName,
2175                               pExistingDirNode,
2176                               lCount);
2177
2178                 *DirEntry = pExistingDirNode;
2179
2180                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2181
2182                 try_return( ntStatus = STATUS_SUCCESS);
2183             }
2184             else
2185             {
2186
2187                 //
2188                 // Need to tear down this entry and rebuild it below
2189                 //
2190
2191                 if( pExistingDirNode->DirOpenReferenceCount <= 0)
2192                 {
2193
2194                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2195                                   AFS_TRACE_LEVEL_VERBOSE,
2196                                   "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2197                                   pExistingDirNode,
2198                                   &pExistingDirNode->NameInformation.FileName,
2199                                   pExistingDirNode->ObjectInformation->FileId.Cell,
2200                                   pExistingDirNode->ObjectInformation->FileId.Volume,
2201                                   pExistingDirNode->ObjectInformation->FileId.Vnode,
2202                                   pExistingDirNode->ObjectInformation->FileId.Unique,
2203                                   pDirNode->ObjectInformation->FileId.Cell,
2204                                   pDirNode->ObjectInformation->FileId.Volume,
2205                                   pDirNode->ObjectInformation->FileId.Vnode,
2206                                   pDirNode->ObjectInformation->FileId.Unique);
2207
2208                     AFSDeleteDirEntry( ParentObjectInfo,
2209                                        pExistingDirNode);
2210                 }
2211                 else
2212                 {
2213
2214                     SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2215
2216                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2217                                   AFS_TRACE_LEVEL_VERBOSE,
2218                                   "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2219                                   pExistingDirNode,
2220                                   &pExistingDirNode->NameInformation.FileName,
2221                                   pExistingDirNode->ObjectInformation->FileId.Cell,
2222                                   pExistingDirNode->ObjectInformation->FileId.Volume,
2223                                   pExistingDirNode->ObjectInformation->FileId.Vnode,
2224                                   pExistingDirNode->ObjectInformation->FileId.Unique,
2225                                   pDirNode->ObjectInformation->FileId.Cell,
2226                                   pDirNode->ObjectInformation->FileId.Volume,
2227                                   pDirNode->ObjectInformation->FileId.Vnode,
2228                                   pDirNode->ObjectInformation->FileId.Unique);
2229
2230                     AFSRemoveNameEntry( ParentObjectInfo,
2231                                         pExistingDirNode);
2232                 }
2233
2234             }
2235         }
2236
2237         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2238                       AFS_TRACE_LEVEL_VERBOSE_2,
2239                       "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2240                       &ParentDirCB->NameInformation.FileName,
2241                       ParentObjectInfo->FileId.Cell,
2242                       ParentObjectInfo->FileId.Volume,
2243                       ParentObjectInfo->FileId.Vnode,
2244                       ParentObjectInfo->FileId.Unique,
2245                       ComponentName);
2246
2247         //
2248         // Insert the directory node
2249         //
2250
2251         AFSInsertDirectoryNode( ParentObjectInfo,
2252                                 pDirNode,
2253                                 TRUE);
2254
2255         lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
2256
2257         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2258                       AFS_TRACE_LEVEL_VERBOSE,
2259                       "AFSCreateDirEntry Increment2 count on %wZ DE %p Cnt %d\n",
2260                       &pDirNode->NameInformation.FileName,
2261                       pDirNode,
2262                       lCount);
2263
2264         //
2265         // Pass back the dir entry
2266         //
2267
2268         *DirEntry = pDirNode;
2269
2270         AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2271
2272 try_exit:
2273
2274         NOTHING;
2275     }
2276
2277     return ntStatus;
2278 }
2279
2280 void
2281 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2282                         IN AFSDirectoryCB *DirEntry,
2283                         IN BOOLEAN InsertInEnumList)
2284 {
2285
2286     LONG lCount;
2287
2288     __Enter
2289     {
2290
2291         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2292
2293         //
2294         // Insert the node into the directory node tree
2295         //
2296
2297         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2298                       AFS_TRACE_LEVEL_VERBOSE,
2299                       "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2300                       DirEntry,
2301                       &DirEntry->NameInformation.FileName);
2302
2303         ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2304
2305         if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2306         {
2307
2308             ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2309
2310             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2311                           AFS_TRACE_LEVEL_VERBOSE,
2312                           "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2313                           DirEntry,
2314                           &DirEntry->NameInformation.FileName);
2315         }
2316         else
2317         {
2318
2319             AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2320                                             DirEntry);
2321
2322             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2323                           AFS_TRACE_LEVEL_VERBOSE,
2324                           "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2325                           DirEntry,
2326                           &DirEntry->NameInformation.FileName);
2327         }
2328
2329         if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2330         {
2331
2332             ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2333
2334             SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2335
2336             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2337                           AFS_TRACE_LEVEL_VERBOSE,
2338                           "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2339                           DirEntry,
2340                           &DirEntry->NameInformation.FileName);
2341         }
2342         else
2343         {
2344
2345             AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2346                                               DirEntry);
2347
2348             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2349                           AFS_TRACE_LEVEL_VERBOSE,
2350                           "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2351                           DirEntry,
2352                           &DirEntry->NameInformation.FileName);
2353         }
2354
2355         //
2356         // Into the shortname tree
2357         //
2358
2359         if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2360         {
2361
2362             if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2363             {
2364
2365                 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2366
2367                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2368                               AFS_TRACE_LEVEL_VERBOSE,
2369                               "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2370                               DirEntry,
2371                               &DirEntry->NameInformation.FileName);
2372
2373                 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2374             }
2375             else
2376             {
2377
2378                 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2379                                                              DirEntry)))
2380                 {
2381                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2382                                   AFS_TRACE_LEVEL_VERBOSE,
2383                                   "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2384                                   DirEntry,
2385                                   &DirEntry->NameInformation.FileName);
2386                 }
2387                 else
2388                 {
2389                     SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2390
2391                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2392                                   AFS_TRACE_LEVEL_VERBOSE,
2393                                   "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2394                                   DirEntry,
2395                                   &DirEntry->NameInformation.FileName);
2396                 }
2397             }
2398         }
2399
2400         if( InsertInEnumList)
2401         {
2402
2403             //
2404             // And insert the node into the directory list
2405             //
2406
2407             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2408                           AFS_TRACE_LEVEL_VERBOSE,
2409                           "AFSInsertDirectoryNode Inserting entry %08lX %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2410                           DirEntry,
2411                           &DirEntry->NameInformation.FileName,
2412                           DirEntry->ObjectInformation->FileId.Cell,
2413                           DirEntry->ObjectInformation->FileId.Volume,
2414                           DirEntry->ObjectInformation->FileId.Vnode,
2415                           DirEntry->ObjectInformation->FileId.Unique);
2416
2417             if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2418             {
2419
2420                 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2421             }
2422             else
2423             {
2424
2425                 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2426
2427                 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2428             }
2429
2430             ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2431
2432             SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2433
2434             lCount = InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2435
2436             AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2437                           AFS_TRACE_LEVEL_VERBOSE,
2438                           "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2439                           &DirEntry->NameInformation.FileName,
2440                           lCount,
2441                           ParentObjectInfo->FileId.Cell,
2442                           ParentObjectInfo->FileId.Volume,
2443                           ParentObjectInfo->FileId.Vnode,
2444                           ParentObjectInfo->FileId.Unique);
2445         }
2446     }
2447
2448     return;
2449 }
2450
2451 NTSTATUS
2452 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2453                    IN AFSDirectoryCB *DirEntry)
2454 {
2455
2456     NTSTATUS ntStatus = STATUS_SUCCESS;
2457     LONG lCount;
2458
2459     __Enter
2460     {
2461
2462         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2463                       AFS_TRACE_LEVEL_VERBOSE,
2464                       "AFSDeleteDirEntry Deleting dir entry in parent %08lX Entry %08lX %wZ FID %08lX-%08lX-%08lX-%08lX RefCount %08lX\n",
2465                       ParentObjectInfo,
2466                       DirEntry,
2467                       &DirEntry->NameInformation.FileName,
2468                       DirEntry->ObjectInformation->FileId.Cell,
2469                       DirEntry->ObjectInformation->FileId.Volume,
2470                       DirEntry->ObjectInformation->FileId.Vnode,
2471                       DirEntry->ObjectInformation->FileId.Unique,
2472                       DirEntry->DirOpenReferenceCount);
2473
2474         ASSERT( DirEntry->DirOpenReferenceCount == 0);
2475
2476         AFSRemoveDirNodeFromParent( ParentObjectInfo,
2477                                     DirEntry,
2478                                     TRUE);
2479
2480         //
2481         // Free up the name buffer if it was reallocated
2482         //
2483
2484         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2485         {
2486
2487             AFSExFreePoolWithTag( DirEntry->NameInformation.FileName.Buffer, 0);
2488         }
2489
2490         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2491         {
2492
2493             AFSExFreePoolWithTag( DirEntry->NameInformation.TargetName.Buffer, 0);
2494         }
2495
2496         //
2497         // Dereference the object for this dir entry
2498         //
2499
2500         ASSERT( DirEntry->ObjectInformation->ObjectReferenceCount > 0);
2501
2502         lCount = AFSObjectInfoDecrement( DirEntry->ObjectInformation);
2503
2504         AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2505                       AFS_TRACE_LEVEL_VERBOSE,
2506                       "AFSDeleteDirEntry Decrement count on object %08lX Cnt %d\n",
2507                       DirEntry->ObjectInformation,
2508                       lCount);
2509
2510         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
2511             DirEntry->ObjectInformation->Links == 0)
2512         {
2513
2514             SetFlag( DirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2515         }
2516
2517         ExDeleteResourceLite( &DirEntry->NonPaged->Lock);
2518
2519         AFSExFreePoolWithTag( DirEntry->NonPaged, AFS_DIR_ENTRY_NP_TAG);
2520
2521         //
2522         // Free up the dir entry
2523         //
2524
2525         AFSExFreePoolWithTag( DirEntry, AFS_DIR_ENTRY_TAG);
2526     }
2527
2528     return ntStatus;
2529 }
2530
2531 NTSTATUS
2532 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2533                             IN AFSDirectoryCB *DirEntry,
2534                             IN BOOLEAN RemoveFromEnumList)
2535 {
2536
2537     NTSTATUS ntStatus = STATUS_SUCCESS;
2538     LONG lCount;
2539
2540     __Enter
2541     {
2542
2543
2544         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2545
2546         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2547                       AFS_TRACE_LEVEL_VERBOSE,
2548                       "AFSRemoveDirNodeFromParent Removing DirEntry %08lX %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %08lX\n",
2549                       DirEntry,
2550                       &DirEntry->NameInformation.FileName,
2551                       DirEntry->ObjectInformation->FileId.Cell,
2552                       DirEntry->ObjectInformation->FileId.Volume,
2553                       DirEntry->ObjectInformation->FileId.Vnode,
2554                       DirEntry->ObjectInformation->FileId.Unique,
2555                       ParentObjectInfo);
2556
2557         if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2558         {
2559
2560             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2561                           AFS_TRACE_LEVEL_VERBOSE,
2562                           "AFSRemoveDirNodeFromParent Removing DirEntry %08lX name %wZ\n",
2563                           DirEntry,
2564                           &DirEntry->NameInformation.FileName);
2565
2566             AFSRemoveNameEntry( ParentObjectInfo,
2567                                 DirEntry);
2568         }
2569         else
2570         {
2571
2572             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2573                           AFS_TRACE_LEVEL_VERBOSE,
2574                           "AFSRemoveDirNodeFromParent DE %p for %wZ NOT removing entry due to flag set\n",
2575                           DirEntry,
2576                           &DirEntry->NameInformation.FileName);
2577
2578         }
2579
2580         if( RemoveFromEnumList &&
2581             BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST))
2582         {
2583
2584             //
2585             // And remove the entry from the enumeration list
2586             //
2587
2588             if( DirEntry->ListEntry.fLink == NULL)
2589             {
2590
2591                 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = (AFSDirectoryCB *)DirEntry->ListEntry.bLink;
2592             }
2593             else
2594             {
2595
2596                 ((AFSDirectoryCB *)DirEntry->ListEntry.fLink)->ListEntry.bLink = DirEntry->ListEntry.bLink;
2597             }
2598
2599             if( DirEntry->ListEntry.bLink == NULL)
2600             {
2601
2602                 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = (AFSDirectoryCB *)DirEntry->ListEntry.fLink;
2603             }
2604             else
2605             {
2606
2607                 ((AFSDirectoryCB *)DirEntry->ListEntry.bLink)->ListEntry.fLink = DirEntry->ListEntry.fLink;
2608             }
2609
2610             ASSERT( ParentObjectInfo->Specific.Directory.DirectoryNodeCount > 0);
2611
2612             lCount = InterlockedDecrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2613
2614             ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2615
2616             AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2617                           AFS_TRACE_LEVEL_VERBOSE,
2618                           "AFSRemoveDirNodeFromParent Removing entry %wZ Dec Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2619                           &DirEntry->NameInformation.FileName,
2620                           lCount,
2621                           ParentObjectInfo->FileId.Cell,
2622                           ParentObjectInfo->FileId.Volume,
2623                           ParentObjectInfo->FileId.Vnode,
2624                           ParentObjectInfo->FileId.Unique);
2625
2626             DirEntry->ListEntry.fLink = NULL;
2627             DirEntry->ListEntry.bLink = NULL;
2628         }
2629     }
2630
2631     return ntStatus;
2632 }
2633
2634 NTSTATUS
2635 AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
2636                     IN OUT PUNICODE_STRING TargetFileName)
2637 {
2638
2639     NTSTATUS ntStatus = STATUS_SUCCESS;
2640     UNICODE_STRING uniFileName;
2641
2642     __Enter
2643     {
2644
2645         //
2646         // We will process backwards from the end of the name looking
2647         // for the first \ we encounter
2648         //
2649
2650         uniFileName.Length = FileName->Length;
2651         uniFileName.MaximumLength = FileName->MaximumLength;
2652
2653         uniFileName.Buffer = FileName->Buffer;
2654
2655         while( TRUE)
2656         {
2657
2658             if( uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
2659             {
2660
2661                 //
2662                 // Subtract one more character off of the filename if it is not the root
2663                 //
2664
2665                 if( uniFileName.Length > sizeof( WCHAR))
2666                 {
2667
2668                     uniFileName.Length -= sizeof( WCHAR);
2669                 }
2670
2671                 //
2672                 // Now build up the target name
2673                 //
2674
2675                 TargetFileName->Length = FileName->Length - uniFileName.Length;
2676
2677                 //
2678                 // If we are not on the root then fixup the name
2679                 //
2680
2681                 if( uniFileName.Length > sizeof( WCHAR))
2682                 {
2683
2684                     TargetFileName->Length -= sizeof( WCHAR);
2685
2686                     TargetFileName->Buffer = &uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) + 1];
2687                 }
2688                 else
2689                 {
2690
2691                     TargetFileName->Buffer = &uniFileName.Buffer[ uniFileName.Length/sizeof( WCHAR)];
2692                 }
2693
2694                 //
2695                 // Fixup the passed back filename length
2696                 //
2697
2698                 FileName->Length = uniFileName.Length;
2699
2700                 TargetFileName->MaximumLength = TargetFileName->Length;
2701
2702                 break;
2703             }
2704
2705             uniFileName.Length -= sizeof( WCHAR);
2706         }
2707     }
2708
2709     return ntStatus;
2710 }
2711
2712 NTSTATUS
2713 AFSParseName( IN PIRP Irp,
2714               IN GUID *AuthGroup,
2715               OUT PUNICODE_STRING FileName,
2716               OUT PUNICODE_STRING ParsedFileName,
2717               OUT PUNICODE_STRING RootFileName,
2718               OUT ULONG *ParseFlags,
2719               OUT AFSVolumeCB   **VolumeCB,
2720               OUT AFSDirectoryCB **ParentDirectoryCB,
2721               OUT AFSNameArrayHdr **NameArray)
2722 {
2723
2724     NTSTATUS            ntStatus = STATUS_SUCCESS;
2725     PIO_STACK_LOCATION  pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2726     AFSDeviceExt       *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2727     UNICODE_STRING      uniFullName, uniComponentName, uniRemainingPath;
2728     ULONG               ulCRC = 0;
2729     AFSDirectoryCB     *pDirEntry = NULL, *pShareDirEntry = NULL, *pTargetDirEntry = NULL;
2730     USHORT              usIndex = 0, usDriveIndex = 0;
2731     AFSCcb             *pRelatedCcb = NULL;
2732     AFSNameArrayHdr    *pNameArray = NULL, *pRelatedNameArray = NULL;
2733     USHORT              usComponentIndex = 0;
2734     USHORT              usComponentLength = 0;
2735     AFSVolumeCB        *pVolumeCB = NULL;
2736     AFSFcb             *pRelatedFcb = NULL;
2737     BOOLEAN             bReleaseTreeLock = FALSE;
2738     BOOLEAN             bIsAllShare = FALSE;
2739     LONG                lCount;
2740
2741     __Enter
2742     {
2743
2744         //
2745         // Indicate we are opening a root ...
2746         //
2747
2748         *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
2749
2750         if( pIrpSp->FileObject->RelatedFileObject != NULL)
2751         {
2752
2753             pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
2754
2755             pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
2756
2757             pRelatedNameArray = pRelatedCcb->NameArray;
2758
2759             uniFullName = pIrpSp->FileObject->FileName;
2760
2761             ASSERT( pRelatedFcb != NULL);
2762
2763             //
2764             // No wild cards in the name
2765             //
2766
2767             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2768                           AFS_TRACE_LEVEL_VERBOSE_2,
2769                           "AFSParseName (%08lX) Relative open for %wZ FID %08lX-%08lX-%08lX-%08lX component %wZ\n",
2770                           Irp,
2771                           &pRelatedCcb->DirectoryCB->NameInformation.FileName,
2772                           pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Cell,
2773                           pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Volume,
2774                           pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
2775                           pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Unique,
2776                           &uniFullName);
2777
2778             if( FsRtlDoesNameContainWildCards( &uniFullName))
2779             {
2780
2781                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2782                               AFS_TRACE_LEVEL_ERROR,
2783                               "AFSParseName (%08lX) Component %wZ contains wild cards\n",
2784                               Irp,
2785                               &uniFullName);
2786
2787                 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
2788             }
2789
2790             pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
2791
2792             pDirEntry = pRelatedCcb->DirectoryCB;
2793
2794             *FileName = pIrpSp->FileObject->FileName;
2795
2796             //
2797             // Grab the root node while checking state
2798             //
2799
2800             AFSAcquireShared( pVolumeCB->VolumeLock,
2801                               TRUE);
2802
2803             if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
2804                 BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
2805             {
2806
2807                 //
2808                 // The volume has been taken off line so fail the access
2809                 //
2810
2811                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2812                               AFS_TRACE_LEVEL_ERROR,
2813                               "AFSParseName (%08lX) Volume %08lX:%08lX OFFLINE/INVALID\n",
2814                               Irp,
2815                               pVolumeCB->ObjectInformation.FileId.Cell,
2816                               pVolumeCB->ObjectInformation.FileId.Volume);
2817
2818                 AFSReleaseResource( pVolumeCB->VolumeLock);
2819
2820                 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
2821             }
2822
2823             if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
2824             {
2825
2826                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2827                               AFS_TRACE_LEVEL_VERBOSE,
2828                               "AFSParseName (%08lX) Verifying root of volume %08lX:%08lX\n",
2829                               Irp,
2830                               pVolumeCB->ObjectInformation.FileId.Cell,
2831                               pVolumeCB->ObjectInformation.FileId.Volume);
2832
2833                 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
2834                                             pVolumeCB);
2835
2836                 if( !NT_SUCCESS( ntStatus))
2837                 {
2838
2839                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2840                                   AFS_TRACE_LEVEL_ERROR,
2841                                   "AFSParseName (%08lX) Failed verification of root Status %08lX\n",
2842                                   Irp,
2843                                   ntStatus);
2844
2845                     AFSReleaseResource( pVolumeCB->VolumeLock);
2846
2847                     try_return( ntStatus);
2848                 }
2849             }
2850
2851             AFSReleaseResource( pVolumeCB->VolumeLock);
2852
2853             if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
2854             {
2855
2856                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2857                               AFS_TRACE_LEVEL_VERBOSE,
2858                               "AFSParseName (%08lX) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2859                               Irp,
2860                               &pDirEntry->NameInformation.FileName,
2861                               pDirEntry->ObjectInformation->FileId.Cell,
2862                               pDirEntry->ObjectInformation->FileId.Volume,
2863                               pDirEntry->ObjectInformation->FileId.Vnode,
2864                               pDirEntry->ObjectInformation->FileId.Unique);
2865
2866                 //
2867                 // Directory TreeLock should be exclusively held
2868                 //
2869
2870                 AFSAcquireExcl( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
2871                                 TRUE);
2872
2873                 ntStatus = AFSVerifyEntry( AuthGroup,
2874                                            pDirEntry);
2875
2876                 AFSReleaseResource( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2877
2878                 if( !NT_SUCCESS( ntStatus))
2879                 {
2880
2881                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2882                                   AFS_TRACE_LEVEL_VERBOSE,
2883                                   "AFSParseName (%08lX) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2884                                   Irp,
2885                                   &pDirEntry->NameInformation.FileName,
2886                                   pDirEntry->ObjectInformation->FileId.Cell,
2887                                   pDirEntry->ObjectInformation->FileId.Volume,
2888                                   pDirEntry->ObjectInformation->FileId.Vnode,
2889                                   pDirEntry->ObjectInformation->FileId.Unique,
2890                                   ntStatus);
2891
2892                     try_return( ntStatus);
2893                 }
2894             }
2895
2896             //
2897             // Create our full path name buffer
2898             //
2899
2900             uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length +
2901                                                     sizeof( WCHAR) +
2902                                                     pIrpSp->FileObject->FileName.Length +
2903                                                     sizeof( WCHAR);
2904
2905             uniFullName.Length = 0;
2906
2907             uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2908                                                                     uniFullName.MaximumLength,
2909                                                                     AFS_NAME_BUFFER_THREE_TAG);
2910
2911             if( uniFullName.Buffer == NULL)
2912             {
2913
2914                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2915                               AFS_TRACE_LEVEL_ERROR,
2916                               "AFSParseName (%08lX) Failed to allocate full name buffer\n",
2917                               Irp);
2918
2919                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2920             }
2921
2922             RtlZeroMemory( uniFullName.Buffer,
2923                            uniFullName.MaximumLength);
2924
2925             RtlCopyMemory( uniFullName.Buffer,
2926                            pRelatedCcb->FullFileName.Buffer,
2927                            pRelatedCcb->FullFileName.Length);
2928
2929             uniFullName.Length = pRelatedCcb->FullFileName.Length;
2930
2931             usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
2932
2933             usComponentLength = pIrpSp->FileObject->FileName.Length;
2934
2935             if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
2936                 pIrpSp->FileObject->FileName.Length > 0 &&
2937                 pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
2938                 pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
2939             {
2940
2941                 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
2942
2943                 uniFullName.Length += sizeof( WCHAR);
2944
2945                 usComponentLength += sizeof( WCHAR);
2946             }
2947
2948             if( pIrpSp->FileObject->FileName.Length > 0)
2949             {
2950
2951                 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
2952                                pIrpSp->FileObject->FileName.Buffer,
2953                                pIr\epSp->FileObject->FileName.Length);
2954
2955                 uniFullName.Length += pIrpSp->FileObject->FileName.Length;
2956             }
2957
2958             *RootFileName = uniFullName;
2959
2960             //
2961             // We populate up to the current parent
2962             //
2963
2964             if( pRelatedNameArray == NULL)
2965             {
2966
2967                 //
2968                 // Init and populate our name array
2969                 //
2970
2971                 pNameArray = AFSInitNameArray( NULL,
2972                                                0);
2973
2974                 if( pNameArray == NULL)
2975                 {
2976
2977                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2978                                   AFS_TRACE_LEVEL_VERBOSE,
2979                                   "AFSParseName (%08lX) Failed to initialize name array\n",
2980                                   Irp);
2981
2982                     AFSExFreePoolWithTag( uniFullName.Buffer, 0);
2983
2984                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2985                 }
2986
2987                 ntStatus = AFSPopulateNameArray( pNameArray,
2988                                                  NULL,
2989                                                  pRelatedCcb->DirectoryCB);
2990             }
2991             else
2992             {
2993
2994                 //
2995                 // Init and populate our name array
2996                 //
2997
2998                 pNameArray = AFSInitNameArray( NULL,
2999                                                pRelatedNameArray->MaxElementCount);
3000
3001                 if( pNameArray == NULL)
3002                 {
3003
3004                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3005                                   AFS_TRACE_LEVEL_VERBOSE,
3006                                   "AFSParseName (%08lX) Failed to initialize name array\n",
3007                                   Irp);
3008
3009                     AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3010
3011                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3012                 }
3013
3014                 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
3015                                                                  pRelatedNameArray,
3016                                                                  pRelatedCcb->DirectoryCB);
3017             }
3018
3019             if( !NT_SUCCESS( ntStatus))
3020             {
3021
3022                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3023                               AFS_TRACE_LEVEL_VERBOSE,
3024                               "AFSParseName (%08lX) Failed to populate name array\n",
3025                               Irp);
3026
3027                 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3028
3029                 try_return( ntStatus);
3030             }
3031
3032             ParsedFileName->Length = usComponentLength;
3033             ParsedFileName->MaximumLength = uniFullName.MaximumLength;
3034
3035             ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
3036
3037             //
3038             // Indicate to caller that RootFileName must be freed
3039             //
3040
3041             SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
3042
3043             *NameArray = pNameArray;
3044
3045             *VolumeCB = pVolumeCB;
3046
3047             //
3048             // Increment our volume reference count
3049             //
3050
3051             lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
3052
3053             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3054                           AFS_TRACE_LEVEL_VERBOSE,
3055                           "AFSParseName Increment count on volume %08lX Cnt %d\n",
3056                           pVolumeCB,
3057                           lCount);
3058
3059             *ParentDirectoryCB = pDirEntry;
3060
3061             lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
3062
3063             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3064                           AFS_TRACE_LEVEL_VERBOSE,
3065                           "AFSParseName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
3066                           &pDirEntry->NameInformation.FileName,
3067                           pDirEntry,
3068                           NULL,
3069                           lCount);
3070
3071             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3072                           AFS_TRACE_LEVEL_VERBOSE_2,
3073                           "AFSParseName (%08lX) Returning full name %wZ\n",
3074                           Irp,
3075                           &uniFullName);
3076
3077             try_return( ntStatus);
3078         }
3079
3080         //
3081         // No wild cards in the name
3082         //
3083
3084         uniFullName = pIrpSp->FileObject->FileName;
3085
3086         if( FsRtlDoesNameContainWildCards( &uniFullName) ||
3087             uniFullName.Length < AFSServerName.Length)
3088         {
3089
3090             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3091                           AFS_TRACE_LEVEL_ERROR,
3092                           "AFSParseName (%08lX) Name %wZ contains wild cards or too short\n",
3093                           Irp,
3094                           &uniFullName);
3095
3096             try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3097         }
3098
3099         //
3100         // The name is a fully qualified name. Parse out the server/share names and
3101         // point to the root qualified name
3102         // First thing is to locate the server name
3103         //
3104
3105         FsRtlDissectName( uniFullName,
3106                           &uniComponentName,
3107                           &uniRemainingPath);
3108
3109         uniFullName = uniRemainingPath;
3110
3111         //
3112         // This component is the server name we are serving
3113         //
3114
3115         if( RtlCompareUnicodeString( &uniComponentName,
3116                                      &AFSServerName,
3117                                      TRUE) != 0)
3118         {
3119
3120             //
3121             // Drive letter based name?
3122             //
3123
3124             uniFullName = pIrpSp->FileObject->FileName;
3125
3126             while( usIndex < uniFullName.Length/sizeof( WCHAR))
3127             {
3128
3129                 if( uniFullName.Buffer[ usIndex] == L':')
3130                 {
3131
3132                     uniFullName.Buffer = &uniFullName.Buffer[ usIndex + 2];
3133
3134                     uniFullName.Length -= (usIndex + 2) * sizeof( WCHAR);
3135
3136                     usDriveIndex = usIndex - 1;
3137
3138                     break;
3139                 }
3140
3141                 usIndex++;
3142             }
3143
3144             //
3145             // Do we have the right server name now?
3146             //
3147
3148             FsRtlDissectName( uniFullName,
3149                               &uniComponentName,
3150                               &uniRemainingPath);
3151
3152             uniFullName = uniRemainingPath;
3153
3154             //
3155             // This component is the server name we are serving
3156             //
3157
3158             if( RtlCompareUnicodeString( &uniComponentName,
3159                                          &AFSServerName,
3160                                          TRUE) != 0)
3161             {
3162
3163                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3164                               AFS_TRACE_LEVEL_ERROR,
3165                               "AFSParseName (%08lX) Name %wZ does not have server name\n",
3166                               Irp,
3167                               &pIrpSp->FileObject->FileName);
3168
3169                 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3170             }
3171
3172             //
3173             // Validate this drive letter is actively mapped
3174             //
3175
3176             if( usDriveIndex > 0 &&
3177                 !AFSIsDriveMapped( pIrpSp->FileObject->FileName.Buffer[ usDriveIndex]))
3178             {
3179
3180                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3181                               AFS_TRACE_LEVEL_ERROR,
3182                               "AFSParseName (%08lX) Name %wZ contains invalid drive mapping\n",
3183                               Irp,
3184                               &pIrpSp->FileObject->FileName);
3185
3186                 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3187             }
3188         }
3189
3190         if( FsRtlDoesNameContainWildCards( &uniFullName))
3191         {
3192
3193             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3194                           AFS_TRACE_LEVEL_ERROR,
3195                           "AFSParseName (%08lX) Component %wZ contains wild cards\n",
3196                           Irp,
3197                           &uniFullName);
3198
3199             try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3200         }
3201
3202         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3203                       AFS_TRACE_LEVEL_VERBOSE_2,
3204                       "AFSParseName (%08lX) Processing full name %wZ\n",
3205                       Irp,
3206                       &uniFullName);
3207
3208         if( uniFullName.Length > 0 &&
3209             uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] == L'\\')
3210         {
3211
3212             uniFullName.Length -= sizeof( WCHAR);
3213         }
3214
3215         //
3216         // Be sure we are online and ready to go
3217         //
3218
3219         AFSAcquireShared( AFSGlobalRoot->VolumeLock,
3220                           TRUE);
3221
3222         if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3223             BooleanFlagOn( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3224         {
3225
3226             //
3227             // The volume has been taken off line so fail the access
3228             //
3229
3230             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3231                           AFS_TRACE_LEVEL_ERROR,
3232                           "AFSParseName (%08lX) Volume %08lX:%08lX OFFLINE/INVALID\n",
3233                           Irp,
3234                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3235                           AFSGlobalRoot->ObjectInformation.FileId.Volume);
3236
3237             AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3238
3239             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3240         }
3241
3242         if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3243         {
3244
3245             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3246                           AFS_TRACE_LEVEL_VERBOSE,
3247                           "AFSParseName (%08lX) Verifying root of volume %08lX:%08lX\n",
3248                           Irp,
3249                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3250                           AFSGlobalRoot->ObjectInformation.FileId.Volume);
3251
3252             ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3253                                         AFSGlobalRoot);
3254
3255             if( !NT_SUCCESS( ntStatus))
3256             {
3257
3258                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3259                               AFS_TRACE_LEVEL_ERROR,
3260                               "AFSParseName (%08lX) Failed verification of root Status %08lX\n",
3261                               Irp,
3262                               ntStatus);
3263
3264                 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3265
3266                 try_return( ntStatus);
3267             }
3268         }
3269
3270         AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3271
3272         if( !BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3273         {
3274
3275             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3276                           AFS_TRACE_LEVEL_VERBOSE,
3277                           "AFSParseName (%08lX) Enumerating global root of volume %08lX:%08lX\n",
3278                           Irp,
3279                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3280                           AFSGlobalRoot->ObjectInformation.FileId.Volume);
3281
3282             ntStatus = AFSEnumerateGlobalRoot( AuthGroup);
3283
3284             if( !NT_SUCCESS( ntStatus))
3285             {
3286
3287                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3288                               AFS_TRACE_LEVEL_ERROR,
3289                               "AFSParseName (%08lX) Failed enumeraiton of root Status %08lX\n",
3290                               Irp,
3291                               ntStatus);
3292
3293                 try_return( ntStatus);
3294             }
3295         }
3296
3297         //
3298         // Check for the \\Server access and return it as though it where \\Server\Globalroot
3299         //
3300
3301         if( uniRemainingPath.Buffer == NULL ||
3302             ( uniRemainingPath.Length == sizeof( WCHAR) &&
3303               uniRemainingPath.Buffer[ 0] == L'\\'))
3304         {
3305
3306             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3307                           AFS_TRACE_LEVEL_VERBOSE_2,
3308                           "AFSParseName (%08lX) Returning global root access\n",
3309                           Irp);
3310
3311             lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3312
3313             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3314                           AFS_TRACE_LEVEL_VERBOSE,
3315                           "AFSParseName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3316                           &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3317                           AFSGlobalRoot->DirectoryCB,
3318                           NULL,
3319                           lCount);
3320
3321             *VolumeCB = NULL;
3322
3323             FileName->Length = 0;
3324             FileName->MaximumLength = 0;
3325             FileName->Buffer = NULL;
3326
3327             try_return( ntStatus = STATUS_SUCCESS);
3328         }
3329
3330         *RootFileName = uniFullName;
3331
3332         //
3333         // Include the starting \ in the root name
3334         //
3335
3336         if( RootFileName->Buffer[ 0] != L'\\')
3337         {
3338             RootFileName->Buffer--;
3339             RootFileName->Length += sizeof( WCHAR);
3340             RootFileName->MaximumLength += sizeof( WCHAR);
3341         }
3342
3343         //
3344         // Get the 'share' name
3345         //
3346
3347         FsRtlDissectName( uniFullName,
3348                           &uniComponentName,
3349                           &uniRemainingPath);
3350
3351         if( FsRtlDoesNameContainWildCards( &uniFullName))
3352         {
3353
3354             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3355                           AFS_TRACE_LEVEL_ERROR,
3356                           "AFSParseName (%08lX) Component %wZ contains wild cards\n",
3357                           Irp,
3358                           &uniComponentName);
3359
3360             try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3361         }
3362
3363         //
3364         // If this is the ALL access then perform some additional processing
3365         //
3366
3367         if( uniComponentName.Length == 0 ||
3368             RtlCompareUnicodeString( &uniComponentName,
3369                                      &AFSGlobalRootName,
3370                                      TRUE) == 0)
3371         {
3372
3373             bIsAllShare = TRUE;
3374
3375             //
3376             // If there is nothing else then get out
3377             //
3378
3379             if( uniRemainingPath.Buffer == NULL ||
3380                 uniRemainingPath.Length == 0 ||
3381                 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3382                   uniRemainingPath.Buffer[ 0] == L'\\'))
3383             {
3384
3385                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3386                               AFS_TRACE_LEVEL_VERBOSE_2,
3387                               "AFSParseName (%08lX) Returning global root access\n",
3388                               Irp);
3389
3390                 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3391
3392                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3393                               AFS_TRACE_LEVEL_VERBOSE,
3394                               "AFSParseName Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
3395                               &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3396                               AFSGlobalRoot->DirectoryCB,
3397                               NULL,
3398                               lCount);
3399
3400                 *VolumeCB = NULL;
3401
3402                 FileName->Length = 0;
3403                 FileName->MaximumLength = 0;
3404                 FileName->Buffer = NULL;
3405
3406                 try_return( ntStatus = STATUS_SUCCESS);
3407             }
3408
3409             //
3410             // Process the name again to strip off the ALL portion
3411             //
3412
3413             uniFullName = uniRemainingPath;
3414
3415             FsRtlDissectName( uniFullName,
3416                               &uniComponentName,
3417                               &uniRemainingPath);
3418
3419             //
3420             // Check for the PIOCtl name
3421             //
3422
3423             if( RtlCompareUnicodeString( &uniComponentName,
3424                                          &AFSPIOCtlName,
3425                                          TRUE) == 0)
3426             {
3427
3428                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3429                               AFS_TRACE_LEVEL_VERBOSE_2,
3430                               "AFSParseName (%08lX) Returning root PIOCtl access\n",
3431                               Irp);
3432
3433                 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3434
3435                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3436                               AFS_TRACE_LEVEL_VERBOSE,
3437                               "AFSParseName Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
3438                               &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3439                               AFSGlobalRoot->DirectoryCB,
3440                               NULL,
3441                               lCount);
3442
3443                 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3444
3445                 *VolumeCB = NULL;
3446
3447                 *FileName = AFSPIOCtlName;
3448
3449                 try_return( ntStatus = STATUS_SUCCESS);
3450             }
3451         }
3452         else if( (pDirEntry = AFSGetSpecialShareNameEntry( &uniComponentName,
3453                                                            &uniRemainingPath)) != NULL)
3454         {
3455
3456             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3457                           AFS_TRACE_LEVEL_VERBOSE_2,
3458                           "AFSParseName (%08lX) Returning root share name %wZ access\n",
3459                           Irp,
3460                           &uniComponentName);
3461
3462             //
3463             // Add in the full share name to pass back
3464             //
3465
3466             if( uniRemainingPath.Buffer != NULL)
3467             {
3468
3469                 //
3470                 // This routine strips off the leading slash so add it back in
3471                 //
3472
3473                 uniRemainingPath.Buffer--;
3474                 uniRemainingPath.Length += sizeof( WCHAR);
3475                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3476
3477                 //
3478                 // And the cell name
3479                 //
3480
3481                 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3482                 uniRemainingPath.Length += uniComponentName.Length;
3483                 uniRemainingPath.MaximumLength += uniComponentName.Length;
3484
3485                 uniComponentName = uniRemainingPath;
3486             }
3487
3488             *VolumeCB = NULL;
3489
3490             *FileName = uniComponentName;
3491
3492             *ParentDirectoryCB = pDirEntry;
3493
3494             ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3495
3496             lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
3497
3498             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3499                           AFS_TRACE_LEVEL_VERBOSE,
3500                           "AFSParseName Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
3501                           &pDirEntry->NameInformation.FileName,
3502                           pDirEntry,
3503                           NULL,
3504                           lCount);
3505
3506             try_return( ntStatus = STATUS_SUCCESS);
3507         }
3508
3509         //
3510         // Determine the 'share' we are accessing
3511         //
3512
3513         ulCRC = AFSGenerateCRC( &uniComponentName,
3514                                 FALSE);
3515
3516         AFSAcquireShared( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3517                           TRUE);
3518
3519         bReleaseTreeLock = TRUE;
3520
3521         AFSLocateCaseSensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
3522                                         ulCRC,
3523                                         &pDirEntry);
3524
3525         if( pDirEntry == NULL)
3526         {
3527
3528             ulCRC = AFSGenerateCRC( &uniComponentName,
3529                                     TRUE);
3530
3531             AFSLocateCaseInsensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
3532                                               ulCRC,
3533                                               &pDirEntry);
3534
3535             if( pDirEntry == NULL)
3536             {
3537
3538                 //
3539                 // OK, if this component is a valid short name then try
3540                 // a lookup in the short name tree
3541                 //
3542
3543                 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3544                     RtlIsNameLegalDOS8Dot3( &uniComponentName,
3545                                             NULL,
3546                                             NULL))
3547                 {
3548
3549                     AFSLocateShortNameDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.ShortNameTree,
3550                                                 ulCRC,
3551                                                 &pDirEntry);
3552                 }
3553
3554                 if( pDirEntry == NULL)
3555                 {
3556
3557                     //
3558                     // Check with the service whether it is a valid cell name
3559                     //
3560
3561                     AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3562
3563                     bReleaseTreeLock = FALSE;
3564
3565                     ntStatus = AFSCheckCellName( AuthGroup,
3566                                                  &uniComponentName,
3567                                                  &pDirEntry);
3568
3569                     if( !NT_SUCCESS( ntStatus))
3570                     {
3571
3572                         if ( bIsAllShare &&
3573                              uniRemainingPath.Length == 0 &&
3574                              ntStatus == STATUS_OBJECT_PATH_NOT_FOUND)
3575                         {
3576
3577                             ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
3578                         }
3579
3580                         try_return( ntStatus);
3581                     }
3582                 }
3583             }
3584         }
3585
3586         if( bReleaseTreeLock)
3587         {
3588             AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3589         }
3590
3591
3592         //
3593         // Be sure we are starting from the correct volume
3594         //
3595
3596         if( pDirEntry->ObjectInformation->VolumeCB != AFSGlobalRoot)
3597         {
3598
3599             //
3600             // We dropped the global root in the CheckCellName routine which is the
3601             // only way we can be here
3602             //
3603
3604             pVolumeCB = pDirEntry->ObjectInformation->VolumeCB;
3605
3606             //
3607             // Init our name array
3608             //
3609
3610             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
3611                                            0);
3612
3613             if( pNameArray == NULL)
3614             {
3615
3616                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3617                               AFS_TRACE_LEVEL_VERBOSE,
3618                               "AFSParseName (%08lX) Failed to initialize name array\n",
3619                               Irp);
3620
3621                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3622             }
3623
3624             ntStatus = AFSInsertNextElement( pNameArray,
3625                                              pVolumeCB->DirectoryCB);
3626
3627             if ( ntStatus)
3628             {
3629
3630                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3631                               AFS_TRACE_LEVEL_VERBOSE,
3632                               "AFSParseName (%08lX) Failed to insert name array element\n",
3633                               Irp);
3634
3635                 try_return( ntStatus);
3636             }
3637
3638             //
3639             // In this case don't add back in the 'share' name since that is where we are
3640             // starting. Just put the leading slash back in
3641             //
3642
3643             if( uniRemainingPath.Buffer != NULL)
3644             {
3645
3646                 uniRemainingPath.Buffer--;
3647                 uniRemainingPath.Length += sizeof( WCHAR);
3648                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3649
3650                 if( uniRemainingPath.Length > sizeof( WCHAR))
3651                 {
3652
3653                     ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3654                 }
3655
3656                 //
3657                 // Pass back the parent being the root of the volume
3658                 //
3659
3660                 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3661             }
3662             else
3663             {
3664
3665                 //
3666                 // Pass back a root slash
3667                 //
3668
3669                 uniRemainingPath = uniComponentName;
3670
3671                 uniRemainingPath.Buffer--;
3672                 uniRemainingPath.Length = sizeof( WCHAR);
3673                 uniRemainingPath.MaximumLength = sizeof( WCHAR);
3674
3675                 //
3676                 // This is a root open so pass back no parent
3677                 //
3678
3679                 *ParentDirectoryCB = NULL;
3680             }
3681         }
3682         else
3683         {
3684
3685             pVolumeCB = AFSGlobalRoot;
3686
3687             //
3688             // Init our name array
3689             //
3690
3691             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
3692                                            0);
3693             if( pNameArray == NULL)
3694             {
3695
3696                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3697                               AFS_TRACE_LEVEL_VERBOSE,
3698                               "AFSParseName (%08lX) Failed to initialize name array\n",
3699                               Irp);
3700
3701                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3702             }
3703
3704             //
3705             // Add back in the 'share' portion of the name since we will parse it out on return
3706             //
3707
3708             if( uniRemainingPath.Buffer != NULL)
3709             {
3710
3711                 //
3712                 // This routine strips off the leading slash so add it back in
3713                 //
3714
3715                 uniRemainingPath.Buffer--;
3716                 uniRemainingPath.Length += sizeof( WCHAR);
3717                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3718
3719                 if( uniRemainingPath.Length > sizeof( WCHAR))
3720                 {
3721
3722                     ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3723                 }
3724
3725                 //
3726                 // And the cell name
3727                 //
3728
3729                 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3730                 uniRemainingPath.Length += uniComponentName.Length;
3731                 uniRemainingPath.MaximumLength += uniComponentName.Length;
3732             }
3733             else
3734             {
3735
3736                 uniRemainingPath = uniComponentName;
3737             }
3738
3739             //
3740             // And the leading slash again ...
3741             //
3742
3743             uniRemainingPath.Buffer--;
3744             uniRemainingPath.Length += sizeof( WCHAR);
3745             uniRemainingPath.MaximumLength += sizeof( WCHAR);
3746
3747             lCount = InterlockedIncrement( &pVolumeCB->DirectoryCB->DirOpenReferenceCount);
3748
3749             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3750                           AFS_TRACE_LEVEL_VERBOSE,
3751                           "AFSParseName Increment6 count on %wZ DE %p Ccb %p Cnt %d\n",
3752                           &pVolumeCB->DirectoryCB->NameInformation.FileName,
3753                           pVolumeCB->DirectoryCB,
3754                           NULL,
3755                           lCount);
3756
3757             //
3758             // Pass back the parent being the volume root
3759             //
3760
3761             *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3762
3763         }
3764
3765         //
3766         // Return the remaining portion as the file name
3767         //
3768
3769         *FileName = uniRemainingPath;
3770
3771         *ParsedFileName = uniRemainingPath;
3772
3773         *NameArray = pNameArray;
3774
3775         *VolumeCB = pVolumeCB;
3776
3777         //
3778         // Increment our reference on the volume
3779         //
3780
3781         lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
3782
3783         AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3784                       AFS_TRACE_LEVEL_VERBOSE,
3785                       "AFSParseName Increment2 count on global volume %08lX Cnt %d\n",
3786                       pVolumeCB,
3787                       lCount);
3788
3789 try_exit:
3790
3791         if( NT_SUCCESS( ntStatus))
3792         {
3793
3794             if( *ParentDirectoryCB != NULL)
3795             {
3796
3797                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3798                               AFS_TRACE_LEVEL_VERBOSE,
3799                               "AFSParseName Count on %wZ DE %p Ccb %p Cnt %d\n",
3800                               &(*ParentDirectoryCB)->NameInformation.FileName,
3801                               *ParentDirectoryCB,
3802                               NULL,
3803                               (*ParentDirectoryCB)->DirOpenReferenceCount);
3804             }
3805         }
3806
3807         if( *VolumeCB != NULL)
3808         {
3809             ASSERT( (*VolumeCB)->VolumeReferenceCount > 1);
3810         }
3811
3812         if( ntStatus != STATUS_SUCCESS)
3813         {
3814
3815             if( pNameArray != NULL)
3816             {
3817
3818                 AFSFreeNameArray( pNameArray);
3819             }
3820         }
3821     }
3822
3823     return ntStatus;
3824 }
3825
3826 NTSTATUS
3827 AFSCheckCellName( IN GUID *AuthGroup,
3828                   IN UNICODE_STRING *CellName,
3829                   OUT AFSDirectoryCB **ShareDirEntry)
3830 {
3831
3832     NTSTATUS ntStatus = STATUS_SUCCESS;
3833     UNICODE_STRING uniName;
3834     AFSDirEnumEntry *pDirEnumEntry = NULL;
3835     AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3836     AFSDirHdr *pDirHdr = &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr;
3837     AFSDirectoryCB *pDirNode = NULL;
3838     UNICODE_STRING uniDirName, uniTargetName;
3839     AFSVolumeCB *pVolumeCB = NULL;
3840     LONG lCount;
3841
3842     __Enter
3843     {
3844
3845         //
3846         // Look for some default names we will not handle
3847         //
3848
3849         RtlInitUnicodeString( &uniName,
3850                               L"IPC$");
3851
3852         if( RtlCompareUnicodeString( &uniName,
3853                                      CellName,
3854                                      TRUE) == 0)
3855         {
3856
3857             try_return( ntStatus = STATUS_NO_SUCH_FILE);
3858         }
3859
3860         RtlInitUnicodeString( &uniName,
3861                               L"wkssvc");
3862
3863         if( RtlCompareUnicodeString( &uniName,
3864                                      CellName,
3865                                      TRUE) == 0)
3866         {
3867
3868             try_return( ntStatus = STATUS_NO_SUCH_FILE);
3869         }
3870
3871         RtlInitUnicodeString( &uniName,
3872                               L"srvsvc");
3873
3874         if( RtlCompareUnicodeString( &uniName,
3875                                      CellName,
3876                                      TRUE) == 0)
3877         {
3878
3879             try_return( ntStatus = STATUS_NO_SUCH_FILE);
3880         }
3881
3882         RtlInitUnicodeString( &uniName,
3883                               L"PIPE");
3884
3885         if( RtlCompareUnicodeString( &uniName,
3886                                      CellName,
3887                                      TRUE) == 0)
3888         {
3889
3890             try_return( ntStatus = STATUS_NO_SUCH_FILE);
3891         }
3892
3893         //
3894         // OK, ask the CM about this component name
3895         //
3896
3897         ntStatus = AFSEvaluateTargetByName( AuthGroup,
3898                                             &AFSGlobalRoot->ObjectInformation,
3899                                             CellName,
3900                                             &pDirEnumEntry);
3901
3902         if( !NT_SUCCESS( ntStatus))
3903         {
3904
3905             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3906                           AFS_TRACE_LEVEL_WARNING,
3907                           "AFSCheckCellName entry %wZ does not exist parent FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3908                           CellName,
3909                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3910                           AFSGlobalRoot->ObjectInformation.FileId.Volume,
3911                           AFSGlobalRoot->ObjectInformation.FileId.Vnode,
3912                           AFSGlobalRoot->ObjectInformation.FileId.Unique,
3913                           ntStatus);
3914
3915             try_return( ntStatus);
3916         }
3917
3918         //
3919         // OK, we have a dir enum entry back so add it to the root node
3920         //
3921
3922         uniDirName = *CellName;
3923
3924         uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
3925         uniTargetName.MaximumLength = uniTargetName.Length;
3926         uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
3927
3928         //
3929         // Is this entry a root volume entry?
3930         //
3931
3932         if( pDirEnumEntry->FileId.Cell != AFSGlobalRoot->ObjectInformation.FileId.Cell ||
3933             pDirEnumEntry->FileId.Volume != AFSGlobalRoot->ObjectInformation.FileId.Volume)
3934         {
3935
3936             //
3937             // Build the root volume entry
3938             //
3939
3940             ntStatus = AFSBuildRootVolume( AuthGroup,
3941                                            &pDirEnumEntry->FileId,
3942                                            &pVolumeCB);
3943
3944             if( !NT_SUCCESS( ntStatus))
3945             {
3946                 try_return( ntStatus);
3947             }
3948
3949             *ShareDirEntry = pVolumeCB->DirectoryCB;
3950
3951             lCount = InterlockedIncrement( &pVolumeCB->DirectoryCB->DirOpenReferenceCount);
3952
3953             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3954                           AFS_TRACE_LEVEL_VERBOSE,
3955                           "AFSCheckCellName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
3956                           &pVolumeCB->DirectoryCB->NameInformation.FileName,
3957                           pVolumeCB->DirectoryCB,
3958                           NULL,
3959                           lCount);
3960
3961             lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
3962
3963             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3964                           AFS_TRACE_LEVEL_VERBOSE,
3965                           "AFSCheckCellName Increment count on volume %08lX Cnt %d\n",
3966                           pVolumeCB,
3967                           lCount);
3968         }
3969         else
3970         {
3971
3972             lCount = InterlockedIncrement( &pDirHdr->ContentIndex);
3973
3974             pDirNode = AFSInitDirEntry( &AFSGlobalRoot->ObjectInformation,
3975                                         &uniDirName,
3976                                         &uniTargetName,
3977                                         pDirEnumEntry,
3978                                         (ULONG)lCount);
3979
3980             if( pDirNode == NULL)
3981             {
3982
3983                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3984             }
3985
3986             //
3987             // Init the short name if we have one
3988             //
3989
3990             if( pDirEnumEntry->ShortNameLength > 0)
3991             {
3992
3993                 pDirNode->NameInformation.ShortNameLength = pDirEnumEntry->ShortNameLength;
3994
3995                 RtlCopyMemory( pDirNode->NameInformation.ShortName,
3996                                pDirEnumEntry->ShortName,
3997                                pDirNode->NameInformation.ShortNameLength);
3998             }
3999
4000             AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4001                             TRUE);
4002
4003             //
4004             // Insert the node into the name tree
4005             //
4006
4007             ASSERT( ExIsResourceAcquiredExclusiveLite( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock));
4008
4009             if( pDirHdr->CaseSensitiveTreeHead == NULL)
4010             {
4011
4012                 pDirHdr->CaseSensitiveTreeHead = pDirNode;
4013             }
4014             else
4015             {
4016
4017                 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( pDirHdr->CaseSensitiveTreeHead,
4018                                                                  pDirNode)))
4019                 {
4020
4021                     AFSDeleteDirEntry( &AFSGlobalRoot->ObjectInformation,
4022                                        pDirNode);
4023
4024                     AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4025
4026                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4027                 }
4028             }
4029
4030             ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
4031
4032             if( pDirHdr->CaseInsensitiveTreeHead == NULL)
4033             {
4034
4035                 pDirHdr->CaseInsensitiveTreeHead = pDirNode;
4036
4037                 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
4038             }
4039             else
4040             {
4041
4042                 AFSInsertCaseInsensitiveDirEntry( pDirHdr->CaseInsensitiveTreeHead,
4043                                                   pDirNode);
4044             }
4045
4046             if( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead == NULL)
4047             {
4048
4049                 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead = pDirNode;
4050             }
4051             else
4052             {
4053
4054                 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
4055
4056                 pDirNode->ListEntry.bLink = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail;
4057             }
4058
4059             AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail = pDirNode;
4060
4061             SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
4062
4063             lCount = InterlockedIncrement( &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeCount);
4064
4065             AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
4066                           AFS_TRACE_LEVEL_VERBOSE,
4067                           "AFSCheckCellName Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
4068                           &pDirNode->NameInformation.FileName,
4069                           lCount,
4070                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
4071                           AFSGlobalRoot->ObjectInformation.FileId.Volume,
4072                           AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4073                           AFSGlobalRoot->ObjectInformation.FileId.Unique);
4074
4075             lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
4076
4077             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4078                           AFS_TRACE_LEVEL_VERBOSE,
4079                           "AFSCheckCellName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
4080                           &pDirNode->NameInformation.FileName,
4081                           pDirNode,
4082                           NULL,
4083                           lCount);
4084
4085             AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4086
4087             //
4088             // Pass back the dir node
4089             //
4090
4091             *ShareDirEntry = pDirNode;
4092         }
4093
4094 try_exit:
4095
4096         if( pDirEnumEntry != NULL)
4097         {
4098
4099             AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_31_TAG);
4100         }
4101     }
4102
4103     return ntStatus;
4104 }
4105
4106 NTSTATUS
4107 AFSBuildMountPointTarget( IN GUID *AuthGroup,
4108                           IN AFSDirectoryCB  *DirectoryCB,
4109                           OUT AFSVolumeCB **TargetVolumeCB)
4110 {
4111
4112     NTSTATUS ntStatus = STATUS_SUCCESS;
4113     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4114     AFSDirEnumEntry *pDirEntry = NULL;
4115     AFSDirectoryCB *pDirNode = NULL;
4116     UNICODE_STRING uniDirName, uniTargetName;
4117     ULONGLONG       ullIndex = 0;
4118     AFSVolumeCB *pVolumeCB = NULL;
4119     AFSFileID stTargetFileID;
4120     LONG lCount;
4121     BOOLEAN bReleaseVolumeLock = FALSE;
4122
4123     __Enter
4124     {
4125
4126         //
4127         // Loop on each entry, building the chain until we encounter the final target
4128         //
4129
4130         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4131                       AFS_TRACE_LEVEL_VERBOSE_2,
4132                       "AFSBuildMountPointTarget Building target directory for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4133                       &DirectoryCB->NameInformation.FileName,
4134                       DirectoryCB->ObjectInformation->FileId.Cell,
4135                       DirectoryCB->ObjectInformation->FileId.Volume,
4136                       DirectoryCB->ObjectInformation->FileId.Vnode,
4137                       DirectoryCB->ObjectInformation->FileId.Unique);
4138
4139         //
4140         // Do we need to evaluate the node?
4141         //
4142
4143         //if( DirectoryCB->ObjectInformation->TargetFileId.Vnode == 0 &&
4144         //    DirectoryCB->ObjectInformation->TargetFileId.Unique == 0)
4145         {
4146
4147             //
4148             // Go evaluate the current target to get the target fid
4149             //
4150
4151             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4152                           AFS_TRACE_LEVEL_VERBOSE_2,
4153                           "AFSBuildMountPointTarget Evaluating target %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4154                               &DirectoryCB->NameInformation.FileName,
4155                               DirectoryCB->ObjectInformation->FileId.Cell,
4156                               DirectoryCB->ObjectInformation->FileId.Volume,
4157                               DirectoryCB->ObjectInformation->FileId.Vnode,
4158                               DirectoryCB->ObjectInformation->FileId.Unique);
4159
4160             ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
4161                                               AuthGroup,
4162                                               FALSE,
4163                                               &pDirEntry);
4164
4165             if( !NT_SUCCESS( ntStatus))
4166             {
4167
4168                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4169                               AFS_TRACE_LEVEL_ERROR,
4170                               "AFSBuildMountPointTarget Failed to evaluate target %wZ Status %08lX\n",
4171                               &DirectoryCB->NameInformation.FileName,
4172                               ntStatus);
4173                 try_return( ntStatus);
4174             }
4175
4176             if( pDirEntry->TargetFileId.Vnode == 0 &&
4177                 pDirEntry->TargetFileId.Unique == 0)
4178             {
4179
4180                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4181                               AFS_TRACE_LEVEL_ERROR,
4182                               "AFSBuildMountPointTarget Target %wZ FID %08lX-%08lX-%08lX-%08lX service returned zero FID\n",
4183                               &DirectoryCB->NameInformation.FileName,
4184                               DirectoryCB->ObjectInformation->FileId.Cell,
4185                               DirectoryCB->ObjectInformation->FileId.Volume,
4186                               DirectoryCB->ObjectInformation->FileId.Vnode,
4187                               DirectoryCB->ObjectInformation->FileId.Unique);
4188
4189                 try_return( ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED);
4190             }
4191
4192             AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
4193                             TRUE);
4194
4195             ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
4196                                             &DirectoryCB->Flags,
4197                                             (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4198                                             (USHORT)pDirEntry->TargetNameLength);
4199
4200             if( !NT_SUCCESS( ntStatus))
4201             {
4202
4203                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4204
4205                 try_return( ntStatus);
4206             }
4207
4208             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4209
4210             DirectoryCB->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
4211         }
4212
4213         stTargetFileID = DirectoryCB->ObjectInformation->TargetFileId;
4214
4215         //
4216         // Try to locate this FID. First the volume then the
4217         // entry itself
4218         //
4219
4220         ullIndex = AFSCreateHighIndex( &stTargetFileID);
4221
4222         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4223                       AFS_TRACE_LEVEL_VERBOSE,
4224                       "AFSBuildMountPointTarget Acquiring RDR VolumeTreeLock lock %08lX EXCL %08lX\n",
4225                       &pDevExt->Specific.RDR.VolumeTreeLock,
4226                       PsGetCurrentThread());
4227
4228         AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4229                           TRUE);
4230
4231         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4232                       AFS_TRACE_LEVEL_VERBOSE_2,
4233                       "AFSBuildMountPointTarget Locating volume for target %I64X\n",
4234                       ullIndex);
4235
4236         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4237                                        ullIndex,
4238                                        (AFSBTreeEntry **)&pVolumeCB);
4239
4240         //
4241         // We can be processing a request for a target that is on a volume
4242         // we have never seen before.
4243         //
4244
4245         if( pVolumeCB == NULL)
4246         {
4247
4248             //
4249             // Locking is held correctly in init routine
4250             //
4251
4252             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4253
4254             //
4255             // Go init the root of the volume
4256             //
4257
4258             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4259                           AFS_TRACE_LEVEL_VERBOSE_2,
4260                           "AFSBuildMountPointTarget Initializing root for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4261                           &DirectoryCB->NameInformation.FileName,
4262                           DirectoryCB->ObjectInformation->FileId.Cell,
4263                           DirectoryCB->ObjectInformation->FileId.Volume,
4264                           DirectoryCB->ObjectInformation->FileId.Vnode,
4265                           DirectoryCB->ObjectInformation->FileId.Unique);
4266
4267             ntStatus = AFSInitVolume( AuthGroup,
4268                                       &stTargetFileID,
4269                                       &pVolumeCB);
4270
4271             if( !NT_SUCCESS( ntStatus))
4272             {
4273
4274                 try_return( ntStatus);
4275             }
4276
4277             //
4278             // pVolumeCB->VolumeLock held exclusive and
4279             // pVolumeCB->VolumeReferenceCount has been incremented
4280             // pVolumeCB->RootFcb == NULL
4281             //
4282
4283             bReleaseVolumeLock = TRUE;
4284         }
4285         else
4286         {
4287
4288             //
4289             // AFSInitVolume returns with a VolumeReferenceCount
4290             // obtain one to match
4291             //
4292
4293             lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
4294
4295             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4296                           AFS_TRACE_LEVEL_VERBOSE,
4297                           "AFSBuildMountPointTarget Increment count on volume %08lX Cnt %d\n",
4298                           pVolumeCB,
4299                           lCount);
4300
4301             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4302         }
4303
4304         if( pVolumeCB->RootFcb == NULL)
4305         {
4306
4307             if ( bReleaseVolumeLock == FALSE)
4308             {
4309
4310                 AFSAcquireExcl( pVolumeCB->VolumeLock,
4311                                 TRUE);
4312
4313                 bReleaseVolumeLock = TRUE;
4314             }
4315
4316             //
4317             // Initialize the root fcb for this volume
4318             //
4319
4320             ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4321                                        pVolumeCB);
4322
4323             if( !NT_SUCCESS( ntStatus))
4324             {
4325
4326                 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
4327
4328                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4329                               AFS_TRACE_LEVEL_VERBOSE,
4330                               "AFSBuildMountPoint Decrement count on volume %08lX Cnt %d\n",
4331                               pVolumeCB,
4332                               lCount);
4333
4334                 AFSReleaseResource( pVolumeCB->VolumeLock);
4335
4336                 try_return( ntStatus);
4337             }
4338
4339             //
4340             // Drop the lock acquired above
4341             //
4342
4343             AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4344         }
4345
4346         if ( bReleaseVolumeLock == TRUE)
4347         {
4348
4349             AFSReleaseResource( pVolumeCB->VolumeLock);
4350         }
4351
4352         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4353                       AFS_TRACE_LEVEL_VERBOSE_2,
4354                       "AFSBuildMountPointTarget Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4355                       &pVolumeCB->DirectoryCB->NameInformation.FileName,
4356                       pVolumeCB->ObjectInformation.FileId.Cell,
4357                       pVolumeCB->ObjectInformation.FileId.Volume,
4358                       pVolumeCB->ObjectInformation.FileId.Vnode,
4359                       pVolumeCB->ObjectInformation.FileId.Unique);
4360
4361         *TargetVolumeCB = pVolumeCB;
4362
4363 try_exit:
4364
4365         if( pDirEntry)
4366         {
4367
4368             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
4369         }
4370     }
4371
4372     return ntStatus;
4373 }
4374
4375 NTSTATUS
4376 AFSBuildRootVolume( IN GUID *AuthGroup,
4377                     IN AFSFileID *FileId,
4378                     OUT AFSVolumeCB **TargetVolumeCB)
4379 {
4380
4381     NTSTATUS ntStatus = STATUS_SUCCESS;
4382     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4383     AFSDirectoryCB *pDirNode = NULL;
4384     UNICODE_STRING uniDirName, uniTargetName;
4385     ULONGLONG       ullIndex = 0;
4386     AFSVolumeCB *pVolumeCB = NULL;
4387     LONG lCount;
4388     BOOLEAN bReleaseVolumeLock = FALSE;
4389
4390     __Enter
4391     {
4392
4393         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4394                       AFS_TRACE_LEVEL_VERBOSE_2,
4395                       "AFSBuildRootVolume Building target volume for FID %08lX-%08lX-%08lX-%08lX\n",
4396                       FileId->Cell,
4397                       FileId->Volume,
4398                       FileId->Vnode,
4399                       FileId->Unique);
4400
4401         ullIndex = AFSCreateHighIndex( FileId);
4402
4403         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4404                       AFS_TRACE_LEVEL_VERBOSE,
4405                       "AFSBuildRootVolume Acquiring RDR VolumeTreeLock lock %08lX EXCL %08lX\n",
4406                       &pDevExt->Specific.RDR.VolumeTreeLock,
4407                       PsGetCurrentThread());
4408
4409         AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4410                           TRUE);
4411
4412         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4413                       AFS_TRACE_LEVEL_VERBOSE_2,
4414                       "AFSBuildRootVolume Locating volume for target %I64X\n",
4415                       ullIndex);
4416
4417         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4418                                        ullIndex,
4419                                        (AFSBTreeEntry **)&pVolumeCB);
4420
4421         //
4422         // We can be processing a request for a target that is on a volume
4423         // we have never seen before.
4424         //
4425
4426         if( pVolumeCB == NULL)
4427         {
4428
4429             //
4430             // Locking is held correctly in init routine
4431             //
4432
4433             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4434
4435             //
4436             // Go init the root of the volume
4437             //
4438
4439             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4440                          AFS_TRACE_LEVEL_VERBOSE_2,
4441                           "AFSBuildRootVolume Initializing root for FID %08lX-%08lX-%08lX-%08lX\n",
4442                           FileId->Cell,
4443                           FileId->Volume,
4444                           FileId->Vnode,
4445                           FileId->Unique);
4446
4447             ntStatus = AFSInitVolume( AuthGroup,
4448                                       FileId,
4449                                       &pVolumeCB);
4450
4451             if( !NT_SUCCESS( ntStatus))
4452             {
4453
4454                 try_return( ntStatus);
4455             }
4456
4457             //
4458             // pVolumeCB->VolumeLock is held exclusive
4459             // pVolumeCB->VolumeReferenceCount has been incremented
4460             // pVolumeCB->RootFcb == NULL
4461             //
4462
4463             bReleaseVolumeLock = TRUE;
4464         }
4465         else
4466         {
4467
4468             //
4469             // AFSInitVolume returns with a VolumeReferenceCount
4470             // obtain one to match
4471             //
4472
4473             lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
4474
4475             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4476                           AFS_TRACE_LEVEL_VERBOSE,
4477                           "AFSBuildRootVolume Increment count on volume %08lX Cnt %d\n",
4478                           pVolumeCB,
4479                           lCount);
4480
4481             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4482         }
4483
4484
4485         if( pVolumeCB->RootFcb == NULL)
4486         {
4487
4488             if ( bReleaseVolumeLock == FALSE)
4489             {
4490
4491                 AFSAcquireExcl( pVolumeCB->VolumeLock,
4492                                 TRUE);
4493
4494                 bReleaseVolumeLock = TRUE;
4495             }
4496
4497             //
4498             // Initialize the root fcb for this volume
4499             //
4500
4501             ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4502                                        pVolumeCB);
4503
4504             if( !NT_SUCCESS( ntStatus))
4505             {
4506
4507                 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
4508
4509                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4510                               AFS_TRACE_LEVEL_VERBOSE,
4511                               "AFSBuildRootVolume Decrement count on volume %08lX Cnt %d\n",
4512                               pVolumeCB,
4513                               lCount);
4514
4515                 AFSReleaseResource( pVolumeCB->VolumeLock);
4516
4517                 try_return( ntStatus);
4518             }
4519
4520             //
4521             // Drop the lock acquired above
4522             //
4523
4524             AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4525         }
4526
4527         if ( bReleaseVolumeLock == TRUE)
4528         {
4529
4530             AFSReleaseResource( pVolumeCB->VolumeLock);
4531         }
4532
4533         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4534                       AFS_TRACE_LEVEL_VERBOSE_2,
4535                       "AFSBuildRootVolume Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4536                       &pVolumeCB->DirectoryCB->NameInformation.FileName,
4537                       pVolumeCB->ObjectInformation.FileId.Cell,
4538                       pVolumeCB->ObjectInformation.FileId.Volume,
4539                       pVolumeCB->ObjectInformation.FileId.Vnode,
4540                       pVolumeCB->ObjectInformation.FileId.Unique);
4541
4542         *TargetVolumeCB = pVolumeCB;
4543
4544 try_exit:
4545
4546         NOTHING;
4547     }
4548
4549     return ntStatus;
4550 }
4551
4552 NTSTATUS
4553 AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
4554                    IN PFILE_OBJECT FileObject,
4555                    IN UNICODE_STRING *RemainingPath,
4556                    IN GUID *AuthGroup)
4557 {
4558
4559     NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
4560     UNICODE_STRING uniReparseName;
4561     UNICODE_STRING uniMUPDeviceName;
4562     AFSDirEnumEntry *pDirEntry = NULL;
4563
4564     __Enter
4565     {
4566
4567         //
4568         // Build up the name to reparse
4569         //
4570
4571         RtlInitUnicodeString( &uniMUPDeviceName,
4572                               L"\\Device\\MUP");
4573
4574         uniReparseName.Length = 0;
4575         uniReparseName.Buffer = NULL;
4576
4577         //
4578         // Be sure we have a target name
4579         //
4580
4581         if( DirEntry->NameInformation.TargetName.Length == 0)
4582         {
4583
4584             ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
4585                                               AuthGroup,
4586                                               FALSE,
4587                                               &pDirEntry);
4588
4589             if( !NT_SUCCESS( ntStatus) ||
4590                 pDirEntry->TargetNameLength == 0)
4591             {
4592
4593                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4594                               AFS_TRACE_LEVEL_ERROR,
4595                               "AFSProcessDFSLink EvaluateTargetByID failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4596                               &DirEntry->NameInformation.FileName,
4597                               DirEntry->ObjectInformation->FileId.Cell,
4598                               DirEntry->ObjectInformation->FileId.Volume,
4599                               DirEntry->ObjectInformation->FileId.Vnode,
4600                               DirEntry->ObjectInformation->FileId.Unique,
4601                               ntStatus);
4602
4603                 if( NT_SUCCESS( ntStatus))
4604                 {
4605
4606                     ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
4607                 }
4608
4609                 try_return( ntStatus);
4610             }
4611
4612             //
4613             // Update the target name
4614             //
4615
4616             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
4617                             TRUE);
4618
4619             ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
4620                                             &DirEntry->Flags,
4621                                             (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4622                                             (USHORT)pDirEntry->TargetNameLength);
4623
4624             if( !NT_SUCCESS( ntStatus))
4625             {
4626
4627                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4628                               AFS_TRACE_LEVEL_ERROR,
4629                               "AFSProcessDFSLink UpdateTargetName failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4630                               &DirEntry->NameInformation.FileName,
4631                               DirEntry->ObjectInformation->FileId.Cell,
4632                               DirEntry->ObjectInformation->FileId.Volume,
4633                               DirEntry->ObjectInformation->FileId.Vnode,
4634                               DirEntry->ObjectInformation->FileId.Unique,
4635                               ntStatus);
4636
4637                 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4638
4639                 try_return( ntStatus);
4640             }
4641
4642             AFSConvertToShared( &DirEntry->NonPaged->Lock);
4643         }
4644         else
4645         {
4646             AFSAcquireShared( &DirEntry->NonPaged->Lock,
4647                               TRUE);
4648         }
4649
4650         uniReparseName.MaximumLength = uniMUPDeviceName.Length +
4651                                                    sizeof( WCHAR) +
4652                                                    DirEntry->NameInformation.TargetName.Length +
4653                                                    sizeof( WCHAR);
4654
4655         if( RemainingPath != NULL &&
4656             RemainingPath->Length > 0)
4657         {
4658
4659             uniReparseName.MaximumLength += RemainingPath->Length;
4660         }
4661
4662         //
4663         // Allocate the reparse buffer
4664         //
4665
4666         uniReparseName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4667                                                                    uniReparseName.MaximumLength,
4668                                                                    AFS_REPARSE_NAME_TAG);
4669
4670         if( uniReparseName.Buffer == NULL)
4671         {
4672
4673             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4674                           AFS_TRACE_LEVEL_ERROR,
4675                           "AFSProcessDFSLink uniReparseName.Buffer == NULL Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4676                           &DirEntry->NameInformation.FileName,
4677                           DirEntry->ObjectInformation->FileId.Cell,
4678                           DirEntry->ObjectInformation->FileId.Volume,
4679                           DirEntry->ObjectInformation->FileId.Vnode,
4680                           DirEntry->ObjectInformation->FileId.Unique,
4681                           STATUS_INSUFFICIENT_RESOURCES);
4682
4683             AFSReleaseResource( &DirEntry->NonPaged->Lock);
4684
4685             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4686         }
4687
4688         //
4689         // Start building the name
4690         //
4691
4692         RtlCopyMemory( uniReparseName.Buffer,
4693                        uniMUPDeviceName.Buffer,
4694                        uniMUPDeviceName.Length);
4695
4696         uniReparseName.Length = uniMUPDeviceName.Length;
4697
4698         if( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\')
4699         {
4700
4701             uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
4702
4703             uniReparseName.Length += sizeof( WCHAR);
4704         }
4705
4706         RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
4707                        DirEntry->NameInformation.TargetName.Buffer,
4708                        DirEntry->NameInformation.TargetName.Length);
4709
4710         uniReparseName.Length += DirEntry->NameInformation.TargetName.Length;
4711
4712         AFSReleaseResource( &DirEntry->NonPaged->Lock);
4713
4714         if( RemainingPath != NULL &&
4715             RemainingPath->Length > 0)
4716         {
4717
4718             if( uniReparseName.Buffer[ (uniReparseName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
4719                 RemainingPath->Buffer[ 0] != L'\\')
4720             {
4721
4722                 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
4723
4724                 uniReparseName.Length += sizeof( WCHAR);
4725             }
4726
4727             RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
4728                            RemainingPath->Buffer,
4729                            RemainingPath->Length);
4730
4731             uniReparseName.Length += RemainingPath->Length;
4732         }
4733
4734         //
4735         // Update the name in the file object
4736         //
4737
4738         if( FileObject->FileName.Buffer != NULL)
4739         {
4740
4741             AFSExFreePoolWithTag( FileObject->FileName.Buffer, 0);
4742         }
4743
4744         FileObject->FileName = uniReparseName;
4745
4746         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4747                       AFS_TRACE_LEVEL_VERBOSE,
4748                       "AFSProcessDFSLink Reparsing access to Fcb %wZ FID %08lX-%08lX-%08lX-%08lX to %wZ\n",
4749                       &DirEntry->NameInformation.FileName,
4750                       DirEntry->ObjectInformation->FileId.Cell,
4751                       DirEntry->ObjectInformation->FileId.Volume,
4752                       DirEntry->ObjectInformation->FileId.Vnode,
4753                       DirEntry->ObjectInformation->FileId.Unique,
4754                       &uniReparseName);
4755
4756         //
4757         // Return status reparse ...
4758         //
4759
4760         ntStatus = STATUS_REPARSE;
4761
4762 try_exit:
4763
4764         if ( pDirEntry)
4765         {
4766
4767             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
4768         }
4769     }
4770
4771     return ntStatus;
4772 }