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