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