Windows: AFSDeleteDirEntry deleted flag shuffle
[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                 }
1952
1953                 ASSERT( pParentObjectInfo != NULL);
1954
1955                 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1956                                 TRUE);
1957
1958                 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1959                                 TRUE);
1960
1961                 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1962
1963                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1964                               AFS_TRACE_LEVEL_VERBOSE,
1965                               "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1966                               &pDirEntry->NameInformation.FileName,
1967                               pDirEntry,
1968                               NULL,
1969                               lCount));
1970
1971                 ASSERT( lCount >= 0);
1972
1973                 if( lCount == 0 &&
1974                     pDirEntry->NameArrayReferenceCount <= 0)
1975                 {
1976
1977                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1978                                   AFS_TRACE_LEVEL_VERBOSE,
1979                                   "AFSLocateNameEntry Deleting dir entry %p (%p) for %wZ\n",
1980                                   pDirEntry,
1981                                   pCurrentObject,
1982                                   &pDirEntry->NameInformation.FileName));
1983
1984                     //
1985                     // Remove and delete the directory entry from the parent list
1986                     //
1987
1988                     AFSDeleteDirEntry( pParentObjectInfo,
1989                                        pDirEntry);
1990
1991                     AFSAcquireShared( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1992                                       TRUE);
1993
1994                     if( pCurrentObject->ObjectReferenceCount <= 0)
1995                     {
1996
1997                         if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
1998                         {
1999
2000                             AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2001                                           AFS_TRACE_LEVEL_VERBOSE,
2002                                           "AFSLocateNameEntry Removing object %p from volume tree\n",
2003                                           pCurrentObject));
2004
2005                             AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
2006                                                 &pCurrentObject->TreeEntry);
2007
2008                             ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
2009                         }
2010                     }
2011
2012                     AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
2013                 }
2014                 else
2015                 {
2016
2017                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2018                                   AFS_TRACE_LEVEL_VERBOSE,
2019                                   "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
2020                                   pDirEntry,
2021                                   &pDirEntry->NameInformation.FileName));
2022
2023                     SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
2024
2025                     AFSRemoveNameEntry( pParentObjectInfo,
2026                                         pDirEntry);
2027                 }
2028
2029                 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2030
2031                 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
2032
2033                 AFSReleaseObjectInfo( &pParentObjectInfo);
2034
2035                 //
2036                 // We deleted the dir entry so check if there is any remaining portion
2037                 // of the name to process.
2038                 //
2039
2040                 if( uniRemainingPath.Length > 0)
2041                 {
2042
2043                     ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
2044
2045                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2046                                   AFS_TRACE_LEVEL_VERBOSE,
2047                                   "AFSLocateNameEntry (FO: %p) Returning path not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2048                                   FileObject,
2049                                   &uniComponentName,
2050                                   pCurrentObject->FileId.Cell,
2051                                   pCurrentObject->FileId.Volume,
2052                                   pCurrentObject->FileId.Vnode,
2053                                   pCurrentObject->FileId.Unique));
2054                 }
2055                 else
2056                 {
2057
2058                     ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
2059
2060                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2061                                   AFS_TRACE_LEVEL_VERBOSE,
2062                                   "AFSLocateNameEntry (FO: %p) Returning name not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2063                                   FileObject,
2064                                   &uniComponentName,
2065                                   pCurrentObject->FileId.Cell,
2066                                   pCurrentObject->FileId.Volume,
2067                                   pCurrentObject->FileId.Vnode,
2068                                   pCurrentObject->FileId.Unique));
2069
2070                     //
2071                     // Pass back the directory entries
2072                     //
2073
2074                     *OutParentDirectoryCB = pParentDirEntry;
2075
2076                     pParentDirEntry = NULL;
2077
2078                     *OutDirectoryCB = NULL;
2079
2080                     *OutVolumeCB = pCurrentVolume;
2081
2082                     *OutVolumeReferenceReason = VolumeReferenceReason;
2083
2084                     bReleaseCurrentVolume = FALSE;
2085
2086                     if( ComponentName != NULL)
2087                     {
2088
2089                         *ComponentName = uniComponentName;
2090                     }
2091
2092                     *RootPathName = uniFullPathName;
2093                 }
2094             }
2095
2096             if( ntStatus != STATUS_SUCCESS)
2097             {
2098
2099                 try_return( ntStatus);
2100             }
2101
2102             //
2103             // If we ended up substituting a name in the component then update
2104             // the full path and update the pointers
2105             //
2106
2107             if( bSubstituteName)
2108             {
2109
2110                 BOOLEAN bRelativeOpen = FALSE;
2111
2112                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2113                               AFS_TRACE_LEVEL_VERBOSE_2,
2114                               "AFSLocateNameEntry (FO: %p) Substituting %wZ into %wZ Index %08lX\n",
2115                               FileObject,
2116                               &uniSearchName,
2117                               &uniComponentName,
2118                               ulSubstituteIndex));
2119
2120                 if( FileObject != NULL &&
2121                     FileObject->RelatedFileObject != NULL)
2122                 {
2123
2124                     bRelativeOpen = TRUE;
2125                 }
2126
2127                 //
2128                 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
2129                 // and free the prior Buffer contents but only if the fourth
2130                 // parameter is TRUE.
2131                 //
2132
2133                 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
2134                                                     &uniComponentName,
2135                                                     &uniSearchName,
2136                                                     &uniRemainingPath,
2137                                                     bRelativeOpen ||
2138                                                     bAllocatedSymLinkBuffer ||
2139                                                     bSubstitutedName);
2140
2141                 if( !NT_SUCCESS( ntStatus))
2142                 {
2143
2144                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2145                                   AFS_TRACE_LEVEL_ERROR,
2146                                   "AFSLocateNameEntry (FO: %p) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
2147                                   FileObject,
2148                                   &uniSearchName,
2149                                   &uniComponentName,
2150                                   ulSubstituteIndex,
2151                                   ntStatus));
2152
2153                     try_return( ntStatus);
2154                 }
2155
2156                 //
2157                 // We have substituted a name into the buffer so if we do this again for this
2158                 // path, we need to free up the buffer we allocated.
2159                 //
2160
2161                 bSubstitutedName = TRUE;
2162             }
2163
2164             //
2165             // Update the search parameters
2166             //
2167
2168             uniPathName = uniRemainingPath;
2169
2170             //
2171             // Check if the is a SymLink entry but has no Target FileID or Name. In this
2172             // case it might be a DFS Link so let's go and evaluate it to be sure
2173             //
2174
2175             if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
2176                 ( pCurrentObject->TargetFileId.Vnode == 0 ||
2177                   pDirEntry->NameInformation.TargetName.Length == 0))
2178             {
2179
2180                 ntStatus = AFSValidateSymLink( AuthGroup,
2181                                                pDirEntry);
2182
2183                 if( !NT_SUCCESS( ntStatus))
2184                 {
2185
2186                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2187                                   AFS_TRACE_LEVEL_ERROR,
2188                                   "AFSLocateNameEntry (FO: %p) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2189                                   FileObject,
2190                                   &pDirEntry->NameInformation.FileName,
2191                                   pCurrentObject->FileId.Cell,
2192                                   pCurrentObject->FileId.Volume,
2193                                   pCurrentObject->FileId.Vnode,
2194                                   pCurrentObject->FileId.Unique,
2195                                   ntStatus));
2196
2197                     try_return( ntStatus);
2198                 }
2199             }
2200
2201             //
2202             // Update the name array
2203             //
2204
2205             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2206                           AFS_TRACE_LEVEL_VERBOSE,
2207                           "AFSLocateNameEntry (FO: %p) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2208                           FileObject,
2209                           &pDirEntry->NameInformation.FileName,
2210                           pCurrentObject->FileId.Cell,
2211                           pCurrentObject->FileId.Volume,
2212                           pCurrentObject->FileId.Vnode,
2213                           pCurrentObject->FileId.Unique));
2214
2215             ntStatus = AFSInsertNextElement( pNameArray,
2216                                              pDirEntry);
2217
2218             if( !NT_SUCCESS( ntStatus))
2219             {
2220
2221                 try_return( ntStatus);
2222             }
2223         }       // while (TRUE)
2224
2225 try_exit:
2226
2227         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2228                       AFS_TRACE_LEVEL_VERBOSE,
2229                       "AFSLocateNameEntry (FO: %p) Completed processing %wZ Status %08lX\n",
2230                       FileObject,
2231                       RootPathName,
2232                       ntStatus));
2233
2234         if( ( !NT_SUCCESS( ntStatus) &&
2235               ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
2236             ntStatus == STATUS_REPARSE)
2237         {
2238             if( RootPathName->Buffer != uniFullPathName.Buffer)
2239             {
2240
2241                 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
2242             }
2243         }
2244         else
2245         {
2246
2247             if( *OutParentDirectoryCB != NULL)
2248             {
2249
2250                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2251                               AFS_TRACE_LEVEL_VERBOSE,
2252                               "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
2253                               &(*OutParentDirectoryCB)->NameInformation.FileName,
2254                               *OutParentDirectoryCB,
2255                               NULL,
2256                               (*OutParentDirectoryCB)->DirOpenReferenceCount));
2257             }
2258
2259             if( *OutDirectoryCB != NULL)
2260             {
2261
2262                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2263                               AFS_TRACE_LEVEL_VERBOSE,
2264                               "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
2265                               &(*OutDirectoryCB)->NameInformation.FileName,
2266                               *OutDirectoryCB,
2267                               NULL,
2268                               (*OutDirectoryCB)->DirOpenReferenceCount));
2269             }
2270         }
2271
2272         if( pDirEntry != NULL)
2273         {
2274
2275             lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
2276
2277             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2278                           AFS_TRACE_LEVEL_VERBOSE,
2279                           "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
2280                           &pDirEntry->NameInformation.FileName,
2281                           pDirEntry,
2282                           NULL,
2283                           lCount));
2284
2285             ASSERT( lCount >= 0);
2286         }
2287
2288         if( pParentDirEntry != NULL)
2289         {
2290
2291             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
2292
2293             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2294                           AFS_TRACE_LEVEL_VERBOSE,
2295                           "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
2296                           &pParentDirEntry->NameInformation.FileName,
2297                           pParentDirEntry,
2298                           NULL,
2299                           lCount));
2300
2301             ASSERT( lCount >= 0);
2302         }
2303
2304         if( bReleaseCurrentVolume)
2305         {
2306
2307             ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
2308
2309             lCount = AFSVolumeDecrement( pCurrentVolume,
2310                                          VolumeReferenceReason);
2311
2312             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2313                           AFS_TRACE_LEVEL_VERBOSE,
2314                           "AFSLocateNameEntry Decrement7 count on volume %p Reason %u Cnt %d\n",
2315                           pCurrentVolume,
2316                           VolumeReferenceReason,
2317                           lCount));
2318
2319             bReleaseCurrentVolume = FALSE;
2320         }
2321
2322         if( bSubstituteName &&
2323             uniSearchName.Buffer != NULL)
2324         {
2325
2326             AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
2327         }
2328     }
2329
2330     return ntStatus;
2331 }
2332
2333 NTSTATUS
2334 AFSCreateDirEntry( IN GUID            *AuthGroup,
2335                    IN AFSObjectInfoCB *ParentObjectInfo,
2336                    IN AFSDirectoryCB *ParentDirCB,
2337                    IN PUNICODE_STRING FileName,
2338                    IN PUNICODE_STRING ComponentName,
2339                    IN ULONG Attributes,
2340                    IN OUT AFSDirectoryCB **DirEntry)
2341 {
2342
2343     UNREFERENCED_PARAMETER(FileName);
2344     NTSTATUS ntStatus = STATUS_SUCCESS;
2345     AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
2346     LARGE_INTEGER liFileSize = {0,0};
2347     LONG lCount;
2348
2349     __Enter
2350     {
2351
2352         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2353                       AFS_TRACE_LEVEL_VERBOSE_2,
2354                       "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
2355                       &ParentDirCB->NameInformation.FileName,
2356                       ParentObjectInfo->FileId.Cell,
2357                       ParentObjectInfo->FileId.Volume,
2358                       ParentObjectInfo->FileId.Vnode,
2359                       ParentObjectInfo->FileId.Unique,
2360                       ComponentName,
2361                       Attributes));
2362
2363         //
2364         // OK, before inserting the node into the parent tree, issue
2365         // the request to the service for node creation
2366         // We will need to drop the lock on the parent node since the create
2367         // could cause a callback into the file system to invalidate it's cache
2368         //
2369
2370         ntStatus = AFSNotifyFileCreate( AuthGroup,
2371                                         ParentObjectInfo,
2372                                         &liFileSize,
2373                                         Attributes,
2374                                         ComponentName,
2375                                         &pDirNode);
2376
2377         //
2378         // If the returned status is STATUS_REPARSE then the entry exists
2379         // and we raced, get out.
2380
2381         if( ntStatus == STATUS_REPARSE)
2382         {
2383
2384             *DirEntry = pDirNode;
2385
2386             try_return( ntStatus = STATUS_SUCCESS);
2387         }
2388
2389         if( !NT_SUCCESS( ntStatus))
2390         {
2391
2392             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2393                           AFS_TRACE_LEVEL_ERROR,
2394                           "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
2395                           &ParentDirCB->NameInformation.FileName,
2396                           ParentObjectInfo->FileId.Cell,
2397                           ParentObjectInfo->FileId.Volume,
2398                           ParentObjectInfo->FileId.Vnode,
2399                           ParentObjectInfo->FileId.Unique,
2400                           ComponentName,
2401                           Attributes,
2402                           ntStatus));
2403
2404             try_return( ntStatus);
2405         }
2406
2407         //
2408         // If AFSNotifyFileCreate returns pDirNode != NULL, then its
2409         // DirOpenReferenceCount is held.
2410         //
2411
2412         AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2413                         TRUE);
2414
2415         //
2416         // Before attempting to insert the new entry, check if we need to validate the parent
2417         //
2418
2419         if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2420         {
2421
2422             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2423                           AFS_TRACE_LEVEL_VERBOSE,
2424                           "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2425                           &ParentDirCB->NameInformation.FileName,
2426                           ParentObjectInfo->FileId.Cell,
2427                           ParentObjectInfo->FileId.Volume,
2428                           ParentObjectInfo->FileId.Vnode,
2429                           ParentObjectInfo->FileId.Unique));
2430
2431             ntStatus = AFSVerifyEntry( AuthGroup,
2432                                        ParentDirCB);
2433
2434             if( !NT_SUCCESS( ntStatus))
2435             {
2436
2437                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2438                               AFS_TRACE_LEVEL_ERROR,
2439                               "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2440                               &ParentDirCB->NameInformation.FileName,
2441                               ParentObjectInfo->FileId.Cell,
2442                               ParentObjectInfo->FileId.Volume,
2443                               ParentObjectInfo->FileId.Vnode,
2444                               ParentObjectInfo->FileId.Unique,
2445                               ntStatus));
2446
2447                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2448
2449                 try_return( ntStatus);
2450             }
2451         }
2452
2453         //
2454         // Check for the entry in the event we raced with some other thread
2455         //
2456
2457         AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2458                                         (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2459                                         &pExistingDirNode);
2460
2461         if( pExistingDirNode != NULL)
2462         {
2463             if (AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2464                                &pExistingDirNode->ObjectInformation->FileId))
2465             {
2466
2467                 if ( pExistingDirNode != pDirNode)
2468                 {
2469
2470                     lCount = InterlockedDecrement( &pDirNode->DirOpenReferenceCount);
2471
2472                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2473                                   AFS_TRACE_LEVEL_VERBOSE,
2474                                   "AFSCreateDirEntry Decrement count on %wZ DE %p Cnt %d\n",
2475                                   &pDirNode->NameInformation.FileName,
2476                                   pDirNode,
2477                                   lCount));
2478
2479                     AFSDeleteDirEntry( ParentObjectInfo,
2480                                        pDirNode);
2481
2482                     lCount = InterlockedIncrement( &pExistingDirNode->DirOpenReferenceCount);
2483
2484                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2485                                   AFS_TRACE_LEVEL_VERBOSE,
2486                                   "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2487                                   &pExistingDirNode->NameInformation.FileName,
2488                                   pExistingDirNode,
2489                                   lCount));
2490
2491                     *DirEntry = pExistingDirNode;
2492                 }
2493
2494                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2495
2496                 try_return( ntStatus = STATUS_SUCCESS);
2497             }
2498             else
2499             {
2500
2501                 //
2502                 // Need to tear down this entry and rebuild it below
2503                 //
2504
2505                 if( pExistingDirNode->DirOpenReferenceCount <= 0 &&
2506                     pExistingDirNode->NameArrayReferenceCount <= 0)
2507                 {
2508
2509                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2510                                   AFS_TRACE_LEVEL_VERBOSE,
2511                                   "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2512                                   pExistingDirNode,
2513                                   &pExistingDirNode->NameInformation.FileName,
2514                                   pExistingDirNode->ObjectInformation->FileId.Cell,
2515                                   pExistingDirNode->ObjectInformation->FileId.Volume,
2516                                   pExistingDirNode->ObjectInformation->FileId.Vnode,
2517                                   pExistingDirNode->ObjectInformation->FileId.Unique,
2518                                   pDirNode->ObjectInformation->FileId.Cell,
2519                                   pDirNode->ObjectInformation->FileId.Volume,
2520                                   pDirNode->ObjectInformation->FileId.Vnode,
2521                                   pDirNode->ObjectInformation->FileId.Unique));
2522
2523                     AFSDeleteDirEntry( ParentObjectInfo,
2524                                        pExistingDirNode);
2525                 }
2526                 else
2527                 {
2528
2529                     SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2530
2531                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2532                                   AFS_TRACE_LEVEL_VERBOSE,
2533                                   "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2534                                   pExistingDirNode,
2535                                   &pExistingDirNode->NameInformation.FileName,
2536                                   pExistingDirNode->ObjectInformation->FileId.Cell,
2537                                   pExistingDirNode->ObjectInformation->FileId.Volume,
2538                                   pExistingDirNode->ObjectInformation->FileId.Vnode,
2539                                   pExistingDirNode->ObjectInformation->FileId.Unique,
2540                                   pDirNode->ObjectInformation->FileId.Cell,
2541                                   pDirNode->ObjectInformation->FileId.Volume,
2542                                   pDirNode->ObjectInformation->FileId.Vnode,
2543                                   pDirNode->ObjectInformation->FileId.Unique));
2544
2545                     AFSRemoveNameEntry( ParentObjectInfo,
2546                                         pExistingDirNode);
2547                 }
2548             }
2549         }
2550
2551         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2552                       AFS_TRACE_LEVEL_VERBOSE_2,
2553                       "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2554                       &ParentDirCB->NameInformation.FileName,
2555                       ParentObjectInfo->FileId.Cell,
2556                       ParentObjectInfo->FileId.Volume,
2557                       ParentObjectInfo->FileId.Vnode,
2558                       ParentObjectInfo->FileId.Unique,
2559                       ComponentName));
2560
2561         //
2562         // Insert the directory node
2563         //
2564
2565         AFSInsertDirectoryNode( ParentObjectInfo,
2566                                 pDirNode,
2567                                 TRUE);
2568
2569         //
2570         // Pass back the dir entry
2571         //
2572
2573         *DirEntry = pDirNode;
2574
2575         AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2576
2577 try_exit:
2578
2579         NOTHING;
2580     }
2581
2582     return ntStatus;
2583 }
2584
2585 void
2586 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2587                         IN AFSDirectoryCB *DirEntry,
2588                         IN BOOLEAN InsertInEnumList)
2589 {
2590
2591     LONG lCount;
2592
2593     __Enter
2594     {
2595
2596         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2597
2598         //
2599         // Insert the node into the directory node tree
2600         //
2601
2602         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2603                       AFS_TRACE_LEVEL_VERBOSE,
2604                       "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2605                       DirEntry,
2606                       &DirEntry->NameInformation.FileName));
2607
2608         ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2609
2610         if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2611         {
2612
2613             ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2614
2615             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2616                           AFS_TRACE_LEVEL_VERBOSE,
2617                           "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2618                           DirEntry,
2619                           &DirEntry->NameInformation.FileName));
2620         }
2621         else
2622         {
2623
2624             AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2625                                             DirEntry);
2626
2627             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2628                           AFS_TRACE_LEVEL_VERBOSE,
2629                           "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2630                           DirEntry,
2631                           &DirEntry->NameInformation.FileName));
2632         }
2633
2634         if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2635         {
2636
2637             ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2638
2639             SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2640
2641             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2642                           AFS_TRACE_LEVEL_VERBOSE,
2643                           "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2644                           DirEntry,
2645                           &DirEntry->NameInformation.FileName));
2646         }
2647         else
2648         {
2649
2650             AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2651                                               DirEntry);
2652
2653             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2654                           AFS_TRACE_LEVEL_VERBOSE,
2655                           "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2656                           DirEntry,
2657                           &DirEntry->NameInformation.FileName));
2658         }
2659
2660         //
2661         // Into the shortname tree
2662         //
2663
2664         if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2665         {
2666
2667             if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2668             {
2669
2670                 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2671
2672                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2673                               AFS_TRACE_LEVEL_VERBOSE,
2674                               "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2675                               DirEntry,
2676                               &DirEntry->NameInformation.FileName));
2677
2678                 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2679             }
2680             else
2681             {
2682
2683                 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2684                                                              DirEntry)))
2685                 {
2686                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2687                                   AFS_TRACE_LEVEL_VERBOSE,
2688                                   "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2689                                   DirEntry,
2690                                   &DirEntry->NameInformation.FileName));
2691                 }
2692                 else
2693                 {
2694                     SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2695
2696                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2697                                   AFS_TRACE_LEVEL_VERBOSE,
2698                                   "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2699                                   DirEntry,
2700                                   &DirEntry->NameInformation.FileName));
2701                 }
2702             }
2703         }
2704
2705         if( InsertInEnumList)
2706         {
2707
2708             //
2709             // And insert the node into the directory list
2710             //
2711
2712             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2713                           AFS_TRACE_LEVEL_VERBOSE,
2714                           "AFSInsertDirectoryNode Inserting entry %p %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2715                           DirEntry,
2716                           &DirEntry->NameInformation.FileName,
2717                           DirEntry->ObjectInformation->FileId.Cell,
2718                           DirEntry->ObjectInformation->FileId.Volume,
2719                           DirEntry->ObjectInformation->FileId.Vnode,
2720                           DirEntry->ObjectInformation->FileId.Unique));
2721
2722             if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2723             {
2724
2725                 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2726             }
2727             else
2728             {
2729
2730                 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2731
2732                 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2733             }
2734
2735             ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2736
2737             SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2738
2739             lCount = InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2740
2741             AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2742                           AFS_TRACE_LEVEL_VERBOSE,
2743                           "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2744                           &DirEntry->NameInformation.FileName,
2745                           lCount,
2746                           ParentObjectInfo->FileId.Cell,
2747                           ParentObjectInfo->FileId.Volume,
2748                           ParentObjectInfo->FileId.Vnode,
2749                           ParentObjectInfo->FileId.Unique));
2750         }
2751     }
2752
2753     return;
2754 }
2755
2756 void
2757 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2758                    IN AFSDirectoryCB *DirEntry)
2759 {
2760
2761     LONG lCount;
2762
2763     __Enter
2764     {
2765
2766         AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2767                       AFS_TRACE_LEVEL_VERBOSE,
2768                       "AFSDeleteDirEntry Deleting dir entry in parent %p Entry %p %wZ FID %08lX-%08lX-%08lX-%08lX RefCount %d\n",
2769                       ParentObjectInfo,
2770                       DirEntry,
2771                       &DirEntry->NameInformation.FileName,
2772                       DirEntry->ObjectInformation->FileId.Cell,
2773                       DirEntry->ObjectInformation->FileId.Volume,
2774                       DirEntry->ObjectInformation->FileId.Vnode,
2775                       DirEntry->ObjectInformation->FileId.Unique,
2776                       DirEntry->DirOpenReferenceCount));
2777
2778         ASSERT( DirEntry->DirOpenReferenceCount == 0);
2779
2780         AFSRemoveDirNodeFromParent( ParentObjectInfo,
2781                                     DirEntry,
2782                                     TRUE);
2783
2784         //
2785         // Free up the name buffer if it was reallocated
2786         //
2787
2788         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2789         {
2790
2791             AFSExFreePoolWithTag( DirEntry->NameInformation.FileName.Buffer, 0);
2792         }
2793
2794         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2795         {
2796
2797             AFSExFreePoolWithTag( DirEntry->NameInformation.TargetName.Buffer, 0);
2798         }
2799
2800         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
2801             DirEntry->ObjectInformation->Links == 0)
2802         {
2803
2804             SetFlag( DirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2805         }
2806
2807         //
2808         // Dereference the object for this dir entry
2809         //
2810
2811         lCount = AFSObjectInfoDecrement( DirEntry->ObjectInformation,
2812                                          AFS_OBJECT_REFERENCE_DIRENTRY);
2813
2814         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2815                       AFS_TRACE_LEVEL_VERBOSE,
2816                       "AFSDeleteDirEntry Decrement count on object %p Cnt %d\n",
2817                       DirEntry->ObjectInformation,
2818                       lCount));
2819
2820         ExDeleteResourceLite( &DirEntry->NonPaged->Lock);
2821
2822         AFSExFreePoolWithTag( DirEntry->NonPaged, AFS_DIR_ENTRY_NP_TAG);
2823
2824         //
2825         // Free up the dir entry
2826         //
2827
2828         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
2829                       AFS_TRACE_LEVEL_VERBOSE,
2830                       "AFSDeleteDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
2831                       DirEntry));
2832
2833         AFSExFreePoolWithTag( DirEntry, AFS_DIR_ENTRY_TAG);
2834     }
2835 }
2836
2837 NTSTATUS
2838 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2839                             IN AFSDirectoryCB *DirEntry,
2840                             IN BOOLEAN RemoveFromEnumList)
2841 {
2842
2843     NTSTATUS ntStatus = STATUS_SUCCESS;
2844     LONG lCount;
2845
2846     __Enter
2847     {
2848
2849
2850         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2851
2852         AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2853                       AFS_TRACE_LEVEL_VERBOSE,
2854                       "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %p\n",
2855                       DirEntry,
2856                       &DirEntry->NameInformation.FileName,
2857                       DirEntry->ObjectInformation->FileId.Cell,
2858                       DirEntry->ObjectInformation->FileId.Volume,
2859                       DirEntry->ObjectInformation->FileId.Vnode,
2860                       DirEntry->ObjectInformation->FileId.Unique,
2861                       ParentObjectInfo));
2862
2863         if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2864         {
2865
2866             AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2867                           AFS_TRACE_LEVEL_VERBOSE,
2868                           "AFSRemoveDirNodeFromParent Removing DirEntry %p name %wZ\n",
2869                           DirEntry,
2870                           &DirEntry->NameInformation.FileName));
2871
2872             AFSRemoveNameEntry( ParentObjectInfo,
2873                                 DirEntry);
2874         }
2875         else
2876         {
2877
2878             AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2879                           AFS_TRACE_LEVEL_VERBOSE,
2880                           "AFSRemoveDirNodeFromParent DE %p for %wZ NOT removing entry due to flag set\n",
2881                           DirEntry,
2882                           &DirEntry->NameInformation.FileName));
2883
2884         }
2885
2886         if( RemoveFromEnumList &&
2887             BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST))
2888         {
2889
2890             //
2891             // And remove the entry from the enumeration list
2892             //
2893
2894             if( DirEntry->ListEntry.fLink == NULL)
2895             {
2896
2897                 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = (AFSDirectoryCB *)DirEntry->ListEntry.bLink;
2898             }
2899             else
2900             {
2901
2902                 ((AFSDirectoryCB *)DirEntry->ListEntry.fLink)->ListEntry.bLink = DirEntry->ListEntry.bLink;
2903             }
2904
2905             if( DirEntry->ListEntry.bLink == NULL)
2906             {
2907
2908                 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = (AFSDirectoryCB *)DirEntry->ListEntry.fLink;
2909             }
2910             else
2911             {
2912
2913                 ((AFSDirectoryCB *)DirEntry->ListEntry.bLink)->ListEntry.fLink = DirEntry->ListEntry.fLink;
2914             }
2915
2916             ASSERT( ParentObjectInfo->Specific.Directory.DirectoryNodeCount > 0);
2917
2918             lCount = InterlockedDecrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2919
2920             ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2921
2922             AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2923                           AFS_TRACE_LEVEL_VERBOSE,
2924                           "AFSRemoveDirNodeFromParent Removing entry %wZ Dec Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2925                           &DirEntry->NameInformation.FileName,
2926                           lCount,
2927                           ParentObjectInfo->FileId.Cell,
2928                           ParentObjectInfo->FileId.Volume,
2929                           ParentObjectInfo->FileId.Vnode,
2930                           ParentObjectInfo->FileId.Unique));
2931
2932             DirEntry->ListEntry.fLink = NULL;
2933             DirEntry->ListEntry.bLink = NULL;
2934         }
2935     }
2936
2937     return ntStatus;
2938 }
2939
2940 NTSTATUS
2941 AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
2942                     IN OUT PUNICODE_STRING TargetFileName)
2943 {
2944
2945     NTSTATUS ntStatus = STATUS_SUCCESS;
2946     UNICODE_STRING uniFileName;
2947
2948     __Enter
2949     {
2950
2951         //
2952         // We will process backwards from the end of the name looking
2953         // for the first \ we encounter
2954         //
2955
2956         uniFileName.Length = FileName->Length;
2957         uniFileName.MaximumLength = FileName->MaximumLength;
2958
2959         uniFileName.Buffer = FileName->Buffer;
2960
2961         while( TRUE)
2962         {
2963
2964             if( uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
2965             {
2966
2967                 //
2968                 // Subtract one more character off of the filename if it is not the root
2969                 //
2970
2971                 if( uniFileName.Length > sizeof( WCHAR))
2972                 {
2973
2974                     uniFileName.Length -= sizeof( WCHAR);
2975                 }
2976
2977                 //
2978                 // Now build up the target name
2979                 //
2980
2981                 TargetFileName->Length = FileName->Length - uniFileName.Length;
2982
2983                 //
2984                 // If we are not on the root then fixup the name
2985                 //
2986
2987                 if( uniFileName.Length > sizeof( WCHAR))
2988                 {
2989
2990                     TargetFileName->Length -= sizeof( WCHAR);
2991
2992                     TargetFileName->Buffer = &uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) + 1];
2993                 }
2994                 else
2995                 {
2996
2997                     TargetFileName->Buffer = &uniFileName.Buffer[ uniFileName.Length/sizeof( WCHAR)];
2998                 }
2999
3000                 //
3001                 // Fixup the passed back filename length
3002                 //
3003
3004                 FileName->Length = uniFileName.Length;
3005
3006                 TargetFileName->MaximumLength = TargetFileName->Length;
3007
3008                 break;
3009             }
3010
3011             uniFileName.Length -= sizeof( WCHAR);
3012         }
3013     }
3014
3015     return ntStatus;
3016 }
3017
3018 NTSTATUS
3019 AFSParseName( IN PIRP Irp,
3020               IN GUID *AuthGroup,
3021               OUT PUNICODE_STRING FileName,
3022               OUT PUNICODE_STRING ParsedFileName,
3023               OUT PUNICODE_STRING RootFileName,
3024               OUT ULONG *ParseFlags,
3025               OUT AFSVolumeCB   **VolumeCB,
3026               OUT AFSDirectoryCB **ParentDirectoryCB,
3027               OUT AFSNameArrayHdr **NameArray)
3028 {
3029
3030     NTSTATUS            ntStatus = STATUS_SUCCESS;
3031     PIO_STACK_LOCATION  pIrpSp = IoGetCurrentIrpStackLocation( Irp);
3032     AFSDeviceExt       *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3033     UNICODE_STRING      uniFullName, uniComponentName, uniRemainingPath;
3034     ULONG               ulCRC = 0;
3035     AFSDirectoryCB     *pDirEntry = NULL;
3036     USHORT              usIndex = 0, usDriveIndex = 0;
3037     AFSCcb             *pRelatedCcb = NULL;
3038     AFSNameArrayHdr    *pNameArray = NULL, *pRelatedNameArray = NULL;
3039     USHORT              usComponentIndex = 0;
3040     USHORT              usComponentLength = 0;
3041     AFSVolumeCB        *pVolumeCB = NULL;
3042     AFSFcb             *pRelatedFcb = NULL;
3043     BOOLEAN             bReleaseTreeLock = FALSE;
3044     BOOLEAN             bIsAllShare = FALSE;
3045     LONG                lCount;
3046
3047     __Enter
3048     {
3049
3050         //
3051         // Indicate we are opening a root ...
3052         //
3053
3054         *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
3055
3056         *ParentDirectoryCB = NULL;
3057
3058         if( pIrpSp->FileObject->RelatedFileObject != NULL)
3059         {
3060
3061             pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
3062
3063             pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
3064
3065             pRelatedNameArray = pRelatedCcb->NameArray;
3066
3067             uniFullName = pIrpSp->FileObject->FileName;
3068
3069             ASSERT( pRelatedFcb != NULL);
3070
3071             //
3072             // No wild cards in the name
3073             //
3074
3075             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3076                           AFS_TRACE_LEVEL_VERBOSE_2,
3077                           "AFSParseName (%p) Relative open for %wZ FID %08lX-%08lX-%08lX-%08lX component %wZ\n",
3078                           Irp,
3079                           &pRelatedCcb->DirectoryCB->NameInformation.FileName,
3080                           pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Cell,
3081                           pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Volume,
3082                           pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
3083                           pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Unique,
3084                           &uniFullName));
3085
3086             if( FsRtlDoesNameContainWildCards( &uniFullName))
3087             {
3088
3089                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3090                               AFS_TRACE_LEVEL_ERROR,
3091                               "AFSParseName (%p) Component %wZ contains wild cards\n",
3092                               Irp,
3093                               &uniFullName));
3094
3095                 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3096             }
3097
3098             pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
3099
3100             pDirEntry = pRelatedCcb->DirectoryCB;
3101
3102             *FileName = pIrpSp->FileObject->FileName;
3103
3104             //
3105             // Grab the root node while checking state
3106             //
3107
3108             AFSAcquireShared( pVolumeCB->VolumeLock,
3109                               TRUE);
3110
3111             if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3112                 BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3113             {
3114
3115                 //
3116                 // The volume has been taken off line so fail the access
3117                 //
3118
3119                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3120                               AFS_TRACE_LEVEL_ERROR,
3121                               "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3122                               Irp,
3123                               pVolumeCB->ObjectInformation.FileId.Cell,
3124                               pVolumeCB->ObjectInformation.FileId.Volume));
3125
3126                 AFSReleaseResource( pVolumeCB->VolumeLock);
3127
3128                 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3129             }
3130
3131             if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3132             {
3133
3134                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3135                               AFS_TRACE_LEVEL_VERBOSE,
3136                               "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
3137                               Irp,
3138                               pVolumeCB->ObjectInformation.FileId.Cell,
3139                               pVolumeCB->ObjectInformation.FileId.Volume));
3140
3141                 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3142                                             pVolumeCB);
3143
3144                 if( !NT_SUCCESS( ntStatus))
3145                 {
3146
3147                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3148                                   AFS_TRACE_LEVEL_ERROR,
3149                                   "AFSParseName (%p) Failed verification of root Status %08lX\n",
3150                                   Irp,
3151                                   ntStatus));
3152
3153                     AFSReleaseResource( pVolumeCB->VolumeLock);
3154
3155                     try_return( ntStatus);
3156                 }
3157             }
3158
3159             AFSReleaseResource( pVolumeCB->VolumeLock);
3160
3161             if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
3162             {
3163
3164                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3165                               AFS_TRACE_LEVEL_VERBOSE,
3166                               "AFSParseName (%p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3167                               Irp,
3168                               &pDirEntry->NameInformation.FileName,
3169                               pDirEntry->ObjectInformation->FileId.Cell,
3170                               pDirEntry->ObjectInformation->FileId.Volume,
3171                               pDirEntry->ObjectInformation->FileId.Vnode,
3172                               pDirEntry->ObjectInformation->FileId.Unique));
3173
3174                 //
3175                 // Directory TreeLock should be exclusively held
3176                 //
3177
3178                 AFSAcquireExcl( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
3179                                 TRUE);
3180
3181                 ntStatus = AFSVerifyEntry( AuthGroup,
3182                                            pDirEntry);
3183
3184                 AFSReleaseResource( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
3185
3186                 if( !NT_SUCCESS( ntStatus))
3187                 {
3188
3189                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3190                                   AFS_TRACE_LEVEL_VERBOSE,
3191                                   "AFSParseName (%p) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3192                                   Irp,
3193                                   &pDirEntry->NameInformation.FileName,
3194                                   pDirEntry->ObjectInformation->FileId.Cell,
3195                                   pDirEntry->ObjectInformation->FileId.Volume,
3196                                   pDirEntry->ObjectInformation->FileId.Vnode,
3197                                   pDirEntry->ObjectInformation->FileId.Unique,
3198                                   ntStatus));
3199
3200                     try_return( ntStatus);
3201                 }
3202             }
3203
3204             //
3205             // Create our full path name buffer
3206             //
3207
3208             uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length +
3209                                                     sizeof( WCHAR) +
3210                                                     pIrpSp->FileObject->FileName.Length +
3211                                                     sizeof( WCHAR);
3212
3213             uniFullName.Length = 0;
3214
3215             uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
3216                                                                     uniFullName.MaximumLength,
3217                                                                     AFS_NAME_BUFFER_THREE_TAG);
3218
3219             if( uniFullName.Buffer == NULL)
3220             {
3221
3222                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3223                               AFS_TRACE_LEVEL_ERROR,
3224                               "AFSParseName (%p) Failed to allocate full name buffer\n",
3225                               Irp));
3226
3227                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3228             }
3229
3230             RtlZeroMemory( uniFullName.Buffer,
3231                            uniFullName.MaximumLength);
3232
3233             RtlCopyMemory( uniFullName.Buffer,
3234                            pRelatedCcb->FullFileName.Buffer,
3235                            pRelatedCcb->FullFileName.Length);
3236
3237             uniFullName.Length = pRelatedCcb->FullFileName.Length;
3238
3239             usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
3240
3241             usComponentLength = pIrpSp->FileObject->FileName.Length;
3242
3243             if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
3244                 pIrpSp->FileObject->FileName.Length > 0 &&
3245                 pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
3246                 pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
3247             {
3248
3249                 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
3250
3251                 uniFullName.Length += sizeof( WCHAR);
3252
3253                 usComponentLength += sizeof( WCHAR);
3254             }
3255
3256             if( pIrpSp->FileObject->FileName.Length > 0)
3257             {
3258
3259                 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
3260                                pIrpSp->FileObject->FileName.Buffer,
3261                                pIrpSp->FileObject->FileName.Length);
3262
3263                 uniFullName.Length += pIrpSp->FileObject->FileName.Length;
3264             }
3265
3266             *RootFileName = uniFullName;
3267
3268             //
3269             // We populate up to the current parent
3270             //
3271
3272             if( pRelatedNameArray == NULL)
3273             {
3274
3275                 //
3276                 // Init and populate our name array
3277                 //
3278
3279                 pNameArray = AFSInitNameArray( NULL,
3280                                                0);
3281
3282                 if( pNameArray == NULL)
3283                 {
3284
3285                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3286                                   AFS_TRACE_LEVEL_VERBOSE,
3287                                   "AFSParseName (%p) Failed to initialize name array\n",
3288                                   Irp));
3289
3290                     AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3291
3292                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3293                 }
3294
3295                 ntStatus = AFSPopulateNameArray( pNameArray,
3296                                                  NULL,
3297                                                  pRelatedCcb->DirectoryCB);
3298             }
3299             else
3300             {
3301
3302                 //
3303                 // Init and populate our name array
3304                 //
3305
3306                 pNameArray = AFSInitNameArray( NULL,
3307                                                pRelatedNameArray->MaxElementCount);
3308
3309                 if( pNameArray == NULL)
3310                 {
3311
3312                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3313                                   AFS_TRACE_LEVEL_VERBOSE,
3314                                   "AFSParseName (%p) Failed to initialize name array\n",
3315                                   Irp));
3316
3317                     AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3318
3319                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3320                 }
3321
3322                 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
3323                                                                  pRelatedNameArray,
3324                                                                  pRelatedCcb->DirectoryCB);
3325             }
3326
3327             if( !NT_SUCCESS( ntStatus))
3328             {
3329
3330                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3331                               AFS_TRACE_LEVEL_VERBOSE,
3332                               "AFSParseName (%p) Failed to populate name array\n",
3333                               Irp));
3334
3335                 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3336
3337                 try_return( ntStatus);
3338             }
3339
3340             ParsedFileName->Length = usComponentLength;
3341             ParsedFileName->MaximumLength = uniFullName.MaximumLength;
3342
3343             ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
3344
3345             //
3346             // Indicate to caller that RootFileName must be freed
3347             //
3348
3349             SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
3350
3351             *NameArray = pNameArray;
3352
3353             //
3354             // Increment our volume reference count
3355             //
3356
3357             lCount = AFSVolumeIncrement( pVolumeCB,
3358                                          AFS_VOLUME_REFERENCE_PARSE_NAME);
3359
3360             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3361                           AFS_TRACE_LEVEL_VERBOSE,
3362                           "AFSParseName Increment count on volume %p Cnt %d\n",
3363                           pVolumeCB,
3364                           lCount));
3365
3366             *VolumeCB = pVolumeCB;
3367
3368             *ParentDirectoryCB = pDirEntry;
3369
3370             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3371                           AFS_TRACE_LEVEL_VERBOSE_2,
3372                           "AFSParseName (%p) Returning full name %wZ\n",
3373                           Irp,
3374                           &uniFullName));
3375
3376             try_return( ntStatus);
3377         }
3378
3379         //
3380         // No wild cards in the name
3381         //
3382
3383         uniFullName = pIrpSp->FileObject->FileName;
3384
3385         if( FsRtlDoesNameContainWildCards( &uniFullName) ||
3386             uniFullName.Length < AFSServerName.Length)
3387         {
3388
3389             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3390                           AFS_TRACE_LEVEL_ERROR,
3391                           "AFSParseName (%p) Name %wZ contains wild cards or too short\n",
3392                           Irp,
3393                           &uniFullName));
3394
3395             try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3396         }
3397
3398         //
3399         // The name is a fully qualified name. Parse out the server/share names and
3400         // point to the root qualified name
3401         // First thing is to locate the server name
3402         //
3403
3404         FsRtlDissectName( uniFullName,
3405                           &uniComponentName,
3406                           &uniRemainingPath);
3407
3408         uniFullName = uniRemainingPath;
3409
3410         //
3411         // This component is the server name we are serving
3412         //
3413
3414         if( RtlCompareUnicodeString( &uniComponentName,
3415                                      &AFSServerName,
3416                                      TRUE) != 0)
3417         {
3418
3419             //
3420             // Drive letter based name?
3421             //
3422
3423             uniFullName = pIrpSp->FileObject->FileName;
3424
3425             while( usIndex < uniFullName.Length/sizeof( WCHAR))
3426             {
3427
3428                 if( uniFullName.Buffer[ usIndex] == L':')
3429                 {
3430
3431                     uniFullName.Buffer = &uniFullName.Buffer[ usIndex + 2];
3432
3433                     uniFullName.Length -= (usIndex + 2) * sizeof( WCHAR);
3434
3435                     usDriveIndex = usIndex - 1;
3436
3437                     break;
3438                 }
3439
3440                 usIndex++;
3441             }
3442
3443             //
3444             // Do we have the right server name now?
3445             //
3446
3447             FsRtlDissectName( uniFullName,
3448                               &uniComponentName,
3449                               &uniRemainingPath);
3450
3451             uniFullName = uniRemainingPath;
3452
3453             //
3454             // This component is the server name we are serving
3455             //
3456
3457             if( RtlCompareUnicodeString( &uniComponentName,
3458                                          &AFSServerName,
3459                                          TRUE) != 0)
3460             {
3461
3462                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3463                               AFS_TRACE_LEVEL_ERROR,
3464                               "AFSParseName (%p) Name %wZ does not have server name\n",
3465                               Irp,
3466                               &pIrpSp->FileObject->FileName));
3467
3468                 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3469             }
3470
3471             //
3472             // Validate this drive letter is actively mapped
3473             //
3474
3475             if( usDriveIndex > 0 &&
3476                 !AFSIsDriveMapped( pIrpSp->FileObject->FileName.Buffer[ usDriveIndex]))
3477             {
3478
3479                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3480                               AFS_TRACE_LEVEL_ERROR,
3481                               "AFSParseName (%p) Name %wZ contains invalid drive mapping\n",
3482                               Irp,
3483                               &pIrpSp->FileObject->FileName));
3484
3485                 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3486             }
3487         }
3488
3489         if( FsRtlDoesNameContainWildCards( &uniFullName))
3490         {
3491
3492             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3493                           AFS_TRACE_LEVEL_ERROR,
3494                           "AFSParseName (%p) Component %wZ contains wild cards\n",
3495                           Irp,
3496                           &uniFullName));
3497
3498             try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3499         }
3500
3501         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3502                       AFS_TRACE_LEVEL_VERBOSE_2,
3503                       "AFSParseName (%p) Processing full name %wZ\n",
3504                       Irp,
3505                       &uniFullName));
3506
3507         if( uniFullName.Length > 0 &&
3508             uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] == L'\\')
3509         {
3510
3511             uniFullName.Length -= sizeof( WCHAR);
3512         }
3513
3514         //
3515         // Be sure we are online and ready to go
3516         //
3517
3518         AFSAcquireShared( AFSGlobalRoot->VolumeLock,
3519                           TRUE);
3520
3521         if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3522             BooleanFlagOn( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3523         {
3524
3525             //
3526             // The volume has been taken off line so fail the access
3527             //
3528
3529             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3530                           AFS_TRACE_LEVEL_ERROR,
3531                           "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3532                           Irp,
3533                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3534                           AFSGlobalRoot->ObjectInformation.FileId.Volume));
3535
3536             AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3537
3538             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3539         }
3540
3541         if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3542         {
3543
3544             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3545                           AFS_TRACE_LEVEL_VERBOSE,
3546                           "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
3547                           Irp,
3548                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3549                           AFSGlobalRoot->ObjectInformation.FileId.Volume));
3550
3551             ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3552                                         AFSGlobalRoot);
3553
3554             if( !NT_SUCCESS( ntStatus))
3555             {
3556
3557                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3558                               AFS_TRACE_LEVEL_ERROR,
3559                               "AFSParseName (%p) Failed verification of root Status %08lX\n",
3560                               Irp,
3561                               ntStatus));
3562
3563                 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3564
3565                 try_return( ntStatus);
3566             }
3567         }
3568
3569         AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3570
3571         if( !BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3572         {
3573
3574             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3575                           AFS_TRACE_LEVEL_VERBOSE,
3576                           "AFSParseName (%p) Enumerating global root of volume %08lX:%08lX\n",
3577                           Irp,
3578                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3579                           AFSGlobalRoot->ObjectInformation.FileId.Volume));
3580
3581             ntStatus = AFSEnumerateGlobalRoot( AuthGroup);
3582
3583             if( !NT_SUCCESS( ntStatus))
3584             {
3585
3586                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3587                               AFS_TRACE_LEVEL_ERROR,
3588                               "AFSParseName (%p) Failed enumeraiton of root Status %08lX\n",
3589                               Irp,
3590                               ntStatus));
3591
3592                 try_return( ntStatus);
3593             }
3594         }
3595
3596         //
3597         // Check for the \\Server access and return it as though it were \\Server\Globalroot
3598         //
3599
3600         if( uniRemainingPath.Buffer == NULL ||
3601             ( uniRemainingPath.Length == sizeof( WCHAR) &&
3602               uniRemainingPath.Buffer[ 0] == L'\\'))
3603         {
3604
3605             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3606                           AFS_TRACE_LEVEL_VERBOSE_2,
3607                           "AFSParseName (%p) Returning global root access\n",
3608                           Irp));
3609
3610             lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3611
3612             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3613                           AFS_TRACE_LEVEL_VERBOSE,
3614                           "AFSParseName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3615                           &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3616                           AFSGlobalRoot->DirectoryCB,
3617                           NULL,
3618                           lCount));
3619
3620             *VolumeCB = NULL;
3621
3622             FileName->Length = 0;
3623             FileName->MaximumLength = 0;
3624             FileName->Buffer = NULL;
3625
3626             try_return( ntStatus = STATUS_SUCCESS);
3627         }
3628
3629         *RootFileName = uniFullName;
3630
3631         //
3632         // Include the starting \ in the root name
3633         //
3634
3635         if( RootFileName->Buffer[ 0] != L'\\')
3636         {
3637             RootFileName->Buffer--;
3638             RootFileName->Length += sizeof( WCHAR);
3639             RootFileName->MaximumLength += sizeof( WCHAR);
3640         }
3641
3642         //
3643         // Get the 'share' name
3644         //
3645
3646         FsRtlDissectName( uniFullName,
3647                           &uniComponentName,
3648                           &uniRemainingPath);
3649
3650         if( FsRtlDoesNameContainWildCards( &uniFullName))
3651         {
3652
3653             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3654                           AFS_TRACE_LEVEL_ERROR,
3655                           "AFSParseName (%p) Component %wZ contains wild cards\n",
3656                           Irp,
3657                           &uniComponentName));
3658
3659             try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3660         }
3661
3662         //
3663         // If this is the ALL access then perform some additional processing
3664         //
3665
3666         if( uniComponentName.Length == 0 ||
3667             RtlCompareUnicodeString( &uniComponentName,
3668                                      &AFSGlobalRootName,
3669                                      TRUE) == 0)
3670         {
3671
3672             bIsAllShare = TRUE;
3673
3674             //
3675             // If there is nothing else then get out
3676             //
3677
3678             if( uniRemainingPath.Buffer == NULL ||
3679                 uniRemainingPath.Length == 0 ||
3680                 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3681                   uniRemainingPath.Buffer[ 0] == L'\\'))
3682             {
3683
3684                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3685                               AFS_TRACE_LEVEL_VERBOSE_2,
3686                               "AFSParseName (%p) Returning global root access\n",
3687                               Irp));
3688
3689                 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3690
3691                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3692                               AFS_TRACE_LEVEL_VERBOSE,
3693                               "AFSParseName Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
3694                               &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3695                               AFSGlobalRoot->DirectoryCB,
3696                               NULL,
3697                               lCount));
3698
3699                 *VolumeCB = NULL;
3700
3701                 FileName->Length = 0;
3702                 FileName->MaximumLength = 0;
3703                 FileName->Buffer = NULL;
3704
3705                 try_return( ntStatus = STATUS_SUCCESS);
3706             }
3707
3708             //
3709             // Process the name again to strip off the ALL portion
3710             //
3711
3712             uniFullName = uniRemainingPath;
3713
3714             FsRtlDissectName( uniFullName,
3715                               &uniComponentName,
3716                               &uniRemainingPath);
3717
3718             //
3719             // Check for the PIOCtl name
3720             //
3721
3722             if( RtlCompareUnicodeString( &uniComponentName,
3723                                          &AFSPIOCtlName,
3724                                          TRUE) == 0)
3725             {
3726
3727                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3728                               AFS_TRACE_LEVEL_VERBOSE_2,
3729                               "AFSParseName (%p) Returning root PIOCtl access\n",
3730                               Irp));
3731
3732                 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3733
3734                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3735                               AFS_TRACE_LEVEL_VERBOSE,
3736                               "AFSParseName Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
3737                               &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3738                               AFSGlobalRoot->DirectoryCB,
3739                               NULL,
3740                               lCount));
3741
3742                 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3743
3744                 *VolumeCB = NULL;
3745
3746                 *FileName = AFSPIOCtlName;
3747
3748                 try_return( ntStatus = STATUS_SUCCESS);
3749             }
3750         }
3751         else if( (pDirEntry = AFSGetSpecialShareNameEntry( &uniComponentName,
3752                                                            &uniRemainingPath)) != NULL)
3753         {
3754
3755             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3756                           AFS_TRACE_LEVEL_VERBOSE_2,
3757                           "AFSParseName (%p) Returning root share name %wZ access\n",
3758                           Irp,
3759                           &uniComponentName));
3760
3761             //
3762             // Add in the full share name to pass back
3763             //
3764
3765             if( uniRemainingPath.Buffer != NULL)
3766             {
3767
3768                 //
3769                 // This routine strips off the leading slash so add it back in
3770                 //
3771
3772                 uniRemainingPath.Buffer--;
3773                 uniRemainingPath.Length += sizeof( WCHAR);
3774                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3775
3776                 //
3777                 // And the cell name
3778                 //
3779
3780                 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3781                 uniRemainingPath.Length += uniComponentName.Length;
3782                 uniRemainingPath.MaximumLength += uniComponentName.Length;
3783
3784                 uniComponentName = uniRemainingPath;
3785             }
3786
3787             *VolumeCB = NULL;
3788
3789             *FileName = uniComponentName;
3790
3791             ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3792
3793             *ParentDirectoryCB = pDirEntry;
3794
3795             try_return( ntStatus = STATUS_SUCCESS);
3796         }
3797
3798         //
3799         // Determine the 'share' we are accessing
3800         //
3801
3802         ulCRC = AFSGenerateCRC( &uniComponentName,
3803                                 FALSE);
3804
3805         AFSAcquireShared( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3806                           TRUE);
3807
3808         bReleaseTreeLock = TRUE;
3809
3810         AFSLocateCaseSensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
3811                                         ulCRC,
3812                                         &pDirEntry);
3813
3814         if( pDirEntry == NULL)
3815         {
3816
3817             ulCRC = AFSGenerateCRC( &uniComponentName,
3818                                     TRUE);
3819
3820             AFSLocateCaseInsensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
3821                                               ulCRC,
3822                                               &pDirEntry);
3823
3824             if( pDirEntry == NULL)
3825             {
3826
3827                 //
3828                 // OK, if this component is a valid short name then try
3829                 // a lookup in the short name tree
3830                 //
3831
3832                 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3833                     RtlIsNameLegalDOS8Dot3( &uniComponentName,
3834                                             NULL,
3835                                             NULL))
3836                 {
3837
3838                     AFSLocateShortNameDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.ShortNameTree,
3839                                                 ulCRC,
3840                                                 &pDirEntry);
3841                 }
3842
3843                 if( pDirEntry == NULL)
3844                 {
3845
3846                     //
3847                     // Check with the service whether it is a valid cell name
3848                     //
3849
3850                     AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3851
3852                     bReleaseTreeLock = FALSE;
3853
3854                     ntStatus = AFSCheckCellName( AuthGroup,
3855                                                  &uniComponentName,
3856                                                  &pDirEntry);
3857
3858                     if( !NT_SUCCESS( ntStatus))
3859                     {
3860
3861                         if ( bIsAllShare &&
3862                              uniRemainingPath.Length == 0 &&
3863                              ntStatus == STATUS_OBJECT_PATH_NOT_FOUND)
3864                         {
3865
3866                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3867                                           AFS_TRACE_LEVEL_VERBOSE,
3868                                           "AFSParseName (%p) AFSCheckCellName %wZ returned path not found; ntStatus %08X\n",
3869                                           Irp,
3870                                           &uniComponentName,
3871                                           STATUS_OBJECT_NAME_NOT_FOUND));
3872
3873                             ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
3874                         }
3875
3876                         try_return( ntStatus);
3877                     }
3878                 }
3879             }
3880         }
3881
3882         if( bReleaseTreeLock)
3883         {
3884             AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3885         }
3886
3887
3888         //
3889         // Be sure we are starting from the correct volume
3890         //
3891
3892         if( pDirEntry->ObjectInformation->VolumeCB != AFSGlobalRoot)
3893         {
3894
3895             //
3896             // We dropped the global root in the CheckCellName routine which is the
3897             // only way we can be here
3898             //
3899
3900             pVolumeCB = pDirEntry->ObjectInformation->VolumeCB;
3901
3902             //
3903             // Init our name array
3904             //
3905
3906             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
3907                                            0);
3908
3909             if( pNameArray == NULL)
3910             {
3911
3912                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3913                               AFS_TRACE_LEVEL_VERBOSE,
3914                               "AFSParseName (%p) Failed to initialize name array\n",
3915                               Irp));
3916
3917                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3918             }
3919
3920             ntStatus = AFSInsertNextElement( pNameArray,
3921                                              pVolumeCB->DirectoryCB);
3922
3923             if ( ntStatus)
3924             {
3925
3926                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3927                               AFS_TRACE_LEVEL_VERBOSE,
3928                               "AFSParseName (%p) Failed to insert name array element\n",
3929                               Irp));
3930
3931                 try_return( ntStatus);
3932             }
3933
3934             //
3935             // In this case don't add back in the 'share' name since that is where we are
3936             // starting. Just put the leading slash back in
3937             //
3938
3939             if( uniRemainingPath.Buffer != NULL)
3940             {
3941
3942                 uniRemainingPath.Buffer--;
3943                 uniRemainingPath.Length += sizeof( WCHAR);
3944                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3945
3946                 if( uniRemainingPath.Length > sizeof( WCHAR))
3947                 {
3948
3949                     ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3950                 }
3951
3952                 //
3953                 // Pass back the parent being the root of the volume
3954                 //
3955
3956                 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3957             }
3958             else
3959             {
3960
3961                 //
3962                 // Pass back a root slash
3963                 //
3964
3965                 uniRemainingPath = uniComponentName;
3966
3967                 uniRemainingPath.Buffer--;
3968                 uniRemainingPath.Length = sizeof( WCHAR);
3969                 uniRemainingPath.MaximumLength = sizeof( WCHAR);
3970
3971                 //
3972                 // This is a root open so pass back no parent
3973                 //
3974             }
3975         }
3976         else
3977         {
3978
3979             pVolumeCB = AFSGlobalRoot;
3980
3981             //
3982             // Init our name array
3983             //
3984
3985             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
3986                                            0);
3987             if( pNameArray == NULL)
3988             {
3989
3990                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3991                               AFS_TRACE_LEVEL_VERBOSE,
3992                               "AFSParseName (%p) Failed to initialize name array\n",
3993                               Irp));
3994
3995                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3996             }
3997
3998             //
3999             // Add back in the 'share' portion of the name since we will parse it out on return
4000             //
4001
4002             if( uniRemainingPath.Buffer != NULL)
4003             {
4004
4005                 //
4006                 // This routine strips off the leading slash so add it back in
4007                 //
4008
4009                 uniRemainingPath.Buffer--;
4010                 uniRemainingPath.Length += sizeof( WCHAR);
4011                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
4012
4013                 if( uniRemainingPath.Length > sizeof( WCHAR))
4014                 {
4015
4016                     ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
4017                 }
4018
4019                 //
4020                 // And the cell name
4021                 //
4022
4023                 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
4024                 uniRemainingPath.Length += uniComponentName.Length;
4025                 uniRemainingPath.MaximumLength += uniComponentName.Length;
4026             }
4027             else
4028             {
4029
4030                 uniRemainingPath = uniComponentName;
4031             }
4032
4033             //
4034             // And the leading slash again ...
4035             //
4036
4037             uniRemainingPath.Buffer--;
4038             uniRemainingPath.Length += sizeof( WCHAR);
4039             uniRemainingPath.MaximumLength += sizeof( WCHAR);
4040
4041             //
4042             // Pass back the parent being the volume root
4043             //
4044
4045             *ParentDirectoryCB = pVolumeCB->DirectoryCB;
4046         }
4047
4048         //
4049         // Return the remaining portion as the file name
4050         //
4051
4052         *FileName = uniRemainingPath;
4053
4054         *ParsedFileName = uniRemainingPath;
4055
4056         *NameArray = pNameArray;
4057
4058         *VolumeCB = pVolumeCB;
4059
4060         //
4061         // Increment our reference on the volume
4062         //
4063
4064         lCount = AFSVolumeIncrement( pVolumeCB,
4065                                      AFS_VOLUME_REFERENCE_PARSE_NAME);
4066
4067         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4068                       AFS_TRACE_LEVEL_VERBOSE,
4069                       "AFSParseName Increment2 count on global volume %p Cnt %d\n",
4070                       pVolumeCB,
4071                       lCount));
4072
4073 try_exit:
4074
4075         if( NT_SUCCESS( ntStatus))
4076         {
4077
4078             if( *ParentDirectoryCB != NULL)
4079             {
4080
4081                 lCount = InterlockedIncrement( &(*ParentDirectoryCB)->DirOpenReferenceCount);
4082
4083                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4084                               AFS_TRACE_LEVEL_VERBOSE,
4085                               "AFSParseName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4086                               &(*ParentDirectoryCB)->NameInformation.FileName,
4087                               (*ParentDirectoryCB),
4088                               NULL,
4089                               lCount));
4090             }
4091         }
4092
4093         if( *VolumeCB != NULL)
4094         {
4095             ASSERT( (*VolumeCB)->VolumeReferenceCount > 0);
4096         }
4097
4098         if( ntStatus != STATUS_SUCCESS)
4099         {
4100
4101             if( pNameArray != NULL)
4102             {
4103
4104                 AFSFreeNameArray( pNameArray);
4105             }
4106         }
4107     }
4108
4109     return ntStatus;
4110 }
4111
4112 NTSTATUS
4113 AFSCheckCellName( IN GUID *AuthGroup,
4114                   IN UNICODE_STRING *CellName,
4115                   OUT AFSDirectoryCB **ShareDirEntry)
4116 {
4117
4118     NTSTATUS ntStatus = STATUS_SUCCESS;
4119     UNICODE_STRING uniName;
4120     AFSDirEnumEntry *pDirEnumEntry = NULL;
4121     AFSDirHdr *pDirHdr = &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr;
4122     AFSDirectoryCB *pDirNode = NULL;
4123     UNICODE_STRING uniDirName, uniTargetName;
4124     AFSVolumeCB *pVolumeCB = NULL;
4125     LONG lCount;
4126
4127     __Enter
4128     {
4129
4130         //
4131         // Look for some default names we will not handle
4132         //
4133
4134         RtlInitUnicodeString( &uniName,
4135                               L"IPC$");
4136
4137         if( RtlCompareUnicodeString( &uniName,
4138                                      CellName,
4139                                      TRUE) == 0)
4140         {
4141
4142             try_return( ntStatus = STATUS_NO_SUCH_FILE);
4143         }
4144
4145         RtlInitUnicodeString( &uniName,
4146                               L"wkssvc");
4147
4148         if( RtlCompareUnicodeString( &uniName,
4149                                      CellName,
4150                                      TRUE) == 0)
4151         {
4152
4153             try_return( ntStatus = STATUS_NO_SUCH_FILE);
4154         }
4155
4156         RtlInitUnicodeString( &uniName,
4157                               L"srvsvc");
4158
4159         if( RtlCompareUnicodeString( &uniName,
4160                                      CellName,
4161                                      TRUE) == 0)
4162         {
4163
4164             try_return( ntStatus = STATUS_NO_SUCH_FILE);
4165         }
4166
4167         RtlInitUnicodeString( &uniName,
4168                               L"PIPE");
4169
4170         if( RtlCompareUnicodeString( &uniName,
4171                                      CellName,
4172                                      TRUE) == 0)
4173         {
4174
4175             try_return( ntStatus = STATUS_NO_SUCH_FILE);
4176         }
4177
4178         //
4179         // OK, ask the CM about this component name
4180         //
4181
4182         ntStatus = AFSEvaluateTargetByName( AuthGroup,
4183                                             &AFSGlobalRoot->ObjectInformation,
4184                                             CellName,
4185                                             0,
4186                                             &pDirEnumEntry);
4187
4188         if( !NT_SUCCESS( ntStatus))
4189         {
4190
4191             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4192                           AFS_TRACE_LEVEL_WARNING,
4193                           "AFSCheckCellName entry %wZ does not exist parent FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4194                           CellName,
4195                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
4196                           AFSGlobalRoot->ObjectInformation.FileId.Volume,
4197                           AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4198                           AFSGlobalRoot->ObjectInformation.FileId.Unique,
4199                           ntStatus));
4200
4201             try_return( ntStatus);
4202         }
4203
4204         //
4205         // OK, we have a dir enum entry back so add it to the root node
4206         //
4207
4208         uniDirName = *CellName;
4209
4210         uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
4211         uniTargetName.MaximumLength = uniTargetName.Length;
4212         uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
4213
4214         //
4215         // Is this entry a root volume entry?
4216         //
4217
4218         if( pDirEnumEntry->FileId.Cell != AFSGlobalRoot->ObjectInformation.FileId.Cell ||
4219             pDirEnumEntry->FileId.Volume != AFSGlobalRoot->ObjectInformation.FileId.Volume)
4220         {
4221
4222             //
4223             // Build the root volume entry
4224             //
4225
4226             ntStatus = AFSBuildRootVolume( AuthGroup,
4227                                            &pDirEnumEntry->FileId,
4228                                            &pVolumeCB);
4229
4230             //
4231             // On success returns with a volume reference count held
4232             //
4233
4234             if( !NT_SUCCESS( ntStatus))
4235             {
4236                 try_return( ntStatus);
4237             }
4238
4239             *ShareDirEntry = pVolumeCB->DirectoryCB;
4240
4241             lCount = InterlockedIncrement( &pVolumeCB->DirectoryCB->DirOpenReferenceCount);
4242
4243             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4244                           AFS_TRACE_LEVEL_VERBOSE,
4245                           "AFSCheckCellName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4246                           &pVolumeCB->DirectoryCB->NameInformation.FileName,
4247                           pVolumeCB->DirectoryCB,
4248                           NULL,
4249                           lCount));
4250
4251             lCount = AFSVolumeDecrement( pVolumeCB,
4252                                          AFS_VOLUME_REFERENCE_BUILD_ROOT);
4253
4254             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4255                           AFS_TRACE_LEVEL_VERBOSE,
4256                           "AFSCheckCellName Decrement count on volume %p Cnt %d\n",
4257                           pVolumeCB,
4258                           lCount));
4259         }
4260         else
4261         {
4262
4263             lCount = InterlockedIncrement( &pDirHdr->ContentIndex);
4264
4265             pDirNode = AFSInitDirEntry( &AFSGlobalRoot->ObjectInformation,
4266                                         &uniDirName,
4267                                         &uniTargetName,
4268                                         pDirEnumEntry,
4269                                         (ULONG)lCount);
4270
4271             if( pDirNode == NULL)
4272             {
4273
4274                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4275             }
4276
4277             //
4278             // Init the short name if we have one
4279             //
4280
4281             if( pDirEnumEntry->ShortNameLength > 0)
4282             {
4283
4284                 pDirNode->NameInformation.ShortNameLength = pDirEnumEntry->ShortNameLength;
4285
4286                 RtlCopyMemory( pDirNode->NameInformation.ShortName,
4287                                pDirEnumEntry->ShortName,
4288                                pDirNode->NameInformation.ShortNameLength);
4289             }
4290
4291             AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4292                             TRUE);
4293
4294             //
4295             // Insert the node into the name tree
4296             //
4297
4298             ASSERT( ExIsResourceAcquiredExclusiveLite( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock));
4299
4300             if( pDirHdr->CaseSensitiveTreeHead == NULL)
4301             {
4302
4303                 pDirHdr->CaseSensitiveTreeHead = pDirNode;
4304             }
4305             else
4306             {
4307
4308                 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( pDirHdr->CaseSensitiveTreeHead,
4309                                                                  pDirNode)))
4310                 {
4311
4312                     AFSDeleteDirEntry( &AFSGlobalRoot->ObjectInformation,
4313                                        pDirNode);
4314
4315                     AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4316
4317                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4318                 }
4319             }
4320
4321             ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
4322
4323             if( pDirHdr->CaseInsensitiveTreeHead == NULL)
4324             {
4325
4326                 pDirHdr->CaseInsensitiveTreeHead = pDirNode;
4327
4328                 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
4329             }
4330             else
4331             {
4332
4333                 AFSInsertCaseInsensitiveDirEntry( pDirHdr->CaseInsensitiveTreeHead,
4334                                                   pDirNode);
4335             }
4336
4337             if( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead == NULL)
4338             {
4339
4340                 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead = pDirNode;
4341             }
4342             else
4343             {
4344
4345                 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
4346
4347                 pDirNode->ListEntry.bLink = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail;
4348             }
4349
4350             AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail = pDirNode;
4351
4352             SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
4353
4354             lCount = InterlockedIncrement( &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeCount);
4355
4356             AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
4357                           AFS_TRACE_LEVEL_VERBOSE,
4358                           "AFSCheckCellName Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
4359                           &pDirNode->NameInformation.FileName,
4360                           lCount,
4361                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
4362                           AFSGlobalRoot->ObjectInformation.FileId.Volume,
4363                           AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4364                           AFSGlobalRoot->ObjectInformation.FileId.Unique));
4365
4366             lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
4367
4368             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4369                           AFS_TRACE_LEVEL_VERBOSE,
4370                           "AFSCheckCellName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
4371                           &pDirNode->NameInformation.FileName,
4372                           pDirNode,
4373                           NULL,
4374                           lCount));
4375
4376             AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4377
4378             //
4379             // Pass back the dir node
4380             //
4381
4382             *ShareDirEntry = pDirNode;
4383         }
4384
4385 try_exit:
4386
4387         if( pDirEnumEntry != NULL)
4388         {
4389
4390             AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_31_TAG);
4391         }
4392     }
4393
4394     return ntStatus;
4395 }
4396
4397 NTSTATUS
4398 AFSBuildMountPointTarget( IN GUID *AuthGroup,
4399                           IN AFSDirectoryCB  *DirectoryCB,
4400                           OUT AFSVolumeCB **TargetVolumeCB)
4401 {
4402
4403     NTSTATUS ntStatus = STATUS_SUCCESS;
4404     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4405     AFSDirEnumEntry *pDirEntry = NULL;
4406     ULONGLONG       ullIndex = 0;
4407     AFSVolumeCB *pVolumeCB = NULL;
4408     AFSFileID stTargetFileID;
4409     LONG lCount;
4410     BOOLEAN bReleaseVolumeLock = FALSE;
4411
4412     __Enter
4413     {
4414
4415         //
4416         // Loop on each entry, building the chain until we encounter the final target
4417         //
4418
4419         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4420                       AFS_TRACE_LEVEL_VERBOSE_2,
4421                       "AFSBuildMountPointTarget Building target directory for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4422                       &DirectoryCB->NameInformation.FileName,
4423                       DirectoryCB->ObjectInformation->FileId.Cell,
4424                       DirectoryCB->ObjectInformation->FileId.Volume,
4425                       DirectoryCB->ObjectInformation->FileId.Vnode,
4426                       DirectoryCB->ObjectInformation->FileId.Unique));
4427
4428         //
4429         // Do we need to evaluate the node?
4430         //
4431
4432         //if( DirectoryCB->ObjectInformation->TargetFileId.Vnode == 0 &&
4433         //    DirectoryCB->ObjectInformation->TargetFileId.Unique == 0)
4434         {
4435
4436             //
4437             // Go evaluate the current target to get the target fid
4438             //
4439
4440             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4441                           AFS_TRACE_LEVEL_VERBOSE_2,
4442                           "AFSBuildMountPointTarget Evaluating target %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4443                               &DirectoryCB->NameInformation.FileName,
4444                               DirectoryCB->ObjectInformation->FileId.Cell,
4445                               DirectoryCB->ObjectInformation->FileId.Volume,
4446                               DirectoryCB->ObjectInformation->FileId.Vnode,
4447                               DirectoryCB->ObjectInformation->FileId.Unique));
4448
4449             ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
4450                                               AuthGroup,
4451                                               FALSE,
4452                                               &pDirEntry);
4453
4454             if( !NT_SUCCESS( ntStatus))
4455             {
4456
4457                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4458                               AFS_TRACE_LEVEL_ERROR,
4459                               "AFSBuildMountPointTarget Failed to evaluate target %wZ Status %08lX\n",
4460                               &DirectoryCB->NameInformation.FileName,
4461                               ntStatus));
4462
4463                 try_return( ntStatus);
4464             }
4465
4466             if( pDirEntry->TargetFileId.Vnode == 0 &&
4467                 pDirEntry->TargetFileId.Unique == 0)
4468             {
4469
4470                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4471                               AFS_TRACE_LEVEL_ERROR,
4472                               "AFSBuildMountPointTarget Target %wZ FID %08lX-%08lX-%08lX-%08lX service returned zero FID\n",
4473                               &DirectoryCB->NameInformation.FileName,
4474                               DirectoryCB->ObjectInformation->FileId.Cell,
4475                               DirectoryCB->ObjectInformation->FileId.Volume,
4476                               DirectoryCB->ObjectInformation->FileId.Vnode,
4477                               DirectoryCB->ObjectInformation->FileId.Unique));
4478
4479                 try_return( ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED);
4480             }
4481
4482             AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
4483                             TRUE);
4484
4485             ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
4486                                             &DirectoryCB->Flags,
4487                                             (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4488                                             (USHORT)pDirEntry->TargetNameLength);
4489
4490             if( !NT_SUCCESS( ntStatus))
4491             {
4492
4493                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4494
4495                 try_return( ntStatus);
4496             }
4497
4498             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4499
4500             DirectoryCB->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
4501         }
4502
4503         stTargetFileID = DirectoryCB->ObjectInformation->TargetFileId;
4504
4505         //
4506         // Try to locate this FID. First the volume then the
4507         // entry itself
4508         //
4509
4510         ullIndex = AFSCreateHighIndex( &stTargetFileID);
4511
4512         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4513                       AFS_TRACE_LEVEL_VERBOSE,
4514                       "AFSBuildMountPointTarget Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4515                       &pDevExt->Specific.RDR.VolumeTreeLock,
4516                       PsGetCurrentThread()));
4517
4518         AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4519                           TRUE);
4520
4521         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4522                       AFS_TRACE_LEVEL_VERBOSE_2,
4523                       "AFSBuildMountPointTarget Locating volume for target %I64X\n",
4524                       ullIndex));
4525
4526         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4527                                        ullIndex,
4528                                        (AFSBTreeEntry **)&pVolumeCB);
4529
4530         //
4531         // We can be processing a request for a target that is on a volume
4532         // we have never seen before.
4533         //
4534
4535         if( pVolumeCB == NULL)
4536         {
4537
4538             //
4539             // Locking is held correctly in init routine
4540             //
4541
4542             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4543
4544             //
4545             // Go init the root of the volume
4546             //
4547
4548             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4549                           AFS_TRACE_LEVEL_VERBOSE_2,
4550                           "AFSBuildMountPointTarget Initializing root for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4551                           &DirectoryCB->NameInformation.FileName,
4552                           DirectoryCB->ObjectInformation->FileId.Cell,
4553                           DirectoryCB->ObjectInformation->FileId.Volume,
4554                           DirectoryCB->ObjectInformation->FileId.Vnode,
4555                           DirectoryCB->ObjectInformation->FileId.Unique));
4556
4557             ntStatus = AFSInitVolume( AuthGroup,
4558                                       &stTargetFileID,
4559                                       AFS_VOLUME_REFERENCE_MOUNTPT,
4560                                       &pVolumeCB);
4561
4562             if( !NT_SUCCESS( ntStatus))
4563             {
4564
4565                 try_return( ntStatus);
4566             }
4567
4568             //
4569             // pVolumeCB->VolumeLock held exclusive and
4570             // pVolumeCB->VolumeReferenceCount has been incremented
4571             // pVolumeCB->RootFcb == NULL
4572             //
4573
4574             bReleaseVolumeLock = TRUE;
4575         }
4576         else
4577         {
4578
4579             //
4580             // AFSInitVolume returns with a VolumeReferenceCount
4581             // obtain one to match
4582             //
4583
4584             lCount = AFSVolumeIncrement( pVolumeCB,
4585                                          AFS_VOLUME_REFERENCE_MOUNTPT);
4586
4587             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4588                           AFS_TRACE_LEVEL_VERBOSE,
4589                           "AFSBuildMountPointTarget Increment count on volume %p Cnt %d\n",
4590                           pVolumeCB,
4591                           lCount));
4592
4593             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4594         }
4595
4596         if( pVolumeCB->RootFcb == NULL)
4597         {
4598
4599             if ( bReleaseVolumeLock == FALSE)
4600             {
4601
4602                 AFSAcquireExcl( pVolumeCB->VolumeLock,
4603                                 TRUE);
4604
4605                 bReleaseVolumeLock = TRUE;
4606             }
4607
4608             //
4609             // Initialize the root fcb for this volume
4610             //
4611
4612             ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4613                                        pVolumeCB);
4614
4615             if( !NT_SUCCESS( ntStatus))
4616             {
4617
4618                 lCount = AFSVolumeDecrement( pVolumeCB,
4619                                              AFS_VOLUME_REFERENCE_MOUNTPT);
4620
4621                 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4622                               AFS_TRACE_LEVEL_VERBOSE,
4623                               "AFSBuildMountPoint Decrement count on volume %p Cnt %d\n",
4624                               pVolumeCB,
4625                               lCount));
4626
4627                 AFSReleaseResource( pVolumeCB->VolumeLock);
4628
4629                 try_return( ntStatus);
4630             }
4631
4632             //
4633             // Drop the lock acquired above
4634             //
4635
4636             AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4637         }
4638
4639         if ( bReleaseVolumeLock == TRUE)
4640         {
4641
4642             AFSReleaseResource( pVolumeCB->VolumeLock);
4643         }
4644
4645         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4646                       AFS_TRACE_LEVEL_VERBOSE_2,
4647                       "AFSBuildMountPointTarget Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4648                       &pVolumeCB->DirectoryCB->NameInformation.FileName,
4649                       pVolumeCB->ObjectInformation.FileId.Cell,
4650                       pVolumeCB->ObjectInformation.FileId.Volume,
4651                       pVolumeCB->ObjectInformation.FileId.Vnode,
4652                       pVolumeCB->ObjectInformation.FileId.Unique));
4653
4654         *TargetVolumeCB = pVolumeCB;
4655
4656 try_exit:
4657
4658         if( pDirEntry)
4659         {
4660
4661             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
4662         }
4663     }
4664
4665     return ntStatus;
4666 }
4667
4668 NTSTATUS
4669 AFSBuildRootVolume( IN GUID *AuthGroup,
4670                     IN AFSFileID *FileId,
4671                     OUT AFSVolumeCB **TargetVolumeCB)
4672 {
4673
4674     NTSTATUS ntStatus = STATUS_SUCCESS;
4675     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4676     ULONGLONG       ullIndex = 0;
4677     AFSVolumeCB *pVolumeCB = NULL;
4678     LONG lCount;
4679     BOOLEAN bReleaseVolumeLock = FALSE;
4680
4681     __Enter
4682     {
4683
4684         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4685                       AFS_TRACE_LEVEL_VERBOSE_2,
4686                       "AFSBuildRootVolume Building target volume for FID %08lX-%08lX-%08lX-%08lX\n",
4687                       FileId->Cell,
4688                       FileId->Volume,
4689                       FileId->Vnode,
4690                       FileId->Unique));
4691
4692         ullIndex = AFSCreateHighIndex( FileId);
4693
4694         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4695                       AFS_TRACE_LEVEL_VERBOSE,
4696                       "AFSBuildRootVolume Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4697                       &pDevExt->Specific.RDR.VolumeTreeLock,
4698                       PsGetCurrentThread()));
4699
4700         AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4701                           TRUE);
4702
4703         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4704                       AFS_TRACE_LEVEL_VERBOSE_2,
4705                       "AFSBuildRootVolume Locating volume for target %I64X\n",
4706                       ullIndex));
4707
4708         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4709                                        ullIndex,
4710                                        (AFSBTreeEntry **)&pVolumeCB);
4711
4712         //
4713         // We can be processing a request for a target that is on a volume
4714         // we have never seen before.
4715         //
4716
4717         if( pVolumeCB == NULL)
4718         {
4719
4720             //
4721             // Locking is held correctly in init routine
4722             //
4723
4724             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4725
4726             //
4727             // Go init the root of the volume
4728             //
4729
4730             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4731                          AFS_TRACE_LEVEL_VERBOSE_2,
4732                           "AFSBuildRootVolume Initializing root for FID %08lX-%08lX-%08lX-%08lX\n",
4733                           FileId->Cell,
4734                           FileId->Volume,
4735                           FileId->Vnode,
4736                           FileId->Unique));
4737
4738             ntStatus = AFSInitVolume( AuthGroup,
4739                                       FileId,
4740                                       AFS_VOLUME_REFERENCE_BUILD_ROOT,
4741                                       &pVolumeCB);
4742
4743             if( !NT_SUCCESS( ntStatus))
4744             {
4745
4746                 try_return( ntStatus);
4747             }
4748
4749             //
4750             // pVolumeCB->VolumeLock is held exclusive
4751             // pVolumeCB->VolumeReferenceCount has been incremented
4752             // pVolumeCB->RootFcb == NULL
4753             //
4754
4755             bReleaseVolumeLock = TRUE;
4756         }
4757         else
4758         {
4759
4760             //
4761             // AFSInitVolume returns with a VolumeReferenceCount
4762             // obtain one to match
4763             //
4764
4765             lCount = AFSVolumeIncrement( pVolumeCB,
4766                                          AFS_VOLUME_REFERENCE_BUILD_ROOT);
4767
4768             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4769                           AFS_TRACE_LEVEL_VERBOSE,
4770                           "AFSBuildRootVolume Increment count on volume %p Cnt %d\n",
4771                           pVolumeCB,
4772                           lCount));
4773
4774             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4775         }
4776
4777
4778         if( pVolumeCB->RootFcb == NULL)
4779         {
4780
4781             if ( bReleaseVolumeLock == FALSE)
4782             {
4783
4784                 AFSAcquireExcl( pVolumeCB->VolumeLock,
4785                                 TRUE);
4786
4787                 bReleaseVolumeLock = TRUE;
4788             }
4789
4790             //
4791             // Initialize the root fcb for this volume
4792             //
4793
4794             ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4795                                        pVolumeCB);
4796
4797             if( !NT_SUCCESS( ntStatus))
4798             {
4799
4800                 lCount = AFSVolumeDecrement( pVolumeCB,
4801                                              AFS_VOLUME_REFERENCE_BUILD_ROOT);
4802
4803                 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4804                               AFS_TRACE_LEVEL_VERBOSE,
4805                               "AFSBuildRootVolume Decrement count on volume %p Cnt %d\n",
4806                               pVolumeCB,
4807                               lCount));
4808
4809                 AFSReleaseResource( pVolumeCB->VolumeLock);
4810
4811                 try_return( ntStatus);
4812             }
4813
4814             //
4815             // Drop the lock acquired above
4816             //
4817
4818             AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4819         }
4820
4821         if ( bReleaseVolumeLock == TRUE)
4822         {
4823
4824             AFSReleaseResource( pVolumeCB->VolumeLock);
4825         }
4826
4827         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4828                       AFS_TRACE_LEVEL_VERBOSE_2,
4829                       "AFSBuildRootVolume Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4830                       &pVolumeCB->DirectoryCB->NameInformation.FileName,
4831                       pVolumeCB->ObjectInformation.FileId.Cell,
4832                       pVolumeCB->ObjectInformation.FileId.Volume,
4833                       pVolumeCB->ObjectInformation.FileId.Vnode,
4834                       pVolumeCB->ObjectInformation.FileId.Unique));
4835
4836         *TargetVolumeCB = pVolumeCB;
4837
4838 try_exit:
4839
4840         NOTHING;
4841     }
4842
4843     return ntStatus;
4844 }
4845
4846 NTSTATUS
4847 AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
4848                    IN PFILE_OBJECT FileObject,
4849                    IN UNICODE_STRING *RemainingPath,
4850                    IN GUID *AuthGroup)
4851 {
4852
4853     NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
4854     UNICODE_STRING uniReparseName;
4855     UNICODE_STRING uniMUPDeviceName;
4856     UNICODE_STRING uniIOMgrDeviceName;
4857     AFSDirEnumEntry *pDirEntry = NULL;
4858
4859     __Enter
4860     {
4861
4862         //
4863         // Build up the name to reparse
4864         //
4865
4866         RtlInitUnicodeString( &uniMUPDeviceName,
4867                               L"\\Device\\MUP");
4868
4869         RtlInitUnicodeString( &uniIOMgrDeviceName,
4870                               L"\\??\\");
4871
4872         uniReparseName.Length = 0;
4873         uniReparseName.Buffer = NULL;
4874
4875         //
4876         // Be sure we have a target name
4877         //
4878
4879         if( DirEntry->NameInformation.TargetName.Length == 0)
4880         {
4881
4882             ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
4883                                               AuthGroup,
4884                                               FALSE,
4885                                               &pDirEntry);
4886
4887             if( !NT_SUCCESS( ntStatus) ||
4888                 pDirEntry->TargetNameLength == 0)
4889             {
4890
4891                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4892                               AFS_TRACE_LEVEL_ERROR,
4893                               "AFSProcessDFSLink EvaluateTargetByID failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4894                               &DirEntry->NameInformation.FileName,
4895                               DirEntry->ObjectInformation->FileId.Cell,
4896                               DirEntry->ObjectInformation->FileId.Volume,
4897                               DirEntry->ObjectInformation->FileId.Vnode,
4898                               DirEntry->ObjectInformation->FileId.Unique,
4899                               ntStatus));
4900
4901                 if( NT_SUCCESS( ntStatus))
4902                 {
4903
4904                     ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
4905                 }
4906
4907                 try_return( ntStatus);
4908             }
4909
4910             //
4911             // Update the target name
4912             //
4913
4914             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
4915                             TRUE);
4916
4917             ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
4918                                             &DirEntry->Flags,
4919                                             (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4920                                             (USHORT)pDirEntry->TargetNameLength);
4921
4922             if( !NT_SUCCESS( ntStatus))
4923             {
4924
4925                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4926                               AFS_TRACE_LEVEL_ERROR,
4927                               "AFSProcessDFSLink UpdateTargetName failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4928                               &DirEntry->NameInformation.FileName,
4929                               DirEntry->ObjectInformation->FileId.Cell,
4930                               DirEntry->ObjectInformation->FileId.Volume,
4931                               DirEntry->ObjectInformation->FileId.Vnode,
4932                               DirEntry->ObjectInformation->FileId.Unique,
4933                               ntStatus));
4934
4935                 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4936
4937                 try_return( ntStatus);
4938             }
4939
4940             AFSConvertToShared( &DirEntry->NonPaged->Lock);
4941         }
4942         else
4943         {
4944             AFSAcquireShared( &DirEntry->NonPaged->Lock,
4945                               TRUE);
4946         }
4947
4948         uniReparseName.MaximumLength = uniMUPDeviceName.Length +
4949                                                    sizeof( WCHAR) +
4950                                                    DirEntry->NameInformation.TargetName.Length +
4951                                                    sizeof( WCHAR);
4952
4953         if( RemainingPath != NULL &&
4954             RemainingPath->Length > 0)
4955         {
4956
4957             uniReparseName.MaximumLength += RemainingPath->Length;
4958         }
4959
4960         //
4961         // Allocate the reparse buffer
4962         //
4963
4964         uniReparseName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4965                                                                    uniReparseName.MaximumLength,
4966                                                                    AFS_REPARSE_NAME_TAG);
4967
4968         if( uniReparseName.Buffer == NULL)
4969         {
4970
4971             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4972                           AFS_TRACE_LEVEL_ERROR,
4973                           "AFSProcessDFSLink uniReparseName.Buffer == NULL Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4974                           &DirEntry->NameInformation.FileName,
4975                           DirEntry->ObjectInformation->FileId.Cell,
4976                           DirEntry->ObjectInformation->FileId.Volume,
4977                           DirEntry->ObjectInformation->FileId.Vnode,
4978                           DirEntry->ObjectInformation->FileId.Unique,
4979                           STATUS_INSUFFICIENT_RESOURCES));
4980
4981             AFSReleaseResource( &DirEntry->NonPaged->Lock);
4982
4983             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4984         }
4985
4986         //
4987         // Start building the name
4988         //
4989
4990         if ( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\' &&
4991              DirEntry->NameInformation.TargetName.Buffer[ 1] == L':')
4992         {
4993
4994             RtlCopyMemory( uniReparseName.Buffer,
4995                            uniIOMgrDeviceName.Buffer,
4996                            uniIOMgrDeviceName.Length);
4997
4998             uniReparseName.Length = uniIOMgrDeviceName.Length;
4999         }
5000         else
5001         {
5002
5003             RtlCopyMemory( uniReparseName.Buffer,
5004                            uniMUPDeviceName.Buffer,
5005                            uniMUPDeviceName.Length);
5006
5007             uniReparseName.Length = uniMUPDeviceName.Length;
5008
5009             if( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\')
5010             {
5011
5012                 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
5013
5014                 uniReparseName.Length += sizeof( WCHAR);
5015             }
5016         }
5017
5018         RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
5019                        DirEntry->NameInformation.TargetName.Buffer,
5020                        DirEntry->NameInformation.TargetName.Length);
5021
5022         uniReparseName.Length += DirEntry->NameInformation.TargetName.Length;
5023
5024         AFSReleaseResource( &DirEntry->NonPaged->Lock);
5025
5026         if( RemainingPath != NULL &&
5027             RemainingPath->Length > 0)
5028         {
5029
5030             if( uniReparseName.Buffer[ (uniReparseName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
5031                 RemainingPath->Buffer[ 0] != L'\\')
5032             {
5033
5034                 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
5035
5036                 uniReparseName.Length += sizeof( WCHAR);
5037             }
5038
5039             RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
5040                            RemainingPath->Buffer,
5041                            RemainingPath->Length);
5042
5043             uniReparseName.Length += RemainingPath->Length;
5044         }
5045
5046         //
5047         // Update the name in the file object
5048         //
5049
5050         if( FileObject->FileName.Buffer != NULL)
5051         {
5052
5053             AFSExFreePoolWithTag( FileObject->FileName.Buffer, 0);
5054         }
5055
5056         FileObject->FileName = uniReparseName;
5057
5058         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5059                       AFS_TRACE_LEVEL_VERBOSE,
5060                       "AFSProcessDFSLink Reparsing access to Fcb %wZ FID %08lX-%08lX-%08lX-%08lX to %wZ\n",
5061                       &DirEntry->NameInformation.FileName,
5062                       DirEntry->ObjectInformation->FileId.Cell,
5063                       DirEntry->ObjectInformation->FileId.Volume,
5064                       DirEntry->ObjectInformation->FileId.Vnode,
5065                       DirEntry->ObjectInformation->FileId.Unique,
5066                       &uniReparseName));
5067
5068         //
5069         // Return status reparse ...
5070         //
5071
5072         ntStatus = STATUS_REPARSE;
5073
5074 try_exit:
5075
5076         if ( pDirEntry)
5077         {
5078
5079             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
5080         }
5081     }
5082
5083     return ntStatus;
5084 }