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