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