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