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