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