Windows: Remove trailing slash on non-root directories
[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        &nb