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