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