94d61543b152c7dbb3d2e31cacae21526f318860
[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 **ppDirEntry)
2759 {
2760
2761     LONG lCount;
2762     AFSDirectoryCB *pDirEntry;
2763
2764     __Enter
2765     {
2766
2767         pDirEntry = (AFSDirectoryCB *) InterlockedCompareExchangePointer( (PVOID *)ppDirEntry,
2768                                                                           NULL,
2769                                                                           *ppDirEntry);
2770
2771         if ( pDirEntry == NULL)
2772         {
2773
2774             try_return( NOTHING);
2775         }
2776
2777         AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2778                       AFS_TRACE_LEVEL_VERBOSE,
2779                       "AFSDeletepDirEntry Deleting dir entry in parent %p Entry %p object %p %wZ RefCount %d\n",
2780                       ParentObjectInfo,
2781                       pDirEntry,
2782                       pDirEntry->ObjectInformation,
2783                       &pDirEntry->NameInformation.FileName,
2784                       pDirEntry->DirOpenReferenceCount));
2785
2786         ASSERT( pDirEntry->DirOpenReferenceCount == 0);
2787
2788         AFSRemoveDirNodeFromParent( ParentObjectInfo,
2789                                     pDirEntry,
2790                                     TRUE);
2791
2792         //
2793         // Free up the name buffer if it was reallocated
2794         //
2795
2796         if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2797         {
2798
2799             AFSExFreePoolWithTag( pDirEntry->NameInformation.FileName.Buffer, 0);
2800         }
2801
2802         if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2803         {
2804
2805             AFSExFreePoolWithTag( pDirEntry->NameInformation.TargetName.Buffer, 0);
2806         }
2807
2808         if ( pDirEntry->ObjectInformation != NULL)
2809         {
2810
2811             if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
2812                 pDirEntry->ObjectInformation->Links == 0)
2813             {
2814
2815                 SetFlag( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2816             }
2817
2818             //
2819             // Dereference the object for this dir entry
2820             //
2821
2822             lCount = AFSObjectInfoDecrement( pDirEntry->ObjectInformation,
2823                                              AFS_OBJECT_REFERENCE_DIRENTRY);
2824
2825             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2826                           AFS_TRACE_LEVEL_VERBOSE,
2827                           "AFSDeletepDirEntry Decrement count on object %p Cnt %d\n",
2828                           pDirEntry->ObjectInformation,
2829                           lCount));
2830         }
2831
2832         ExDeleteResourceLite( &pDirEntry->NonPaged->Lock);
2833
2834         AFSExFreePoolWithTag( pDirEntry->NonPaged, AFS_DIR_ENTRY_NP_TAG);
2835
2836         //
2837         // Free up the dir entry
2838         //
2839
2840         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
2841                       AFS_TRACE_LEVEL_VERBOSE,
2842                       "AFSDeletepDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
2843                       pDirEntry));
2844
2845         AFSExFreePoolWithTag( pDirEntry, AFS_DIR_ENTRY_TAG);
2846
2847 try_exit:
2848
2849         NOTHING;
2850     }
2851 }
2852
2853 NTSTATUS
2854 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2855                             IN AFSDirectoryCB *DirEntry,
2856                             IN BOOLEAN RemoveFromEnumList)
2857 {
2858
2859     NTSTATUS ntStatus = STATUS_SUCCESS;
2860     LONG lCount;
2861
2862     __Enter
2863     {
2864
2865
2866         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2867
2868         if ( DirEntry->ObjectInformation != NULL)
2869         {
2870
2871             AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2872                           AFS_TRACE_LEVEL_VERBOSE,
2873                           "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %p\n",
2874                           DirEntry,
2875                           &DirEntry->NameInformation.FileName,
2876                           DirEntry->ObjectInformation->FileId.Cell,
2877                           DirEntry->ObjectInformation->FileId.Volume,
2878                           DirEntry->ObjectInformation->FileId.Vnode,
2879                           DirEntry->ObjectInformation->FileId.Unique,
2880                           ParentObjectInfo));
2881         }
2882         else
2883         {
2884
2885             AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2886                           AFS_TRACE_LEVEL_VERBOSE,
2887                           "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ from Parent %p\n",
2888                           DirEntry,
2889                           &DirEntry->NameInformation.FileName,
2890                           ParentObjectInfo));
2891         }
2892
2893         if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2894         {
2895
2896             AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2897                           AFS_TRACE_LEVEL_VERBOSE,
2898                           "AFSRemoveDirNodeFromParent Removing DirEntry %p name %wZ\n",
2899                           DirEntry,
2900                           &DirEntry->NameInformation.FileName));
2901
2902             AFSRemoveNameEntry( ParentObjectInfo,
2903                                 DirEntry);
2904         }
2905         else
2906         {
2907
2908             AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2909                           AFS_TRACE_LEVEL_VERBOSE,
2910                           "AFSRemoveDirNodeFromParent DE %p for %wZ NOT removing entry due to flag set\n",
2911                           DirEntry,
2912                           &DirEntry->NameInformation.FileName));
2913
2914         }
2915
2916         if( RemoveFromEnumList &&
2917             BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST))
2918         {
2919
2920             //
2921             // And remove the entry from the enumeration list
2922             //
2923
2924             if( DirEntry->ListEntry.fLink == NULL)
2925             {
2926
2927                 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = (AFSDirectoryCB *)DirEntry->ListEntry.bLink;
2928             }
2929             else
2930             {
2931
2932                 ((AFSDirectoryCB *)DirEntry->ListEntry.fLink)->ListEntry.bLink = DirEntry->ListEntry.bLink;
2933             }
2934
2935             if( DirEntry->ListEntry.bLink == NULL)
2936             {
2937
2938                 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = (AFSDirectoryCB *)DirEntry->ListEntry.fLink;
2939             }
2940             else
2941             {
2942
2943                 ((AFSDirectoryCB *)DirEntry->ListEntry.bLink)->ListEntry.fLink = DirEntry->ListEntry.fLink;
2944             }
2945
2946             ASSERT( ParentObjectInfo->Specific.Directory.DirectoryNodeCount > 0);
2947
2948             lCount = InterlockedDecrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2949
2950             ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2951
2952             AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2953                           AFS_TRACE_LEVEL_VERBOSE,
2954                           "AFSRemoveDirNodeFromParent Removing entry %wZ Dec Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2955                           &DirEntry->NameInformation.FileName,
2956                           lCount,
2957                           ParentObjectInfo->FileId.Cell,
2958                           ParentObjectInfo->FileId.Volume,
2959                           ParentObjectInfo->FileId.Vnode,
2960                           ParentObjectInfo->FileId.Unique));
2961
2962             DirEntry->ListEntry.fLink = NULL;
2963             DirEntry->ListEntry.bLink = NULL;
2964         }
2965     }
2966
2967     return ntStatus;
2968 }
2969
2970 NTSTATUS
2971 AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
2972                     IN OUT PUNICODE_STRING TargetFileName)
2973 {
2974
2975     NTSTATUS ntStatus = STATUS_SUCCESS;
2976     UNICODE_STRING uniFileName;
2977
2978     __Enter
2979     {
2980
2981         //
2982         // We will process backwards from the end of the name looking
2983         // for the first \ we encounter
2984         //
2985
2986         uniFileName.Length = FileName->Length;
2987         uniFileName.MaximumLength = FileName->MaximumLength;
2988
2989         uniFileName.Buffer = FileName->Buffer;
2990
2991         while( TRUE)
2992         {
2993
2994             if( uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
2995             {
2996
2997                 //
2998                 // Subtract one more character off of the filename if it is not the root
2999                 //
3000
3001                 if( uniFileName.Length > sizeof( WCHAR))
3002                 {
3003
3004                     uniFileName.Length -= sizeof( WCHAR);
3005                 }
3006
3007                 //
3008                 // Now build up the target name
3009                 //
3010
3011                 TargetFileName->Length = FileName->Length - uniFileName.Length;
3012
3013                 //
3014                 // If we are not on the root then fixup the name
3015                 //
3016
3017                 if( uniFileName.Length > sizeof( WCHAR))
3018                 {
3019
3020                     TargetFileName->Length -= sizeof( WCHAR);
3021
3022                     TargetFileName->Buffer = &uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) + 1];
3023                 }
3024                 else
3025                 {
3026
3027                     TargetFileName->Buffer = &uniFileName.Buffer[ uniFileName.Length/sizeof( WCHAR)];
3028                 }
3029
3030                 //
3031                 // Fixup the passed back filename length
3032                 //
3033
3034                 FileName->Length = uniFileName.Length;
3035
3036                 TargetFileName->MaximumLength = TargetFileName->Length;
3037
3038                 break;
3039             }
3040
3041             uniFileName.Length -= sizeof( WCHAR);
3042         }
3043     }
3044
3045     return ntStatus;
3046 }
3047
3048 NTSTATUS
3049 AFSParseName( IN PIRP Irp,
3050               IN GUID *AuthGroup,
3051               OUT PUNICODE_STRING FileName,
3052               OUT PUNICODE_STRING ParsedFileName,
3053               OUT PUNICODE_STRING RootFileName,
3054               OUT ULONG *ParseFlags,
3055               OUT AFSVolumeCB   **VolumeCB,
3056               OUT AFSDirectoryCB **ParentDirectoryCB,
3057               OUT AFSNameArrayHdr **NameArray)
3058 {
3059
3060     NTSTATUS            ntStatus = STATUS_SUCCESS;
3061     PIO_STACK_LOCATION  pIrpSp = IoGetCurrentIrpStackLocation( Irp);
3062     AFSDeviceExt       *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3063     UNICODE_STRING      uniFullName, uniComponentName, uniRemainingPath;
3064     ULONG               ulCRC = 0;
3065     AFSDirectoryCB     *pDirEntry = NULL;
3066     USHORT              usIndex = 0, usDriveIndex = 0;
3067     AFSCcb             *pRelatedCcb = NULL;
3068     AFSNameArrayHdr    *pNameArray = NULL, *pRelatedNameArray = NULL;
3069     USHORT              usComponentIndex = 0;
3070     USHORT              usComponentLength = 0;
3071     AFSVolumeCB        *pVolumeCB = NULL;
3072     AFSFcb             *pRelatedFcb = NULL;
3073     BOOLEAN             bReleaseTreeLock = FALSE;
3074     BOOLEAN             bIsAllShare = FALSE;
3075     LONG                lCount;
3076
3077     __Enter
3078     {
3079
3080         //
3081         // Indicate we are opening a root ...
3082         //
3083
3084         *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
3085
3086         *ParentDirectoryCB = NULL;
3087
3088         if( pIrpSp->FileObject->RelatedFileObject != NULL)
3089         {
3090
3091             pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
3092
3093             pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
3094
3095             pRelatedNameArray = pRelatedCcb->NameArray;
3096
3097             uniFullName = pIrpSp->FileObject->FileName;
3098
3099             ASSERT( pRelatedFcb != NULL);
3100
3101             //
3102             // No wild cards in the name
3103             //
3104
3105             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3106                           AFS_TRACE_LEVEL_VERBOSE_2,
3107                           "AFSParseName (%p) Relative open for %wZ FID %08lX-%08lX-%08lX-%08lX component %wZ\n",
3108                           Irp,
3109                           &pRelatedCcb->DirectoryCB->NameInformation.FileName,
3110                           pRelatedFcb->ObjectInformation->FileId.Cell,
3111                           pRelatedFcb->ObjectInformation->FileId.Volume,
3112                           pRelatedFcb->ObjectInformation->FileId.Vnode,
3113                           pRelatedFcb->ObjectInformation->FileId.Unique,
3114                           &uniFullName));
3115
3116             if( FsRtlDoesNameContainWildCards( &uniFullName))
3117             {
3118
3119                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3120                               AFS_TRACE_LEVEL_ERROR,
3121                               "AFSParseName (%p) Component %wZ contains wild cards\n",
3122                               Irp,
3123                               &uniFullName));
3124
3125                 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3126             }
3127
3128             pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
3129
3130             pDirEntry = pRelatedCcb->DirectoryCB;
3131
3132             *FileName = pIrpSp->FileObject->FileName;
3133
3134             //
3135             // Grab the root node while checking state
3136             //
3137
3138             AFSAcquireShared( pVolumeCB->VolumeLock,
3139                               TRUE);
3140
3141             if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3142                 BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3143             {
3144
3145                 //
3146                 // The volume has been taken off line so fail the access
3147                 //
3148
3149                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3150                               AFS_TRACE_LEVEL_ERROR,
3151                               "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3152                               Irp,
3153                               pVolumeCB->ObjectInformation.FileId.Cell,
3154                               pVolumeCB->ObjectInformation.FileId.Volume));
3155
3156                 AFSReleaseResource( pVolumeCB->VolumeLock);
3157
3158                 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3159             }
3160
3161             if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3162             {
3163
3164                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3165                               AFS_TRACE_LEVEL_VERBOSE,
3166                               "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
3167                               Irp,
3168                               pVolumeCB->ObjectInformation.FileId.Cell,
3169                               pVolumeCB->ObjectInformation.FileId.Volume));
3170
3171                 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3172                                             pVolumeCB);
3173
3174                 if( !NT_SUCCESS( ntStatus))
3175                 {
3176
3177                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3178                                   AFS_TRACE_LEVEL_ERROR,
3179                                   "AFSParseName (%p) Failed verification of root Status %08lX\n",
3180                                   Irp,
3181                                   ntStatus));
3182
3183                     AFSReleaseResource( pVolumeCB->VolumeLock);
3184
3185                     try_return( ntStatus);
3186                 }
3187             }
3188
3189             AFSReleaseResource( pVolumeCB->VolumeLock);
3190
3191             if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
3192             {
3193
3194                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3195                               AFS_TRACE_LEVEL_VERBOSE,
3196                               "AFSParseName (%p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3197                               Irp,
3198                               &pDirEntry->NameInformation.FileName,
3199                               pDirEntry->ObjectInformation->FileId.Cell,
3200                               pDirEntry->ObjectInformation->FileId.Volume,
3201                               pDirEntry->ObjectInformation->FileId.Vnode,
3202                               pDirEntry->ObjectInformation->FileId.Unique));
3203
3204                 //
3205                 // Directory TreeLock should be exclusively held
3206                 //
3207
3208                 AFSAcquireExcl( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
3209                                 TRUE);
3210
3211                 ntStatus = AFSVerifyEntry( AuthGroup,
3212                                            pDirEntry);
3213
3214                 AFSReleaseResource( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
3215
3216                 if( !NT_SUCCESS( ntStatus))
3217                 {
3218
3219                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3220                                   AFS_TRACE_LEVEL_VERBOSE,
3221                                   "AFSParseName (%p) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3222                                   Irp,
3223                                   &pDirEntry->NameInformation.FileName,
3224                                   pDirEntry->ObjectInformation->FileId.Cell,
3225                                   pDirEntry->ObjectInformation->FileId.Volume,
3226                                   pDirEntry->ObjectInformation->FileId.Vnode,
3227                                   pDirEntry->ObjectInformation->FileId.Unique,
3228                                   ntStatus));
3229
3230                     try_return( ntStatus);
3231                 }
3232             }
3233
3234             //
3235             // Create our full path name buffer
3236             //
3237
3238             uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length +
3239                                                     sizeof( WCHAR) +
3240                                                     pIrpSp->FileObject->FileName.Length +
3241                                                     sizeof( WCHAR);
3242
3243             uniFullName.Length = 0;
3244
3245             uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
3246                                                                     uniFullName.MaximumLength,
3247                                                                     AFS_NAME_BUFFER_THREE_TAG);
3248
3249             if( uniFullName.Buffer == NULL)
3250             {
3251
3252                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3253                               AFS_TRACE_LEVEL_ERROR,
3254                               "AFSParseName (%p) Failed to allocate full name buffer\n",
3255                               Irp));
3256
3257                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3258             }
3259
3260             RtlZeroMemory( uniFullName.Buffer,
3261                            uniFullName.MaximumLength);
3262
3263             RtlCopyMemory( uniFullName.Buffer,
3264                            pRelatedCcb->FullFileName.Buffer,
3265                            pRelatedCcb->FullFileName.Length);
3266
3267             uniFullName.Length = pRelatedCcb->FullFileName.Length;
3268
3269             usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
3270
3271             usComponentLength = pIrpSp->FileObject->FileName.Length;
3272
3273             if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
3274                 pIrpSp->FileObject->FileName.Length > 0 &&
3275                 pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
3276                 pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
3277             {
3278
3279                 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
3280
3281                 uniFullName.Length += sizeof( WCHAR);
3282
3283                 usComponentLength += sizeof( WCHAR);
3284             }
3285
3286             if( pIrpSp->FileObject->FileName.Length > 0)
3287             {
3288
3289                 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
3290                                pIrpSp->FileObject->FileName.Buffer,
3291                                pIrpSp->FileObject->FileName.Length);
3292
3293                 uniFullName.Length += pIrpSp->FileObject->FileName.Length;
3294             }
3295
3296             *RootFileName = uniFullName;
3297
3298             //
3299             // We populate up to the current parent
3300             //
3301
3302             if( pRelatedNameArray == NULL)
3303             {
3304
3305                 //
3306                 // Init and populate our name array
3307                 //
3308
3309                 pNameArray = AFSInitNameArray( NULL,
3310                                                0);
3311
3312                 if( pNameArray == NULL)
3313                 {
3314
3315                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3316                                   AFS_TRACE_LEVEL_VERBOSE,
3317                                   "AFSParseName (%p) Failed to initialize name array\n",
3318                                   Irp));
3319
3320                     AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3321
3322                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3323                 }
3324
3325                 ntStatus = AFSPopulateNameArray( pNameArray,
3326                                                  NULL,
3327                                                  pRelatedCcb->DirectoryCB);
3328             }
3329             else
3330             {
3331
3332                 //
3333                 // Init and populate our name array
3334                 //
3335
3336                 pNameArray = AFSInitNameArray( NULL,
3337                                                pRelatedNameArray->MaxElementCount);
3338
3339                 if( pNameArray == NULL)
3340                 {
3341
3342                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3343                                   AFS_TRACE_LEVEL_VERBOSE,
3344                                   "AFSParseName (%p) Failed to initialize name array\n",
3345                                   Irp));
3346
3347                     AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3348
3349                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3350                 }
3351
3352                 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
3353                                                                  pRelatedNameArray,
3354                                                                  pRelatedCcb->DirectoryCB);
3355             }
3356
3357             if( !NT_SUCCESS( ntStatus))
3358             {
3359
3360                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3361                               AFS_TRACE_LEVEL_VERBOSE,
3362                               "AFSParseName (%p) Failed to populate name array\n",
3363                               Irp));
3364
3365                 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3366
3367                 try_return( ntStatus);
3368             }
3369
3370             ParsedFileName->Length = usComponentLength;
3371             ParsedFileName->MaximumLength = uniFullName.MaximumLength;
3372
3373             ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
3374
3375             //
3376             // Indicate to caller that RootFileName must be freed
3377             //
3378
3379             SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
3380
3381             *NameArray = pNameArray;
3382
3383             //
3384             // Increment our volume reference count
3385             //
3386
3387             lCount = AFSVolumeIncrement( pVolumeCB,
3388                                          AFS_VOLUME_REFERENCE_PARSE_NAME);
3389
3390             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3391                           AFS_TRACE_LEVEL_VERBOSE,
3392                           "AFSParseName Increment count on volume %p Cnt %d\n",
3393                           pVolumeCB,
3394                           lCount));
3395
3396             *VolumeCB = pVolumeCB;
3397
3398             *ParentDirectoryCB = pDirEntry;
3399
3400             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3401                           AFS_TRACE_LEVEL_VERBOSE_2,
3402                           "AFSParseName (%p) Returning full name %wZ\n",
3403                           Irp,
3404                           &uniFullName));
3405
3406             try_return( ntStatus);
3407         }
3408
3409         //
3410         // No wild cards in the name
3411         //
3412
3413         uniFullName = pIrpSp->FileObject->FileName;
3414
3415         if( FsRtlDoesNameContainWildCards( &uniFullName) ||
3416             uniFullName.Length < AFSServerName.Length)
3417         {
3418
3419             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3420                           AFS_TRACE_LEVEL_ERROR,
3421                           "AFSParseName (%p) Name %wZ contains wild cards or too short\n",
3422                           Irp,
3423                           &uniFullName));
3424
3425             try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3426         }
3427
3428         //
3429         // The name is a fully qualified name. Parse out the server/share names and
3430         // point to the root qualified name
3431         // First thing is to locate the server name
3432         //
3433
3434         FsRtlDissectName( uniFullName,
3435                           &uniComponentName,
3436                           &uniRemainingPath);
3437
3438         uniFullName = uniRemainingPath;
3439
3440         //
3441         // This component is the server name we are serving
3442         //
3443
3444         if( RtlCompareUnicodeString( &uniComponentName,
3445                                      &AFSServerName,
3446                                      TRUE) != 0)
3447         {
3448
3449             //
3450             // Drive letter based name?
3451             //
3452
3453             uniFullName = pIrpSp->FileObject->FileName;
3454
3455             while( usIndex < uniFullName.Length/sizeof( WCHAR))
3456             {
3457
3458                 if( uniFullName.Buffer[ usIndex] == L':')
3459                 {
3460
3461                     uniFullName.Buffer = &uniFullName.Buffer[ usIndex + 2];
3462
3463                     uniFullName.Length -= (usIndex + 2) * sizeof( WCHAR);
3464
3465                     usDriveIndex = usIndex - 1;
3466
3467                     break;
3468                 }
3469
3470                 usIndex++;
3471             }
3472
3473             //
3474             // Do we have the right server name now?
3475             //
3476
3477             FsRtlDissectName( uniFullName,
3478                               &uniComponentName,
3479                               &uniRemainingPath);
3480
3481             uniFullName = uniRemainingPath;
3482
3483             //
3484             // This component is the server name we are serving
3485             //
3486
3487             if( RtlCompareUnicodeString( &uniComponentName,
3488                                          &AFSServerName,
3489                                          TRUE) != 0)
3490             {
3491
3492                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3493                               AFS_TRACE_LEVEL_ERROR,
3494                               "AFSParseName (%p) Name %wZ does not have server name\n",
3495                               Irp,
3496                               &pIrpSp->FileObject->FileName));
3497
3498                 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3499             }
3500
3501             //
3502             // Validate this drive letter is actively mapped
3503             //
3504
3505             if( usDriveIndex > 0 &&
3506                 !AFSIsDriveMapped( pIrpSp->FileObject->FileName.Buffer[ usDriveIndex]))
3507             {
3508
3509                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3510                               AFS_TRACE_LEVEL_ERROR,
3511                               "AFSParseName (%p) Name %wZ contains invalid drive mapping\n",
3512                               Irp,
3513                               &pIrpSp->FileObject->FileName));
3514
3515                 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3516             }
3517         }
3518
3519         if( FsRtlDoesNameContainWildCards( &uniFullName))
3520         {
3521
3522             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3523                           AFS_TRACE_LEVEL_ERROR,
3524                           "AFSParseName (%p) Component %wZ contains wild cards\n",
3525                           Irp,
3526                           &uniFullName));
3527
3528             try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3529         }
3530
3531         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3532                       AFS_TRACE_LEVEL_VERBOSE_2,
3533                       "AFSParseName (%p) Processing full name %wZ\n",
3534                       Irp,
3535                       &uniFullName));
3536
3537         if( uniFullName.Length > 0 &&
3538             uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] == L'\\')
3539         {
3540
3541             uniFullName.Length -= sizeof( WCHAR);
3542         }
3543
3544         //
3545         // Be sure we are online and ready to go
3546         //
3547
3548         AFSAcquireShared( AFSGlobalRoot->VolumeLock,
3549                           TRUE);
3550
3551         if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3552             BooleanFlagOn( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3553         {
3554
3555             //
3556             // The volume has been taken off line so fail the access
3557             //
3558
3559             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3560                           AFS_TRACE_LEVEL_ERROR,
3561                           "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3562                           Irp,
3563                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3564                           AFSGlobalRoot->ObjectInformation.FileId.Volume));
3565
3566             AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3567
3568             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3569         }
3570
3571         if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3572         {
3573
3574             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3575                           AFS_TRACE_LEVEL_VERBOSE,
3576                           "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
3577                           Irp,
3578                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3579                           AFSGlobalRoot->ObjectInformation.FileId.Volume));
3580
3581             ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3582                                         AFSGlobalRoot);
3583
3584             if( !NT_SUCCESS( ntStatus))
3585             {
3586
3587                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3588                               AFS_TRACE_LEVEL_ERROR,
3589                               "AFSParseName (%p) Failed verification of root Status %08lX\n",
3590                               Irp,
3591                               ntStatus));
3592
3593                 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3594
3595                 try_return( ntStatus);
3596             }
3597         }
3598
3599         AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3600
3601         if( !BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3602         {
3603
3604             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3605                           AFS_TRACE_LEVEL_VERBOSE,
3606                           "AFSParseName (%p) Enumerating global root of volume %08lX:%08lX\n",
3607                           Irp,
3608                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3609                           AFSGlobalRoot->ObjectInformation.FileId.Volume));
3610
3611             ntStatus = AFSEnumerateGlobalRoot( AuthGroup);
3612
3613             if( !NT_SUCCESS( ntStatus))
3614             {
3615
3616                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3617                               AFS_TRACE_LEVEL_ERROR,
3618                               "AFSParseName (%p) Failed enumeraiton of root Status %08lX\n",
3619                               Irp,
3620                               ntStatus));
3621
3622                 try_return( ntStatus);
3623             }
3624         }
3625
3626         //
3627         // Check for the \\Server access and return it as though it were \\Server\Globalroot
3628         //
3629
3630         if( uniRemainingPath.Buffer == NULL ||
3631             ( uniRemainingPath.Length == sizeof( WCHAR) &&
3632               uniRemainingPath.Buffer[ 0] == L'\\'))
3633         {
3634
3635             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3636                           AFS_TRACE_LEVEL_VERBOSE_2,
3637                           "AFSParseName (%p) Returning global root access\n",
3638                           Irp));
3639
3640             lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3641
3642             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3643                           AFS_TRACE_LEVEL_VERBOSE,
3644                           "AFSParseName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3645                           &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3646                           AFSGlobalRoot->DirectoryCB,
3647                           NULL,
3648                           lCount));
3649
3650             *VolumeCB = NULL;
3651
3652             FileName->Length = 0;
3653             FileName->MaximumLength = 0;
3654             FileName->Buffer = NULL;
3655
3656             try_return( ntStatus = STATUS_SUCCESS);
3657         }
3658
3659         *RootFileName = uniFullName;
3660
3661         //
3662         // Include the starting \ in the root name
3663         //
3664
3665         if( RootFileName->Buffer[ 0] != L'\\')
3666         {
3667             RootFileName->Buffer--;
3668             RootFileName->Length += sizeof( WCHAR);
3669             RootFileName->MaximumLength += sizeof( WCHAR);
3670         }
3671
3672         //
3673         // Get the 'share' name
3674         //
3675
3676         FsRtlDissectName( uniFullName,
3677                           &uniComponentName,
3678                           &uniRemainingPath);
3679
3680         if( FsRtlDoesNameContainWildCards( &uniFullName))
3681         {
3682
3683             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3684                           AFS_TRACE_LEVEL_ERROR,
3685                           "AFSParseName (%p) Component %wZ contains wild cards\n",
3686                           Irp,
3687                           &uniComponentName));
3688
3689             try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3690         }
3691
3692         //
3693         // If this is the ALL access then perform some additional processing
3694         //
3695
3696         if( uniComponentName.Length == 0 ||
3697             RtlCompareUnicodeString( &uniComponentName,
3698                                      &AFSGlobalRootName,
3699                                      TRUE) == 0)
3700         {
3701
3702             bIsAllShare = TRUE;
3703
3704             //
3705             // If there is nothing else then get out
3706             //
3707
3708             if( uniRemainingPath.Buffer == NULL ||
3709                 uniRemainingPath.Length == 0 ||
3710                 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3711                   uniRemainingPath.Buffer[ 0] == L'\\'))
3712             {
3713
3714                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3715                               AFS_TRACE_LEVEL_VERBOSE_2,
3716                               "AFSParseName (%p) Returning global root access\n",
3717                               Irp));
3718
3719                 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3720
3721                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3722                               AFS_TRACE_LEVEL_VERBOSE,
3723                               "AFSParseName Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
3724                               &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3725                               AFSGlobalRoot->DirectoryCB,
3726                               NULL,
3727                               lCount));
3728
3729                 *VolumeCB = NULL;
3730
3731                 FileName->Length = 0;
3732                 FileName->MaximumLength = 0;
3733                 FileName->Buffer = NULL;
3734
3735                 try_return( ntStatus = STATUS_SUCCESS);
3736             }
3737
3738             //
3739             // Process the name again to strip off the ALL portion
3740             //
3741
3742             uniFullName = uniRemainingPath;
3743
3744             FsRtlDissectName( uniFullName,
3745                               &uniComponentName,
3746                               &uniRemainingPath);
3747
3748             //
3749             // Check for the PIOCtl name
3750             //
3751
3752             if( RtlCompareUnicodeString( &uniComponentName,
3753                                          &AFSPIOCtlName,
3754                                          TRUE) == 0)
3755             {
3756
3757                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3758                               AFS_TRACE_LEVEL_VERBOSE_2,
3759                               "AFSParseName (%p) Returning root PIOCtl access\n",
3760                               Irp));
3761
3762                 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3763
3764                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3765                               AFS_TRACE_LEVEL_VERBOSE,
3766                               "AFSParseName Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
3767                               &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3768                               AFSGlobalRoot->DirectoryCB,
3769                               NULL,
3770                               lCount));
3771
3772                 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3773
3774                 *VolumeCB = NULL;
3775
3776                 *FileName = AFSPIOCtlName;
3777
3778                 try_return( ntStatus = STATUS_SUCCESS);
3779             }
3780         }
3781         else if( (pDirEntry = AFSGetSpecialShareNameEntry( &uniComponentName,
3782                                                            &uniRemainingPath)) != NULL)
3783         {
3784
3785             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3786                           AFS_TRACE_LEVEL_VERBOSE_2,
3787                           "AFSParseName (%p) Returning root share name %wZ access\n",
3788                           Irp,
3789                           &uniComponentName));
3790
3791             //
3792             // Add in the full share name to pass back
3793             //
3794
3795             if( uniRemainingPath.Buffer != NULL)
3796             {
3797
3798                 //
3799                 // This routine strips off the leading slash so add it back in
3800                 //
3801
3802                 uniRemainingPath.Buffer--;
3803                 uniRemainingPath.Length += sizeof( WCHAR);
3804                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3805
3806                 //
3807                 // And the cell name
3808                 //
3809
3810                 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3811                 uniRemainingPath.Length += uniComponentName.Length;
3812                 uniRemainingPath.MaximumLength += uniComponentName.Length;
3813
3814                 uniComponentName = uniRemainingPath;
3815             }
3816
3817             *VolumeCB = NULL;
3818
3819             *FileName = uniComponentName;
3820
3821             ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3822
3823             *ParentDirectoryCB = pDirEntry;
3824
3825             try_return( ntStatus = STATUS_SUCCESS);
3826         }
3827
3828         //
3829         // Determine the 'share' we are accessing
3830         //
3831
3832         ulCRC = AFSGenerateCRC( &uniComponentName,
3833                                 FALSE);
3834
3835         AFSAcquireShared( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3836                           TRUE);
3837
3838         bReleaseTreeLock = TRUE;
3839
3840         AFSLocateCaseSensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
3841                                         ulCRC,
3842                                         &pDirEntry);
3843
3844         if( pDirEntry == NULL)
3845         {
3846
3847             ulCRC = AFSGenerateCRC( &uniComponentName,
3848                                     TRUE);
3849
3850             AFSLocateCaseInsensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
3851                                               ulCRC,
3852                                               &pDirEntry);
3853
3854             if( pDirEntry == NULL)
3855             {
3856
3857                 //
3858                 // OK, if this component is a valid short name then try
3859                 // a lookup in the short name tree
3860                 //
3861
3862                 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3863                     RtlIsNameLegalDOS8Dot3( &uniComponentName,
3864                                             NULL,
3865                                             NULL))
3866                 {
3867
3868                     AFSLocateShortNameDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.ShortNameTree,
3869                                                 ulCRC,
3870                                                 &pDirEntry);
3871                 }
3872
3873                 if( pDirEntry == NULL)
3874                 {
3875
3876                     //
3877                     // Check with the service whether it is a valid cell name
3878                     //
3879
3880                     AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3881
3882                     bReleaseTreeLock = FALSE;
3883
3884                     ntStatus = AFSCheckCellName( AuthGroup,
3885                                                  &uniComponentName,
3886                                                  &pDirEntry);
3887
3888                     if( !NT_SUCCESS( ntStatus))
3889                     {
3890
3891                         if ( bIsAllShare &&
3892                              uniRemainingPath.Length == 0 &&
3893                              ntStatus == STATUS_OBJECT_PATH_NOT_FOUND)
3894                         {
3895
3896                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3897                                           AFS_TRACE_LEVEL_VERBOSE,
3898                                           "AFSParseName (%p) AFSCheckCellName %wZ returned path not found; ntStatus %08X\n",
3899                                           Irp,
3900                                           &uniComponentName,
3901                                           STATUS_OBJECT_NAME_NOT_FOUND));
3902
3903                             ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
3904                         }
3905
3906                         try_return( ntStatus);
3907                     }
3908                 }
3909             }
3910         }
3911
3912         if( bReleaseTreeLock)
3913         {
3914             AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3915         }
3916
3917
3918         //
3919         // Be sure we are starting from the correct volume
3920         //
3921
3922         if( pDirEntry->ObjectInformation->VolumeCB != AFSGlobalRoot)
3923         {
3924
3925             //
3926             // We dropped the global root in the CheckCellName routine which is the
3927             // only way we can be here
3928             //
3929
3930             pVolumeCB = pDirEntry->ObjectInformation->VolumeCB;
3931
3932             //
3933             // Init our name array
3934             //
3935
3936             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
3937                                            0);
3938
3939             if( pNameArray == NULL)
3940             {
3941
3942                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3943                               AFS_TRACE_LEVEL_VERBOSE,
3944                               "AFSParseName (%p) Failed to initialize name array\n",
3945                               Irp));
3946
3947                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3948             }
3949
3950             ntStatus = AFSInsertNextElement( pNameArray,
3951                                              pVolumeCB->DirectoryCB);
3952
3953             if ( ntStatus)
3954             {
3955
3956                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3957                               AFS_TRACE_LEVEL_VERBOSE,
3958                               "AFSParseName (%p) Failed to insert name array element\n",
3959                               Irp));
3960
3961                 try_return( ntStatus);
3962             }
3963
3964             //
3965             // In this case don't add back in the 'share' name since that is where we are
3966             // starting. Just put the leading slash back in
3967             //
3968
3969             if( uniRemainingPath.Buffer != NULL)
3970             {
3971
3972                 uniRemainingPath.Buffer--;
3973                 uniRemainingPath.Length += sizeof( WCHAR);
3974                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3975
3976                 if( uniRemainingPath.Length > sizeof( WCHAR))
3977                 {
3978
3979                     ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3980                 }
3981
3982                 //
3983                 // Pass back the parent being the root of the volume
3984                 //
3985
3986                 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3987             }
3988             else
3989             {
3990
3991                 //
3992                 // Pass back a root slash
3993                 //
3994
3995                 uniRemainingPath = uniComponentName;
3996
3997                 uniRemainingPath.Buffer--;
3998                 uniRemainingPath.Length = sizeof( WCHAR);
3999                 uniRemainingPath.MaximumLength = sizeof( WCHAR);
4000
4001                 //
4002                 // This is a root open so pass back no parent
4003                 //
4004             }
4005         }
4006         else
4007         {
4008
4009             pVolumeCB = AFSGlobalRoot;
4010
4011             //
4012             // Init our name array
4013             //
4014
4015             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
4016                                            0);
4017             if( pNameArray == NULL)
4018             {
4019
4020                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4021                               AFS_TRACE_LEVEL_VERBOSE,
4022                               "AFSParseName (%p) Failed to initialize name array\n",
4023                               Irp));
4024
4025                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4026             }
4027
4028             //
4029             // Add back in the 'share' portion of the name since we will parse it out on return
4030             //
4031
4032             if( uniRemainingPath.Buffer != NULL)
4033             {
4034
4035                 //
4036                 // This routine strips off the leading slash so add it back in
4037                 //
4038
4039                 uniRemainingPath.Buffer--;
4040                 uniRemainingPath.Length += sizeof( WCHAR);
4041                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
4042
4043                 if( uniRemainingPath.Length > sizeof( WCHAR))
4044                 {
4045
4046                     ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
4047                 }
4048
4049                 //
4050                 // And the cell name
4051                 //
4052
4053                 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
4054                 uniRemainingPath.Length += uniComponentName.Length;
4055                 uniRemainingPath.MaximumLength += uniComponentName.Length;
4056             }
4057             else
4058             {
4059
4060                 uniRemainingPath = uniComponentName;
4061             }
4062
4063             //
4064             // And the leading slash again ...
4065             //
4066
4067             uniRemainingPath.Buffer--;
4068             uniRemainingPath.Length += sizeof( WCHAR);
4069             uniRemainingPath.MaximumLength += sizeof( WCHAR);
4070
4071             //
4072             // Pass back the parent being the volume root
4073             //
4074
4075             *ParentDirectoryCB = pVolumeCB->DirectoryCB;
4076         }
4077
4078         //
4079         // Return the remaining portion as the file name
4080         //
4081
4082         *FileName = uniRemainingPath;
4083
4084         *ParsedFileName = uniRemainingPath;
4085
4086         *NameArray = pNameArray;
4087
4088         *VolumeCB = pVolumeCB;
4089
4090         //
4091         // Increment our reference on the volume
4092         //
4093
4094         lCount = AFSVolumeIncrement( pVolumeCB,
4095                                      AFS_VOLUME_REFERENCE_PARSE_NAME);
4096
4097         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4098                       AFS_TRACE_LEVEL_VERBOSE,
4099                       "AFSParseName Increment2 count on global volume %p Cnt %d\n",
4100                       pVolumeCB,
4101                       lCount));
4102
4103 try_exit:
4104
4105         if( NT_SUCCESS( ntStatus))
4106         {
4107
4108             if( *ParentDirectoryCB != NULL)
4109             {
4110
4111                 lCount = InterlockedIncrement( &(*ParentDirectoryCB)->DirOpenReferenceCount);
4112
4113                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4114                               AFS_TRACE_LEVEL_VERBOSE,
4115                               "AFSParseName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4116                               &(*ParentDirectoryCB)->NameInformation.FileName,
4117                               (*ParentDirectoryCB),
4118                               NULL,
4119                               lCount));
4120             }
4121         }
4122
4123         if( *VolumeCB != NULL)
4124         {
4125             ASSERT( (*VolumeCB)->VolumeReferenceCount > 0);
4126         }
4127
4128         if( ntStatus != STATUS_SUCCESS)
4129         {
4130
4131             if( pNameArray != NULL)
4132             {
4133
4134                 AFSFreeNameArray( pNameArray);
4135             }
4136         }
4137     }
4138
4139     return ntStatus;
4140 }
4141
4142 NTSTATUS
4143 AFSCheckCellName( IN GUID *AuthGroup,
4144                   IN UNICODE_STRING *CellName,
4145                   OUT AFSDirectoryCB **ShareDirEntry)
4146 {
4147
4148     NTSTATUS ntStatus = STATUS_SUCCESS;
4149     UNICODE_STRING uniName;
4150     AFSDirEnumEntry *pDirEnumEntry = NULL;
4151     AFSDirHdr *pDirHdr = &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr;
4152     AFSDirectoryCB *pDirNode = NULL;
4153     UNICODE_STRING uniDirName, uniTargetName;
4154     AFSVolumeCB *pVolumeCB = NULL;
4155     LONG lCount;
4156
4157     __Enter
4158     {
4159
4160         //
4161         // Look for some default names we will not handle
4162         //
4163
4164         RtlInitUnicodeString( &uniName,
4165                               L"IPC$");
4166
4167         if( RtlCompareUnicodeString( &uniName,
4168                                      CellName,
4169                                      TRUE) == 0)
4170         {
4171
4172             try_return( ntStatus = STATUS_NO_SUCH_FILE);
4173         }
4174
4175         RtlInitUnicodeString( &uniName,
4176                               L"wkssvc");
4177
4178         if( RtlCompareUnicodeString( &uniName,
4179                                      CellName,
4180                                      TRUE) == 0)
4181         {
4182
4183             try_return( ntStatus = STATUS_NO_SUCH_FILE);
4184         }
4185
4186         RtlInitUnicodeString( &uniName,
4187                               L"srvsvc");
4188
4189         if( RtlCompareUnicodeString( &uniName,
4190                                      CellName,
4191                                      TRUE) == 0)
4192         {
4193
4194             try_return( ntStatus = STATUS_NO_SUCH_FILE);
4195         }
4196
4197         RtlInitUnicodeString( &uniName,
4198                               L"PIPE");
4199
4200         if( RtlCompareUnicodeString( &uniName,
4201                                      CellName,
4202                                      TRUE) == 0)
4203         {
4204
4205             try_return( ntStatus = STATUS_NO_SUCH_FILE);
4206         }
4207
4208         //
4209         // OK, ask the CM about this component name
4210         //
4211
4212         ntStatus = AFSEvaluateTargetByName( AuthGroup,
4213                                             &AFSGlobalRoot->ObjectInformation,
4214                                             CellName,
4215                                             0,
4216                                             &pDirEnumEntry);
4217
4218         if( !NT_SUCCESS( ntStatus))
4219         {
4220
4221             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4222                           AFS_TRACE_LEVEL_WARNING,
4223                           "AFSCheckCellName entry %wZ does not exist parent FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4224                           CellName,
4225                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
4226                           AFSGlobalRoot->ObjectInformation.FileId.Volume,
4227                           AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4228                           AFSGlobalRoot->ObjectInformation.FileId.Unique,
4229                           ntStatus));
4230
4231             try_return( ntStatus);
4232         }
4233
4234         //
4235         // OK, we have a dir enum entry back so add it to the root node
4236         //
4237
4238         uniDirName = *CellName;
4239
4240         uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
4241         uniTargetName.MaximumLength = uniTargetName.Length;
4242         uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
4243
4244         //
4245         // Is this entry a root volume entry?
4246         //
4247
4248         if( pDirEnumEntry->FileId.Cell != AFSGlobalRoot->ObjectInformation.FileId.Cell ||
4249             pDirEnumEntry->FileId.Volume != AFSGlobalRoot->ObjectInformation.FileId.Volume)
4250         {
4251
4252             //
4253             // Build the root volume entry
4254             //
4255
4256             ntStatus = AFSBuildRootVolume( AuthGroup,
4257                                            &pDirEnumEntry->FileId,
4258                                            &pVolumeCB);
4259
4260             //
4261             // On success returns with a volume reference count held
4262             //
4263
4264             if( !NT_SUCCESS( ntStatus))
4265             {
4266                 try_return( ntStatus);
4267             }
4268
4269             *ShareDirEntry = pVolumeCB->DirectoryCB;
4270
4271             lCount = InterlockedIncrement( &pVolumeCB->DirectoryCB->DirOpenReferenceCount);
4272
4273             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4274                           AFS_TRACE_LEVEL_VERBOSE,
4275                           "AFSCheckCellName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4276                           &pVolumeCB->DirectoryCB->NameInformation.FileName,
4277                           pVolumeCB->DirectoryCB,
4278                           NULL,
4279                           lCount));
4280
4281             lCount = AFSVolumeDecrement( pVolumeCB,
4282                                          AFS_VOLUME_REFERENCE_BUILD_ROOT);
4283
4284             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4285                           AFS_TRACE_LEVEL_VERBOSE,
4286                           "AFSCheckCellName Decrement count on volume %p Cnt %d\n",
4287                           pVolumeCB,
4288                           lCount));
4289         }
4290         else
4291         {
4292
4293             lCount = InterlockedIncrement( &pDirHdr->ContentIndex);
4294
4295             pDirNode = AFSInitDirEntry( &AFSGlobalRoot->ObjectInformation,
4296                                         &uniDirName,
4297                                         &uniTargetName,
4298                                         pDirEnumEntry,
4299                                         (ULONG)lCount);
4300
4301             if( pDirNode == NULL)
4302             {
4303
4304                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4305             }
4306
4307             //
4308             // Init the short name if we have one
4309             //
4310
4311             if( pDirEnumEntry->ShortNameLength > 0)
4312             {
4313
4314                 pDirNode->NameInformation.ShortNameLength = pDirEnumEntry->ShortNameLength;
4315
4316                 RtlCopyMemory( pDirNode->NameInformation.ShortName,
4317                                pDirEnumEntry->ShortName,
4318                                pDirNode->NameInformation.ShortNameLength);
4319             }
4320
4321             AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4322                             TRUE);
4323
4324             //
4325             // Insert the node into the name tree
4326             //
4327
4328             ASSERT( ExIsResourceAcquiredExclusiveLite( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock));
4329
4330             if( pDirHdr->CaseSensitiveTreeHead == NULL)
4331             {
4332
4333                 pDirHdr->CaseSensitiveTreeHead = pDirNode;
4334             }
4335             else
4336             {
4337
4338                 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( pDirHdr->CaseSensitiveTreeHead,
4339                                                                  pDirNode)))
4340                 {
4341
4342                     AFSDeleteDirEntry( &AFSGlobalRoot->ObjectInformation,
4343                                        &pDirNode);
4344
4345                     AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4346
4347                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4348                 }
4349             }
4350
4351             ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
4352
4353             if( pDirHdr->CaseInsensitiveTreeHead == NULL)
4354             {
4355
4356                 pDirHdr->CaseInsensitiveTreeHead = pDirNode;
4357
4358                 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
4359             }
4360             else
4361             {
4362
4363                 AFSInsertCaseInsensitiveDirEntry( pDirHdr->CaseInsensitiveTreeHead,
4364                                                   pDirNode);
4365             }
4366
4367             if( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead == NULL)
4368             {
4369
4370                 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead = pDirNode;
4371             }
4372             else
4373             {
4374
4375                 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
4376
4377                 pDirNode->ListEntry.bLink = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail;
4378             }
4379
4380             AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail = pDirNode;
4381
4382             SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
4383
4384             lCount = InterlockedIncrement( &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeCount);
4385
4386             AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
4387                           AFS_TRACE_LEVEL_VERBOSE,
4388                           "AFSCheckCellName Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
4389                           &pDirNode->NameInformation.FileName,
4390                           lCount,
4391                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
4392                           AFSGlobalRoot->ObjectInformation.FileId.Volume,
4393                           AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4394                           AFSGlobalRoot->ObjectInformation.FileId.Unique));
4395
4396             lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
4397
4398             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4399                           AFS_TRACE_LEVEL_VERBOSE,
4400                           "AFSCheckCellName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
4401                           &pDirNode->NameInformation.FileName,
4402                           pDirNode,
4403                           NULL,
4404                           lCount));
4405
4406             AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4407
4408             //
4409             // Pass back the dir node
4410             //
4411
4412             *ShareDirEntry = pDirNode;
4413         }
4414
4415 try_exit:
4416
4417         if( pDirEnumEntry != NULL)
4418         {
4419
4420             AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_31_TAG);
4421         }
4422     }
4423
4424     return ntStatus;
4425 }
4426
4427 NTSTATUS
4428 AFSBuildMountPointTarget( IN GUID *AuthGroup,
4429                           IN AFSDirectoryCB  *DirectoryCB,
4430                           OUT AFSVolumeCB **TargetVolumeCB)
4431 {
4432
4433     NTSTATUS ntStatus = STATUS_SUCCESS;
4434     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4435     AFSDirEnumEntry *pDirEntry = NULL;
4436     ULONGLONG       ullIndex = 0;
4437     AFSVolumeCB *pVolumeCB = NULL;
4438     AFSFileID stTargetFileID;
4439     LONG lCount;
4440     BOOLEAN bReleaseVolumeLock = FALSE;
4441
4442     __Enter
4443     {
4444
4445         //
4446         // Loop on each entry, building the chain until we encounter the final target
4447         //
4448
4449         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4450                       AFS_TRACE_LEVEL_VERBOSE_2,
4451                       "AFSBuildMountPointTarget Building target directory for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4452                       &DirectoryCB->NameInformation.FileName,
4453                       DirectoryCB->ObjectInformation->FileId.Cell,
4454                       DirectoryCB->ObjectInformation->FileId.Volume,
4455                       DirectoryCB->ObjectInformation->FileId.Vnode,
4456                       DirectoryCB->ObjectInformation->FileId.Unique));
4457
4458         //
4459         // Do we need to evaluate the node?
4460         //
4461
4462         //if( DirectoryCB->ObjectInformation->TargetFileId.Vnode == 0 &&
4463         //    DirectoryCB->ObjectInformation->TargetFileId.Unique == 0)
4464         {
4465
4466             //
4467             // Go evaluate the current target to get the target fid
4468             //
4469
4470             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4471                           AFS_TRACE_LEVEL_VERBOSE_2,
4472                           "AFSBuildMountPointTarget Evaluating target %wZ FID %08lX-%08lX-%08lX-%08lX\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             ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
4480                                               AuthGroup,
4481                                               FALSE,
4482                                               &pDirEntry);
4483
4484             if( !NT_SUCCESS( ntStatus))
4485             {
4486
4487                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4488                               AFS_TRACE_LEVEL_ERROR,
4489                               "AFSBuildMountPointTarget Failed to evaluate target %wZ Status %08lX\n",
4490                               &DirectoryCB->NameInformation.FileName,
4491                               ntStatus));
4492
4493                 try_return( ntStatus);
4494             }
4495
4496             if( pDirEntry->TargetFileId.Vnode == 0 &&
4497                 pDirEntry->TargetFileId.Unique == 0)
4498             {
4499
4500                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4501                               AFS_TRACE_LEVEL_ERROR,
4502                               "AFSBuildMountPointTarget Target %wZ FID %08lX-%08lX-%08lX-%08lX service returned zero FID\n",
4503                               &DirectoryCB->NameInformation.FileName,
4504                               DirectoryCB->ObjectInformation->FileId.Cell,
4505                               DirectoryCB->ObjectInformation->FileId.Volume,
4506                               DirectoryCB->ObjectInformation->FileId.Vnode,
4507                               DirectoryCB->ObjectInformation->FileId.Unique));
4508
4509                 try_return( ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED);
4510             }
4511
4512             AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
4513                             TRUE);
4514
4515             ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
4516                                             &DirectoryCB->Flags,
4517                                             (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4518                                             (USHORT)pDirEntry->TargetNameLength);
4519
4520             if( !NT_SUCCESS( ntStatus))
4521             {
4522
4523                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4524
4525                 try_return( ntStatus);
4526             }
4527
4528             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4529
4530             DirectoryCB->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
4531         }
4532
4533         stTargetFileID = DirectoryCB->ObjectInformation->TargetFileId;
4534
4535         //
4536         // Try to locate this FID. First the volume then the
4537         // entry itself
4538         //
4539
4540         ullIndex = AFSCreateHighIndex( &stTargetFileID);
4541
4542         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4543                       AFS_TRACE_LEVEL_VERBOSE,
4544                       "AFSBuildMountPointTarget Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4545                       &pDevExt->Specific.RDR.VolumeTreeLock,
4546                       PsGetCurrentThread()));
4547
4548         AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4549                           TRUE);
4550
4551         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4552                       AFS_TRACE_LEVEL_VERBOSE_2,
4553                       "AFSBuildMountPointTarget Locating volume for target %I64X\n",
4554                       ullIndex));
4555
4556         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4557                                        ullIndex,
4558                                        (AFSBTreeEntry **)&pVolumeCB);
4559
4560         //
4561         // We can be processing a request for a target that is on a volume
4562         // we have never seen before.
4563         //
4564
4565         if( pVolumeCB == NULL)
4566         {
4567
4568             //
4569             // Locking is held correctly in init routine
4570             //
4571
4572             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4573
4574             //
4575             // Go init the root of the volume
4576             //
4577
4578             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4579                           AFS_TRACE_LEVEL_VERBOSE_2,
4580                           "AFSBuildMountPointTarget Initializing root for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4581                           &DirectoryCB->NameInformation.FileName,
4582                           DirectoryCB->ObjectInformation->FileId.Cell,
4583                           DirectoryCB->ObjectInformation->FileId.Volume,
4584                           DirectoryCB->ObjectInformation->FileId.Vnode,
4585                           DirectoryCB->ObjectInformation->FileId.Unique));
4586
4587             ntStatus = AFSInitVolume( AuthGroup,
4588                                       &stTargetFileID,
4589                                       AFS_VOLUME_REFERENCE_MOUNTPT,
4590                                       &pVolumeCB);
4591
4592             if( !NT_SUCCESS( ntStatus))
4593             {
4594
4595                 try_return( ntStatus);
4596             }
4597
4598             //
4599             // pVolumeCB->VolumeLock held exclusive and
4600             // pVolumeCB->VolumeReferenceCount has been incremented
4601             // pVolumeCB->RootFcb == NULL
4602             //
4603
4604             bReleaseVolumeLock = TRUE;
4605         }
4606         else
4607         {
4608
4609             //
4610             // AFSInitVolume returns with a VolumeReferenceCount
4611             // obtain one to match
4612             //
4613
4614             lCount = AFSVolumeIncrement( pVolumeCB,
4615                                          AFS_VOLUME_REFERENCE_MOUNTPT);
4616
4617             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4618                           AFS_TRACE_LEVEL_VERBOSE,
4619                           "AFSBuildMountPointTarget Increment count on volume %p Cnt %d\n",
4620                           pVolumeCB,
4621                           lCount));
4622
4623             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4624         }
4625
4626         if( pVolumeCB->RootFcb == NULL)
4627         {
4628
4629             if ( bReleaseVolumeLock == FALSE)
4630             {
4631
4632                 AFSAcquireExcl( pVolumeCB->VolumeLock,
4633                                 TRUE);
4634
4635                 bReleaseVolumeLock = TRUE;
4636             }
4637
4638             //
4639             // Initialize the root fcb for this volume
4640             //
4641
4642             ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4643                                        pVolumeCB);
4644
4645             if( !NT_SUCCESS( ntStatus))
4646             {
4647
4648                 lCount = AFSVolumeDecrement( pVolumeCB,
4649                                              AFS_VOLUME_REFERENCE_MOUNTPT);
4650
4651                 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4652                               AFS_TRACE_LEVEL_VERBOSE,
4653                               "AFSBuildMountPoint Decrement count on volume %p Cnt %d\n",
4654                               pVolumeCB,
4655                               lCount));
4656
4657                 AFSReleaseResource( pVolumeCB->VolumeLock);
4658
4659                 try_return( ntStatus);
4660             }
4661
4662             //
4663             // Drop the lock acquired above
4664             //
4665
4666             AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4667         }
4668
4669         if ( bReleaseVolumeLock == TRUE)
4670         {
4671
4672             AFSReleaseResource( pVolumeCB->VolumeLock);
4673         }
4674
4675         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4676                       AFS_TRACE_LEVEL_VERBOSE_2,
4677                       "AFSBuildMountPointTarget Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4678                       &pVolumeCB->DirectoryCB->NameInformation.FileName,
4679                       pVolumeCB->ObjectInformation.FileId.Cell,
4680                       pVolumeCB->ObjectInformation.FileId.Volume,
4681                       pVolumeCB->ObjectInformation.FileId.Vnode,
4682                       pVolumeCB->ObjectInformation.FileId.Unique));
4683
4684         *TargetVolumeCB = pVolumeCB;
4685
4686 try_exit:
4687
4688         if( pDirEntry)
4689         {
4690
4691             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
4692         }
4693     }
4694
4695     return ntStatus;
4696 }
4697
4698 NTSTATUS
4699 AFSBuildRootVolume( IN GUID *AuthGroup,
4700                     IN AFSFileID *FileId,
4701                     OUT AFSVolumeCB **TargetVolumeCB)
4702 {
4703
4704     NTSTATUS ntStatus = STATUS_SUCCESS;
4705     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4706     ULONGLONG       ullIndex = 0;
4707     AFSVolumeCB *pVolumeCB = NULL;
4708     LONG lCount;
4709     BOOLEAN bReleaseVolumeLock = FALSE;
4710
4711     __Enter
4712     {
4713
4714         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4715                       AFS_TRACE_LEVEL_VERBOSE_2,
4716                       "AFSBuildRootVolume Building target volume for FID %08lX-%08lX-%08lX-%08lX\n",
4717                       FileId->Cell,
4718                       FileId->Volume,
4719                       FileId->Vnode,
4720                       FileId->Unique));
4721
4722         ullIndex = AFSCreateHighIndex( FileId);
4723
4724         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4725                       AFS_TRACE_LEVEL_VERBOSE,
4726                       "AFSBuildRootVolume Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4727                       &pDevExt->Specific.RDR.VolumeTreeLock,
4728                       PsGetCurrentThread()));
4729
4730         AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4731                           TRUE);
4732
4733         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4734                       AFS_TRACE_LEVEL_VERBOSE_2,
4735                       "AFSBuildRootVolume Locating volume for target %I64X\n",
4736                       ullIndex));
4737
4738         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4739                                        ullIndex,
4740                                        (AFSBTreeEntry **)&pVolumeCB);
4741
4742         //
4743         // We can be processing a request for a target that is on a volume
4744         // we have never seen before.
4745         //
4746
4747         if( pVolumeCB == NULL)
4748         {
4749
4750             //
4751             // Locking is held correctly in init routine
4752             //
4753
4754             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4755
4756             //
4757             // Go init the root of the volume
4758             //
4759
4760             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4761                          AFS_TRACE_LEVEL_VERBOSE_2,
4762                           "AFSBuildRootVolume Initializing root for FID %08lX-%08lX-%08lX-%08lX\n",
4763                           FileId->Cell,
4764                           FileId->Volume,
4765                           FileId->Vnode,
4766                           FileId->Unique));
4767
4768             ntStatus = AFSInitVolume( AuthGroup,
4769                                       FileId,
4770                                       AFS_VOLUME_REFERENCE_BUILD_ROOT,
4771                                       &pVolumeCB);
4772
4773             if( !NT_SUCCESS( ntStatus))
4774             {
4775
4776                 try_return( ntStatus);
4777             }
4778
4779             //
4780             // pVolumeCB->VolumeLock is held exclusive
4781             // pVolumeCB->VolumeReferenceCount has been incremented
4782             // pVolumeCB->RootFcb == NULL
4783             //
4784
4785             bReleaseVolumeLock = TRUE;
4786         }
4787         else
4788         {
4789
4790             //
4791             // AFSInitVolume returns with a VolumeReferenceCount
4792             // obtain one to match
4793             //
4794
4795             lCount = AFSVolumeIncrement( pVolumeCB,
4796                                          AFS_VOLUME_REFERENCE_BUILD_ROOT);
4797
4798             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4799                           AFS_TRACE_LEVEL_VERBOSE,
4800                           "AFSBuildRootVolume Increment count on volume %p Cnt %d\n",
4801                           pVolumeCB,
4802                           lCount));
4803
4804             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4805         }
4806
4807
4808         if( pVolumeCB->RootFcb == NULL)
4809         {
4810
4811             if ( bReleaseVolumeLock == FALSE)
4812             {
4813
4814                 AFSAcquireExcl( pVolumeCB->VolumeLock,
4815                                 TRUE);
4816
4817                 bReleaseVolumeLock = TRUE;
4818             }
4819
4820             //
4821             // Initialize the root fcb for this volume
4822             //
4823
4824             ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4825                                        pVolumeCB);
4826
4827             if( !NT_SUCCESS( ntStatus))
4828             {
4829
4830                 lCount = AFSVolumeDecrement( pVolumeCB,
4831                                              AFS_VOLUME_REFERENCE_BUILD_ROOT);
4832
4833                 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4834                               AFS_TRACE_LEVEL_VERBOSE,
4835                               "AFSBuildRootVolume Decrement count on volume %p Cnt %d\n",
4836                               pVolumeCB,
4837                               lCount));
4838
4839                 AFSReleaseResource( pVolumeCB->VolumeLock);
4840
4841                 try_return( ntStatus);
4842             }
4843
4844             //
4845             // Drop the lock acquired above
4846             //
4847
4848             AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4849         }
4850
4851         if ( bReleaseVolumeLock == TRUE)
4852         {
4853
4854             AFSReleaseResource( pVolumeCB->VolumeLock);
4855         }
4856
4857         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4858                       AFS_TRACE_LEVEL_VERBOSE_2,
4859                       "AFSBuildRootVolume Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4860                       &pVolumeCB->DirectoryCB->NameInformation.FileName,
4861                       pVolumeCB->ObjectInformation.FileId.Cell,
4862                       pVolumeCB->ObjectInformation.FileId.Volume,
4863                       pVolumeCB->ObjectInformation.FileId.Vnode,
4864                       pVolumeCB->ObjectInformation.FileId.Unique));
4865
4866         *TargetVolumeCB = pVolumeCB;
4867
4868 try_exit:
4869
4870         NOTHING;
4871     }
4872
4873     return ntStatus;
4874 }
4875
4876 NTSTATUS
4877 AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
4878                    IN PFILE_OBJECT FileObject,
4879                    IN UNICODE_STRING *RemainingPath,
4880                    IN GUID *AuthGroup)
4881 {
4882
4883     NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
4884     UNICODE_STRING uniReparseName;
4885     UNICODE_STRING uniMUPDeviceName;
4886     UNICODE_STRING uniIOMgrDeviceName;
4887     AFSDirEnumEntry *pDirEntry = NULL;
4888
4889     __Enter
4890     {
4891
4892         //
4893         // Build up the name to reparse
4894         //
4895
4896         RtlInitUnicodeString( &uniMUPDeviceName,
4897                               L"\\Device\\MUP");
4898
4899         RtlInitUnicodeString( &uniIOMgrDeviceName,
4900                               L"\\??\\");
4901
4902         uniReparseName.Length = 0;
4903         uniReparseName.Buffer = NULL;
4904
4905         //
4906         // Be sure we have a target name
4907         //
4908
4909         if( DirEntry->NameInformation.TargetName.Length == 0)
4910         {
4911
4912             ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
4913                                               AuthGroup,
4914                                               FALSE,
4915                                               &pDirEntry);
4916
4917             if( !NT_SUCCESS( ntStatus) ||
4918                 pDirEntry->TargetNameLength == 0)
4919             {
4920
4921                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4922                               AFS_TRACE_LEVEL_ERROR,
4923                               "AFSProcessDFSLink EvaluateTargetByID failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4924                               &DirEntry->NameInformation.FileName,
4925                               DirEntry->ObjectInformation->FileId.Cell,
4926                               DirEntry->ObjectInformation->FileId.Volume,
4927                               DirEntry->ObjectInformation->FileId.Vnode,
4928                               DirEntry->ObjectInformation->FileId.Unique,
4929                               ntStatus));
4930
4931                 if( NT_SUCCESS( ntStatus))
4932                 {
4933
4934                     ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
4935                 }
4936
4937                 try_return( ntStatus);
4938             }
4939
4940             //
4941             // Update the target name
4942             //
4943
4944             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
4945                             TRUE);
4946
4947             ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
4948                                             &DirEntry->Flags,
4949                                             (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4950                                             (USHORT)pDirEntry->TargetNameLength);
4951
4952             if( !NT_SUCCESS( ntStatus))
4953             {
4954
4955                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4956                               AFS_TRACE_LEVEL_ERROR,
4957                               "AFSProcessDFSLink UpdateTargetName failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4958                               &DirEntry->NameInformation.FileName,
4959                               DirEntry->ObjectInformation->FileId.Cell,
4960                               DirEntry->ObjectInformation->FileId.Volume,
4961                               DirEntry->ObjectInformation->FileId.Vnode,
4962                               DirEntry->ObjectInformation->FileId.Unique,
4963                               ntStatus));
4964
4965                 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4966
4967                 try_return( ntStatus);
4968             }
4969
4970             AFSConvertToShared( &DirEntry->NonPaged->Lock);
4971         }
4972         else
4973         {
4974             AFSAcquireShared( &DirEntry->NonPaged->Lock,
4975                               TRUE);
4976         }
4977
4978         uniReparseName.MaximumLength = uniMUPDeviceName.Length +
4979                                                    sizeof( WCHAR) +
4980                                                    DirEntry->NameInformation.TargetName.Length +
4981                                                    sizeof( WCHAR);
4982
4983         if( RemainingPath != NULL &&
4984             RemainingPath->Length > 0)
4985         {
4986
4987             uniReparseName.MaximumLength += RemainingPath->Length;
4988         }
4989
4990         //
4991         // Allocate the reparse buffer
4992         //
4993
4994         uniReparseName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4995                                                                    uniReparseName.MaximumLength,
4996                                                                    AFS_REPARSE_NAME_TAG);
4997
4998         if( uniReparseName.Buffer == NULL)
4999         {
5000
5001             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5002                           AFS_TRACE_LEVEL_ERROR,
5003                           "AFSProcessDFSLink uniReparseName.Buffer == NULL Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
5004                           &DirEntry->NameInformation.FileName,
5005                           DirEntry->ObjectInformation->FileId.Cell,
5006                           DirEntry->ObjectInformation->FileId.Volume,
5007                           DirEntry->ObjectInformation->FileId.Vnode,
5008                           DirEntry->ObjectInformation->FileId.Unique,
5009                           STATUS_INSUFFICIENT_RESOURCES));
5010
5011             AFSReleaseResource( &DirEntry->NonPaged->Lock);
5012
5013             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5014         }
5015
5016         //
5017         // Start building the name
5018         //
5019
5020         if ( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\' &&
5021              DirEntry->NameInformation.TargetName.Buffer[ 1] == L':')
5022         {
5023
5024             RtlCopyMemory( uniReparseName.Buffer,
5025                            uniIOMgrDeviceName.Buffer,
5026                            uniIOMgrDeviceName.Length);
5027
5028             uniReparseName.Length = uniIOMgrDeviceName.Length;
5029         }
5030         else
5031         {
5032
5033             RtlCopyMemory( uniReparseName.Buffer,
5034                            uniMUPDeviceName.Buffer,
5035                            uniMUPDeviceName.Length);
5036
5037             uniReparseName.Length = uniMUPDeviceName.Length;
5038
5039             if( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\')
5040             {
5041
5042                 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
5043
5044                 uniReparseName.Length += sizeof( WCHAR);
5045             }
5046         }
5047
5048         RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
5049                        DirEntry->NameInformation.TargetName.Buffer,
5050                        DirEntry->NameInformation.TargetName.Length);
5051
5052         uniReparseName.Length += DirEntry->NameInformation.TargetName.Length;
5053
5054         AFSReleaseResource( &DirEntry->NonPaged->Lock);
5055
5056         if( RemainingPath != NULL &&
5057             RemainingPath->Length > 0)
5058         {
5059
5060             if( uniReparseName.Buffer[ (uniReparseName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
5061                 RemainingPath->Buffer[ 0] != L'\\')
5062             {
5063
5064                 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
5065
5066                 uniReparseName.Length += sizeof( WCHAR);
5067             }
5068
5069             RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
5070                            RemainingPath->Buffer,
5071                            RemainingPath->Length);
5072
5073             uniReparseName.Length += RemainingPath->Length;
5074         }
5075
5076         //
5077         // Update the name in the file object
5078         //
5079
5080         if( FileObject->FileName.Buffer != NULL)
5081         {
5082
5083             AFSExFreePoolWithTag( FileObject->FileName.Buffer, 0);
5084         }
5085
5086         FileObject->FileName = uniReparseName;
5087
5088         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5089                       AFS_TRACE_LEVEL_VERBOSE,
5090                       "AFSProcessDFSLink Reparsing access to Fcb %wZ FID %08lX-%08lX-%08lX-%08lX to %wZ\n",
5091                       &DirEntry->NameInformation.FileName,
5092                       DirEntry->ObjectInformation->FileId.Cell,
5093                       DirEntry->ObjectInformation->FileId.Volume,
5094                       DirEntry->ObjectInformation->FileId.Vnode,
5095                       DirEntry->ObjectInformation->FileId.Unique,
5096                       &uniReparseName));
5097
5098         //
5099         // Return status reparse ...
5100         //
5101
5102         ntStatus = STATUS_REPARSE;
5103
5104 try_exit:
5105
5106         if ( pDirEntry)
5107         {
5108
5109             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
5110         }
5111     }
5112
5113     return ntStatus;
5114 }