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