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