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