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