Windows: Fix trace msg typo in AFSDeleteDirEntry
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSNameSupport.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright
13  *   notice,
14  *   this list of conditions and the following disclaimer in the
15  *   documentation
16  *   and/or other materials provided with the distribution.
17  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18  *   nor the names of their contributors may be used to endorse or promote
19  *   products derived from this software without specific prior written
20  *   permission from Kernel Drivers, LLC and Your File System, Inc.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 //
36 // File: AFSNameSupport.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 //
42 // AFSLocateNameEntry
43 //
44 // On entry, *VolumeCB must have a held ReferenceCount provided by
45 // the caller which will not be released.  On successful exit, *OutVolumeCB
46 // will be assigned the new current volume with a held ReferenceCount.
47 //
48 // On entry, *ParentDirectoryCB must have a held DirOpenReferenceCount
49 // provided by the caller.  This reference will not be released.
50 // On exit, if OutParentDirectoryCB is set, it will have a new reference.
51 //
52 // On exit, if OutDirectoryCB is set, it will have a reference.
53 //
54
55 NTSTATUS
56 AFSLocateNameEntry( IN GUID *AuthGroup,
57                     IN PFILE_OBJECT FileObject,
58                     IN OUT UNICODE_STRING *RootPathName,
59                     IN UNICODE_STRING *ParsedPathName,
60                     IN AFSNameArrayHdr *NameArray,
61                     IN ULONG Flags,
62                     IN AFSVolumeCB *VolumeCB,
63                     IN AFSDirectoryCB *ParentDirectoryCB,
64                     OUT AFSVolumeCB **OutVolumeCB,
65                     OUT LONG *OutVolumeReferenceReason,
66                     OUT AFSDirectoryCB **OutParentDirectoryCB,
67                     OUT AFSDirectoryCB **OutDirectoryCB,
68                     OUT PUNICODE_STRING ComponentName)
69 {
70
71     NTSTATUS          ntStatus = STATUS_SUCCESS;
72     UNICODE_STRING    uniPathName, uniComponentName, uniRemainingPath, uniSearchName, uniFullPathName;
73     ULONG             ulCRC = 0;
74     AFSDirectoryCB   *pDirEntry = NULL, *pParentDirEntry = NULL;
75     AFSDeviceExt     *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
76     UNICODE_STRING    uniSysName;
77     ULONG             ulSubstituteIndex = 0;
78     BOOLEAN           bSubstituteName = FALSE;
79     AFSNameArrayHdr  *pNameArray = NameArray;
80     BOOLEAN           bAllocatedSymLinkBuffer = FALSE;
81     UNICODE_STRING    uniRelativeName, uniNoOpName;
82     AFSObjectInfoCB  *pCurrentObject = NULL;
83     AFSObjectInfoCB  *pParentObjectInfo = NULL;
84     AFSVolumeCB      *pCurrentVolume = NULL;
85     AFSVolumeCB      *pTargetVolume = NULL;
86     BOOLEAN           bReleaseCurrentVolume = FALSE;
87     LONG              VolumeReferenceReason;
88     BOOLEAN           bSubstitutedName = FALSE;
89     LONG              lCount;
90
91     __Enter
92     {
93
94         ASSERT( *OutVolumeCB != VolumeCB);
95
96         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
97                       AFS_TRACE_LEVEL_VERBOSE_2,
98                       "AFSLocateNameEntry (FO: %p) Processing full name %wZ\n",
99                       FileObject,
100                       RootPathName));
101
102         RtlInitUnicodeString( &uniSysName,
103                               L"*@SYS");
104
105         RtlInitUnicodeString( &uniRelativeName,
106                               L"..");
107
108         RtlInitUnicodeString( &uniNoOpName,
109                               L".");
110
111         //
112         // Cleanup some parameters
113         //
114
115         if( ComponentName != NULL)
116         {
117
118             ComponentName->Length = 0;
119             ComponentName->MaximumLength = 0;
120             ComponentName->Buffer = NULL;
121         }
122
123         //
124         // We will parse through the filename, locating the directory nodes until we encounter a cache miss
125         // Starting at the root node
126         //
127
128         pParentDirEntry = NULL;
129
130         pDirEntry = ParentDirectoryCB;
131
132         //
133         // Increment our reference on this dir entry
134         //
135
136         lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
137
138         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
139                       AFS_TRACE_LEVEL_VERBOSE,
140                       "AFSLocateNameEntry Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
141                       &pDirEntry->NameInformation.FileName,
142                       pDirEntry,
143                       NULL,
144                       lCount));
145
146         pCurrentVolume = VolumeCB;
147
148         VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
149
150         lCount = AFSVolumeIncrement( pCurrentVolume,
151                                      VolumeReferenceReason);
152
153         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
154                       AFS_TRACE_LEVEL_VERBOSE,
155                       "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
156                       pCurrentVolume,
157                       VolumeReferenceReason,
158                       lCount));
159
160         bReleaseCurrentVolume = TRUE;
161
162         uniPathName = *ParsedPathName;
163
164         uniFullPathName = *RootPathName;
165
166         uniComponentName.Length = uniComponentName.MaximumLength = 0;
167         uniComponentName.Buffer = NULL;
168
169         uniRemainingPath.Length = uniRemainingPath.MaximumLength = 0;
170         uniRemainingPath.Buffer = NULL;
171
172         uniSearchName.Length = uniSearchName.MaximumLength = 0;
173         uniSearchName.Buffer = NULL;
174
175         while( TRUE)
176         {
177
178             ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
179
180             ASSERT( pDirEntry->DirOpenReferenceCount > 0);
181
182             //
183             // Check our total link count for this name array
184             //
185
186             if( pNameArray->LinkCount >= (LONG)pDevExt->Specific.RDR.MaxLinkCount)
187             {
188
189                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
190             }
191
192             pCurrentObject = pDirEntry->ObjectInformation;
193
194             KeQueryTickCount( &pCurrentObject->LastAccessCount);
195
196             //
197             // Check that the directory entry is not deleted or pending delete
198             //
199
200             if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
201             {
202
203                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
204                               AFS_TRACE_LEVEL_ERROR,
205                               "AFSLocateNameEntry (FO: %p) Deleted parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
206                               FileObject,
207                               &pDirEntry->NameInformation.FileName,
208                               pCurrentObject->FileId.Cell,
209                               pCurrentObject->FileId.Volume,
210                               pCurrentObject->FileId.Vnode,
211                               pCurrentObject->FileId.Unique,
212                               STATUS_FILE_DELETED));
213
214                 try_return( ntStatus = STATUS_FILE_DELETED);
215             }
216
217             if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
218             {
219
220                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
221                               AFS_TRACE_LEVEL_ERROR,
222                               "AFSLocateNameEntry (FO: %p) Delete pending on %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
223                               FileObject,
224                               &pDirEntry->NameInformation.FileName,
225                               pCurrentObject->FileId.Cell,
226                               pCurrentObject->FileId.Volume,
227                               pCurrentObject->FileId.Vnode,
228                               pCurrentObject->FileId.Unique,
229                               STATUS_DELETE_PENDING));
230
231                 try_return( ntStatus = STATUS_DELETE_PENDING);
232             }
233
234             //
235             // Check if the directory requires verification
236             //
237
238             if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
239                 ( pCurrentObject->FileType != AFS_FILE_TYPE_DIRECTORY ||
240                   !AFSIsEnumerationInProcess( pCurrentObject)))
241             {
242
243                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
244                               AFS_TRACE_LEVEL_VERBOSE,
245                               "AFSLocateNameEntry (FO: %p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
246                               FileObject,
247                               &pDirEntry->NameInformation.FileName,
248                               pCurrentObject->FileId.Cell,
249                               pCurrentObject->FileId.Volume,
250                               pCurrentObject->FileId.Vnode,
251                               pCurrentObject->FileId.Unique));
252
253                 //
254                 // Directory TreeLock should be exclusively held
255                 //
256
257                 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
258                                 TRUE);
259
260                 ntStatus = AFSVerifyEntry( AuthGroup,
261                                            pDirEntry);
262
263                 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
264
265                 if( !NT_SUCCESS( ntStatus))
266                 {
267
268                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
269                                   AFS_TRACE_LEVEL_ERROR,
270                                   "AFSLocateNameEntry (FO: %p) Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
271                                   FileObject,
272                                   &pDirEntry->NameInformation.FileName,
273                                   pCurrentObject->FileId.Cell,
274                                   pCurrentObject->FileId.Volume,
275                                   pCurrentObject->FileId.Vnode,
276                                   pCurrentObject->FileId.Unique,
277                                   ntStatus));
278
279                     try_return( ntStatus);
280                 }
281             }
282
283             //
284             // Ensure the parent node has been evaluated, if not then go do it now
285             //
286
287             if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) ||
288                 pCurrentObject->FileType == AFS_FILE_TYPE_UNKNOWN)
289             {
290
291                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
292                               AFS_TRACE_LEVEL_VERBOSE,
293                               "AFSLocateNameEntry (FO: %p) Evaluating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
294                               FileObject,
295                               &pDirEntry->NameInformation.FileName,
296                               pCurrentObject->FileId.Cell,
297                               pCurrentObject->FileId.Volume,
298                               pCurrentObject->FileId.Vnode,
299                               pCurrentObject->FileId.Unique));
300
301                 ntStatus = AFSEvaluateNode( AuthGroup,
302                                             pDirEntry);
303
304                 if( !NT_SUCCESS( ntStatus))
305                 {
306
307                     if ( ntStatus == STATUS_NOT_A_DIRECTORY)
308                     {
309
310                         if ( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
311                         {
312
313                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
314                                           AFS_TRACE_LEVEL_ERROR,
315                                           "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT NULL Status %08lX\n",
316                                           FileObject,
317                                           &pDirEntry->NameInformation.FileName,
318                                           pCurrentObject->FileId.Cell,
319                                           pCurrentObject->FileId.Volume,
320                                           pCurrentObject->FileId.Vnode,
321                                           pCurrentObject->FileId.Unique,
322                                           ntStatus));
323                         }
324                         else
325                         {
326
327                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
328                                           AFS_TRACE_LEVEL_ERROR,
329                                           "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT %08lX-%08lX-%08lX-%08lX Status %08lX\n",
330                                           FileObject,
331                                           &pDirEntry->NameInformation.FileName,
332                                           pCurrentObject->FileId.Cell,
333                                           pCurrentObject->FileId.Volume,
334                                           pCurrentObject->FileId.Vnode,
335                                           pCurrentObject->FileId.Unique,
336                                           pCurrentObject->ParentFileId.Cell,
337                                           pCurrentObject->ParentFileId.Volume,
338                                           pCurrentObject->ParentFileId.Vnode,
339                                           pCurrentObject->ParentFileId.Unique,
340                                           ntStatus));
341                         }
342                     }
343                     else
344                     {
345                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
346                                       AFS_TRACE_LEVEL_ERROR,
347                                       "AFSLocateNameEntry (FO: %p) Failed to evaluate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
348                                       FileObject,
349                                       &pDirEntry->NameInformation.FileName,
350                                       pCurrentObject->FileId.Cell,
351                                       pCurrentObject->FileId.Volume,
352                                       pCurrentObject->FileId.Vnode,
353                                       pCurrentObject->FileId.Unique,
354                                       ntStatus));
355                     }
356
357                     try_return( ntStatus);
358                 }
359
360                 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
361             }
362
363             //
364             // If this is a mount point or symlink then go get the real directory node
365             //
366
367             switch( pCurrentObject->FileType)
368             {
369
370                 case AFS_FILE_TYPE_SYMLINK:
371                 {
372
373                     UNICODE_STRING uniTempName;
374                     WCHAR *pTmpBuffer = NULL;
375                     LONG lLinkCount = 0;
376
377                     //
378                     // Check if the flag is set to NOT evaluate a symlink
379                     // and we are done with the parsing
380                     //
381
382                     if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL) &&
383                         uniRemainingPath.Length == 0)
384                     {
385
386                         //
387                         // Pass back the directory entries
388                         //
389
390                         *OutParentDirectoryCB = pParentDirEntry;
391
392                         pParentDirEntry = NULL;
393
394                         *OutDirectoryCB = pDirEntry;
395
396                         pDirEntry = NULL;
397
398                         *OutVolumeCB = pCurrentVolume;
399
400                         *OutVolumeReferenceReason = VolumeReferenceReason;
401
402                         bReleaseCurrentVolume = FALSE;
403
404                         *RootPathName = uniFullPathName;
405
406                         try_return( ntStatus);
407                     }
408
409                     AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
410                                     TRUE);
411
412                     AFSAcquireExcl( &pDirEntry->NonPaged->Lock,
413                                     TRUE);
414
415                     if( pDirEntry->NameInformation.TargetName.Length == 0)
416                     {
417
418                         //
419                         // We'll reset the DV to ensure we validate the metadata content
420                         //
421
422                         pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
423
424                         SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
425
426                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
427                                       AFS_TRACE_LEVEL_VERBOSE,
428                                       "AFSLocateNameEntry (FO: %p) Verifying symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
429                                       FileObject,
430                                       &pDirEntry->NameInformation.FileName,
431                                       pCurrentObject->FileId.Cell,
432                                       pCurrentObject->FileId.Volume,
433                                       pCurrentObject->FileId.Vnode,
434                                       pCurrentObject->FileId.Unique));
435
436                         //
437                         // Directory TreeLock should be exclusively held
438                         //
439
440                         ntStatus = AFSVerifyEntry( AuthGroup,
441                                                    pDirEntry);
442
443                         AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
444
445                         if( !NT_SUCCESS( ntStatus))
446                         {
447
448                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
449                                           AFS_TRACE_LEVEL_ERROR,
450                                           "AFSLocateNameEntry (FO: %p) Failed to verify symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
451                                           FileObject,
452                                           &pDirEntry->NameInformation.FileName,
453                                           pCurrentObject->FileId.Cell,
454                                           pCurrentObject->FileId.Volume,
455                                           pCurrentObject->FileId.Vnode,
456                                           pCurrentObject->FileId.Unique,
457                                           ntStatus));
458
459                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
460
461                             try_return( ntStatus);
462                         }
463
464                         //
465                         // If the type changed then reprocess this entry
466                         //
467
468                         if( pCurrentObject->FileType != AFS_FILE_TYPE_SYMLINK)
469                         {
470
471                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
472
473                             continue;
474                         }
475                     }
476                     else
477                     {
478
479                         AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
480                     }
481
482                     //
483                     // If we were given a zero length target name then deny access to the entry
484                     //
485
486                     if( pDirEntry->NameInformation.TargetName.Length == 0)
487                     {
488
489                         ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
490
491                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
492                                       AFS_TRACE_LEVEL_ERROR,
493                                       "AFSLocateNameEntry (FO: %p) Failed to retrieve target name for symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
494                                       FileObject,
495                                       &pDirEntry->NameInformation.FileName,
496                                       pCurrentObject->FileId.Cell,
497                                       pCurrentObject->FileId.Volume,
498                                       pCurrentObject->FileId.Vnode,
499                                       pCurrentObject->FileId.Unique,
500                                       ntStatus));
501
502                         AFSReleaseResource( &pDirEntry->NonPaged->Lock);
503
504                         try_return( ntStatus);
505                     }
506
507                     if( AFSIsRelativeName( &pDirEntry->NameInformation.TargetName))
508                     {
509
510                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
511                                       AFS_TRACE_LEVEL_VERBOSE,
512                                       "AFSLocateNameEntry (FO: %p) Processing relative symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
513                                       FileObject,
514                                       &pDirEntry->NameInformation.TargetName,
515                                       &pDirEntry->NameInformation.FileName,
516                                       pCurrentObject->FileId.Cell,
517                                       pCurrentObject->FileId.Volume,
518                                       pCurrentObject->FileId.Vnode,
519                                       pCurrentObject->FileId.Unique));
520
521                         //
522                         // We'll substitute this name into the current process name
523                         // starting at where we sit in the path
524                         //
525
526                         uniTempName.Length = 0;
527                         uniTempName.MaximumLength = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer) +
528                                                                     pDirEntry->NameInformation.TargetName.Length +
529                                                                     sizeof( WCHAR) +
530                                                                     uniRemainingPath.Length;
531
532                         uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
533                                                                                 uniTempName.MaximumLength,
534                                                                                 AFS_NAME_BUFFER_ONE_TAG);
535
536                         if( uniTempName.Buffer == NULL)
537                         {
538
539                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
540
541                             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
542                         }
543
544                         //
545                         // We have so first copy in the portion up to the component
546                         // name
547                         //
548
549                         RtlCopyMemory( uniTempName.Buffer,
550                                        uniFullPathName.Buffer,
551                                        (ULONG)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer));
552
553                         uniTempName.Length = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer);
554
555                         if( bAllocatedSymLinkBuffer ||
556                             bSubstitutedName)
557                         {
558
559                             pTmpBuffer = uniFullPathName.Buffer;
560                         }
561
562                         bAllocatedSymLinkBuffer = TRUE;
563
564                         //
565                         // Have we parsed this name yet? Better have at least once ...
566                         //
567
568                         if( uniComponentName.Length == 0)
569                         {
570                             ASSERT( FALSE);
571                         }
572
573                         //
574                         // Copy in the target name ...
575                         //
576
577                         RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
578                                        pDirEntry->NameInformation.TargetName.Buffer,
579                                        pDirEntry->NameInformation.TargetName.Length);
580
581                         uniPathName.Buffer = &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)];
582
583                         uniPathName.Length += pDirEntry->NameInformation.TargetName.Length;
584                         uniPathName.MaximumLength = uniTempName.MaximumLength;
585
586                         uniTempName.Length += pDirEntry->NameInformation.TargetName.Length;
587
588                         //
589                         // And now any remaining portion of the name
590                         //
591
592                         if( uniRemainingPath.Length > 0)
593                         {
594
595                             if( uniRemainingPath.Buffer[ 0] != L'\\')
596                             {
597
598                                 uniRemainingPath.Buffer--;
599                                 uniRemainingPath.Length += sizeof( WCHAR);
600
601                                 uniPathName.Length += sizeof( WCHAR);
602                             }
603
604                             RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
605                                            uniRemainingPath.Buffer,
606                                            uniRemainingPath.Length);
607
608                             uniTempName.Length += uniRemainingPath.Length;
609                         }
610
611                         uniFullPathName = uniTempName;
612
613                         if( pTmpBuffer != NULL)
614                         {
615
616                             AFSExFreePoolWithTag( pTmpBuffer, 0);
617                         }
618
619                         AFSReleaseResource( &pDirEntry->NonPaged->Lock);
620
621                         //
622                         // Dereference the current entry ..
623                         //
624
625                         lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
626
627                         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
628                                       AFS_TRACE_LEVEL_VERBOSE,
629                                       "AFSLocateNameEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
630                                       &pDirEntry->NameInformation.FileName,
631                                       pDirEntry,
632                                       NULL,
633                                       lCount));
634
635                         ASSERT( lCount >= 0);
636
637                         //
638                         // OK, need to back up one entry for the correct parent since the current
639                         // entry we are on is the symlink itself
640                         //
641
642                         pDirEntry = AFSBackupEntry( pNameArray);
643
644                         pCurrentObject = pDirEntry->ObjectInformation;
645
646                         //
647                         // Increment our reference on this dir entry
648                         //
649
650                         lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
651
652                         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
653                                       AFS_TRACE_LEVEL_VERBOSE,
654                                       "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
655                                       &pDirEntry->NameInformation.FileName,
656                                       pDirEntry,
657                                       NULL,
658                                       lCount));
659
660                         if ( pParentDirEntry)
661                         {
662
663                             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
664
665                             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
666                                           AFS_TRACE_LEVEL_VERBOSE,
667                                           "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
668                                           &pParentDirEntry->NameInformation.FileName,
669                                           pParentDirEntry,
670                                           NULL,
671                                           lCount));
672
673                             pParentDirEntry = NULL;
674                         }
675
676                         if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
677                         {
678
679                             pParentDirEntry = AFSGetParentEntry( pNameArray);
680
681                             ASSERT( pParentDirEntry != pDirEntry);
682
683                             lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
684
685                             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
686                                           AFS_TRACE_LEVEL_VERBOSE,
687                                           "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
688                                           &pParentDirEntry->NameInformation.FileName,
689                                           pParentDirEntry,
690                                           NULL,
691                                           lCount));
692                         }
693
694                         if ( pDirEntry->ObjectInformation->VolumeCB != pCurrentVolume)
695                         {
696
697                             lCount = AFSVolumeDecrement( pCurrentVolume,
698                                                          VolumeReferenceReason);
699
700                             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
701                                           AFS_TRACE_LEVEL_VERBOSE,
702                                           "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
703                                           pCurrentVolume,
704                                           VolumeReferenceReason,
705                                           lCount));
706
707                             pCurrentVolume = pDirEntry->ObjectInformation->VolumeCB;
708
709                             VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
710
711                             lCount = AFSVolumeIncrement( pCurrentVolume,
712                                                          VolumeReferenceReason);
713
714                             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
715                                           AFS_TRACE_LEVEL_VERBOSE,
716                                           "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
717                                           pCurrentVolume,
718                                           VolumeReferenceReason,
719                                           lCount));
720                         }
721                     }
722                     else
723                     {
724
725                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
726                                       AFS_TRACE_LEVEL_VERBOSE,
727                                       "AFSLocateNameEntry (FO: %p) Processing absolute symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
728                                       FileObject,
729                                       &pDirEntry->NameInformation.TargetName,
730                                       &pDirEntry->NameInformation.FileName,
731                                       pCurrentObject->FileId.Cell,
732                                       pCurrentObject->FileId.Volume,
733                                       pCurrentObject->FileId.Vnode,
734                                       pCurrentObject->FileId.Unique));
735
736                         if ( !AFSIsAbsoluteAFSName( &pDirEntry->NameInformation.TargetName))
737                         {
738
739                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
740                                           AFS_TRACE_LEVEL_ERROR,
741                                           "AFSLocateNameEntry Name %wZ contains invalid server name\n",
742                                           &pDirEntry->NameInformation.TargetName));
743
744                             //
745                             // The correct response would be STATUS_OBJECT_PATH_INVALID
746                             // but that prevents cmd.exe from performing a recursive
747                             // directory enumeration when opening a directory entry
748                             // that represents a symlink to an invalid path is discovered.
749                             //
750
751                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
752
753                             try_return( ntStatus = STATUS_OBJECT_PATH_NOT_FOUND);
754                         }
755
756                         //
757                         // We'll substitute this name into the current process name
758                         // starting at where we sit in the path
759                         //
760
761                         uniTempName.Length = 0;
762                         uniTempName.MaximumLength = pDirEntry->NameInformation.TargetName.Length +
763                                                                     sizeof( WCHAR) +
764                                                                     uniRemainingPath.Length;
765
766                         uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
767                                                                                 uniTempName.MaximumLength,
768                                                                                 AFS_NAME_BUFFER_TWO_TAG);
769
770                         if( uniTempName.Buffer == NULL)
771                         {
772
773                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
774
775                             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
776                         }
777
778                         if( bAllocatedSymLinkBuffer ||
779                             bSubstitutedName)
780                         {
781
782                             pTmpBuffer = uniFullPathName.Buffer;
783                         }
784
785                         bAllocatedSymLinkBuffer = TRUE;
786
787                         //
788                         // Have we parsed this name yet? Better have at least once ...
789                         //
790
791                         if( uniComponentName.Length == 0)
792                         {
793                             ASSERT( FALSE);
794                         }
795
796                         //
797                         // Copy in the target name ...
798                         //
799
800                         RtlCopyMemory( uniTempName.Buffer,
801                                        &pDirEntry->NameInformation.TargetName.Buffer[ AFSMountRootName.Length/sizeof( WCHAR)],
802                                        pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length);
803
804                         uniTempName.Length = pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length;
805
806                         //
807                         // And now any remaining portion of the name
808                         //
809
810                         if( uniRemainingPath.Length > 0)
811                         {
812
813                             if( uniRemainingPath.Buffer[ 0] != L'\\')
814                             {
815
816                                 uniRemainingPath.Buffer--;
817                                 uniRemainingPath.Length += sizeof( WCHAR);
818                             }
819
820                             RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
821                                            uniRemainingPath.Buffer,
822                                            uniRemainingPath.Length);
823
824                             uniTempName.Length += uniRemainingPath.Length;
825                         }
826
827                         uniFullPathName = uniTempName;
828
829                         uniPathName = uniTempName;
830
831                         if( pTmpBuffer != NULL)
832                         {
833
834                             AFSExFreePoolWithTag( pTmpBuffer, 0);
835                         }
836
837                         AFSReleaseResource( &pDirEntry->NonPaged->Lock);
838
839                         //
840                         // If our current volume is not the global root then make it so ...
841                         //
842
843                         if( pCurrentVolume != AFSGlobalRoot)
844                         {
845
846                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
847                                           AFS_TRACE_LEVEL_VERBOSE,
848                                           "AFSLocateNameEntry (FO: %p) Current volume not global, resetting for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
849                                           FileObject,
850                                           &pDirEntry->NameInformation.FileName,
851                                           pCurrentObject->FileId.Cell,
852                                           pCurrentObject->FileId.Volume,
853                                           pCurrentObject->FileId.Vnode,
854                                           pCurrentObject->FileId.Unique));
855
856                             lCount = AFSVolumeDecrement( pCurrentVolume,
857                                                          VolumeReferenceReason);
858
859                             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
860                                           AFS_TRACE_LEVEL_VERBOSE,
861                                           "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
862                                           pCurrentVolume,
863                                           VolumeReferenceReason,
864                                           lCount));
865
866                             pCurrentVolume = AFSGlobalRoot;
867
868                             VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
869
870                             lCount = AFSVolumeIncrement( pCurrentVolume,
871                                                          VolumeReferenceReason);
872
873                             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
874                                           AFS_TRACE_LEVEL_VERBOSE,
875                                           "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
876                                           pCurrentVolume,
877                                           VolumeReferenceReason,
878                                           lCount));
879                         }
880
881                         //
882                         // Dereference our current dir entry
883                         //
884
885                         lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
886
887                         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
888                                       AFS_TRACE_LEVEL_VERBOSE,
889                                       "AFSLocateNameEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
890                                       &pDirEntry->NameInformation.FileName,
891                                       pDirEntry,
892                                       NULL,
893                                       lCount));
894
895                         ASSERT( lCount >= 0);
896
897                         pDirEntry = pCurrentVolume->DirectoryCB;
898
899                         pCurrentObject = pDirEntry->ObjectInformation;
900
901                         //
902                         // Reference the new dir entry
903                         //
904
905                         lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
906
907                         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
908                                       AFS_TRACE_LEVEL_VERBOSE,
909                                       "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
910                                       &pDirEntry->NameInformation.FileName,
911                                       pDirEntry,
912                                       NULL,
913                                       lCount));
914
915                         //
916                         // Reset the name array
917                         // Persist the link count in the name array
918                         //
919
920                         lLinkCount = pNameArray->LinkCount;
921
922                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
923                                       AFS_TRACE_LEVEL_VERBOSE,
924                                       "AFSLocateNameEntry (FO: %p) Resetting name array for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
925                                       FileObject,
926                                       &pDirEntry->NameInformation.FileName,
927                                       pCurrentObject->FileId.Cell,
928                                       pCurrentObject->FileId.Volume,
929                                       pCurrentObject->FileId.Vnode,
930                                       pCurrentObject->FileId.Unique));
931
932                         AFSResetNameArray( pNameArray,
933                                            pDirEntry);
934
935                         pNameArray->LinkCount = lLinkCount;
936
937                         if ( pParentDirEntry)
938                         {
939
940                             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
941
942                             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
943                                           AFS_TRACE_LEVEL_VERBOSE,
944                                           "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
945                                           &pParentDirEntry->NameInformation.FileName,
946                                           pParentDirEntry,
947                                           NULL,
948                                           lCount));
949
950                             pParentDirEntry = NULL;
951                         }
952                     }
953
954                     //
955                     // Increment our link count
956                     //
957
958                     lCount = InterlockedIncrement( &pNameArray->LinkCount);
959
960                     continue;
961                 }
962
963                 case AFS_FILE_TYPE_MOUNTPOINT:
964                 {
965
966                     //
967                     // Check if the flag is set to NOT evaluate a mount point
968                     // and we are done with the parsing
969                     //
970
971                     if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL) &&
972                         uniRemainingPath.Length == 0)
973                     {
974
975                         //
976                         // Pass back the directory entries
977                         //
978
979                         *OutParentDirectoryCB = pParentDirEntry;
980
981                         pParentDirEntry = NULL;
982
983                         *OutDirectoryCB = pDirEntry;
984
985                         pDirEntry = NULL;
986
987                         *OutVolumeCB = pCurrentVolume;
988
989                         *OutVolumeReferenceReason = VolumeReferenceReason;
990
991                         bReleaseCurrentVolume = FALSE;
992
993                         *RootPathName = uniFullPathName;
994
995                         try_return( ntStatus);
996                     }
997
998                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
999                                   AFS_TRACE_LEVEL_VERBOSE,
1000                                   "AFSLocateNameEntry (FO: %p) Building MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1001                                   FileObject,
1002                                   &pDirEntry->NameInformation.FileName,
1003                                   pCurrentObject->FileId.Cell,
1004                                   pCurrentObject->FileId.Volume,
1005                                   pCurrentObject->FileId.Vnode,
1006                                   pCurrentObject->FileId.Unique));
1007
1008                     //
1009                     // Go retrieve the target entry for this node
1010                     // Release the current volume cb entry since we would
1011                     // have lock inversion in the following call
1012                     // Also decrement the ref count on the volume
1013                     //
1014
1015                     ntStatus = AFSBuildMountPointTarget( AuthGroup,
1016                                                          pDirEntry,
1017                                                          &pTargetVolume);
1018
1019                     if( !NT_SUCCESS( ntStatus))
1020                     {
1021
1022                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1023                                       AFS_TRACE_LEVEL_ERROR,
1024                                       "AFSLocateNameEntry (FO: %p) Failed to build MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1025                                       FileObject,
1026                                       &pDirEntry->NameInformation.FileName,
1027                                       pCurrentObject->FileId.Cell,
1028                                       pCurrentObject->FileId.Volume,
1029                                       pCurrentObject->FileId.Vnode,
1030                                       pCurrentObject->FileId.Unique,
1031                                       ntStatus));
1032
1033                         try_return( ntStatus);
1034                     }
1035
1036                     ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
1037
1038                     lCount = AFSVolumeDecrement( pCurrentVolume,
1039                                                  VolumeReferenceReason);
1040
1041                     AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1042                                   AFS_TRACE_LEVEL_VERBOSE,
1043                                   "AFSLocateNameEntry Decrement2 count on volume %p Reason %u Cnt %d\n",
1044                                   pCurrentVolume,
1045                                   VolumeReferenceReason,
1046                                   lCount));
1047
1048                     pCurrentVolume = pTargetVolume;
1049
1050                     pTargetVolume = NULL;
1051
1052                     ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
1053
1054                     VolumeReferenceReason = AFS_VOLUME_REFERENCE_MOUNTPT;
1055
1056                     //
1057                     // We want to restart processing here on the new parent ...
1058                     // Deref and ref count the entries
1059                     //
1060
1061                     lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1062
1063                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1064                                   AFS_TRACE_LEVEL_VERBOSE,
1065                                   "AFSLocateNameEntry Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
1066                                   &pDirEntry->NameInformation.FileName,
1067                                   pDirEntry,
1068                                   NULL,
1069                                   lCount));
1070
1071                     ASSERT( lCount >= 0);
1072
1073                     pDirEntry = pCurrentVolume->DirectoryCB;
1074
1075                     pCurrentObject = pDirEntry->ObjectInformation;
1076
1077                     lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1078
1079                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1080                                   AFS_TRACE_LEVEL_VERBOSE,
1081                                   "AFSLocateNameEntry Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
1082                                   &pDirEntry->NameInformation.FileName,
1083                                   pDirEntry,
1084                                   NULL,
1085                                   lCount));
1086
1087                     //
1088                     // The name array stores both the mount point and the target.
1089                     // Insert the target.
1090                     //
1091
1092                     AFSInsertNextElement( pNameArray,
1093                                           pDirEntry);
1094
1095                     if ( pParentDirEntry)
1096                     {
1097
1098                         lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1099
1100                         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1101                                       AFS_TRACE_LEVEL_VERBOSE,
1102                                       "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1103                                       &pParentDirEntry->NameInformation.FileName,
1104                                       pParentDirEntry,
1105                                       NULL,
1106                                       lCount));
1107
1108                         pParentDirEntry = NULL;
1109                     }
1110
1111                     //
1112                     // Increment our link count
1113                     //
1114
1115                     lCount = InterlockedIncrement( &pNameArray->LinkCount);
1116
1117                     continue;
1118                 }
1119
1120                 case AFS_FILE_TYPE_DFSLINK:
1121                 {
1122
1123                     if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL))
1124                     {
1125
1126                         //
1127                         // Pass back the directory entries
1128                         //
1129
1130                         *OutParentDirectoryCB = pParentDirEntry;
1131
1132                         pParentDirEntry = NULL;
1133
1134                         *OutDirectoryCB = pDirEntry;
1135
1136                         pDirEntry = NULL;
1137
1138                         *OutVolumeCB = pCurrentVolume;
1139
1140                         *OutVolumeReferenceReason = VolumeReferenceReason;
1141
1142                         bReleaseCurrentVolume = FALSE;
1143
1144                         *RootPathName = uniFullPathName;
1145
1146                         try_return( ntStatus);
1147                     }
1148
1149                     //
1150                     // This is a DFS link so we need to update the file name and return STATUS_REPARSE to the
1151                     // system for it to reevaluate it
1152                     //
1153
1154                     if( FileObject != NULL)
1155                     {
1156
1157                         ntStatus = AFSProcessDFSLink( pDirEntry,
1158                                                       FileObject,
1159                                                       &uniRemainingPath,
1160                                                       AuthGroup);
1161                     }
1162                     else
1163                     {
1164
1165                         //
1166                         // This is where we have been re-entered from an NP evaluation call via the BuildBranch()
1167                         // routine.
1168                         //
1169
1170                         ntStatus = STATUS_INVALID_PARAMETER;
1171                     }
1172
1173                     if( ntStatus != STATUS_SUCCESS &&
1174                         ntStatus != STATUS_REPARSE)
1175                     {
1176
1177                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1178                                       AFS_TRACE_LEVEL_ERROR,
1179                                       "AFSLocateNameEntry (FO: %p) Failed to process DFSLink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1180                                       FileObject,
1181                                       &pDirEntry->NameInformation.FileName,
1182                                       pCurrentObject->FileId.Cell,
1183                                       pCurrentObject->FileId.Volume,
1184                                       pCurrentObject->FileId.Vnode,
1185                                       pCurrentObject->FileId.Unique,
1186                                       ntStatus));
1187                     }
1188
1189                     try_return( ntStatus);
1190                 }
1191
1192                 case AFS_FILE_TYPE_UNKNOWN:
1193                 case AFS_FILE_TYPE_INVALID:
1194                 {
1195
1196                     //
1197                     // Something was not processed ...
1198                     //
1199
1200                     try_return( ntStatus = STATUS_ACCESS_DENIED);
1201                 }
1202
1203             }   /* end of switch */
1204
1205             //
1206             // If the parent is not initialized then do it now
1207             //
1208
1209             if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1210                 !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED) &&
1211                 uniPathName.Length > 0)
1212             {
1213
1214                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1215                               AFS_TRACE_LEVEL_VERBOSE,
1216                               "AFSLocateNameEntry (FO: %p) Enumerating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1217                               FileObject,
1218                               &pDirEntry->NameInformation.FileName,
1219                               pCurrentObject->FileId.Cell,
1220                               pCurrentObject->FileId.Volume,
1221                               pCurrentObject->FileId.Vnode,
1222                               pCurrentObject->FileId.Unique));
1223
1224                 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1225                                 TRUE);
1226
1227                 if( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1228                 {
1229
1230                     ntStatus = AFSEnumerateDirectory( AuthGroup,
1231                                                       pCurrentObject,
1232                                                       TRUE);
1233
1234                     if( !NT_SUCCESS( ntStatus))
1235                     {
1236
1237                         AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1238
1239                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1240                                       AFS_TRACE_LEVEL_ERROR,
1241                                       "AFSLocateNameEntry (FO: %p) Failed to enumerate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1242                                       FileObject,
1243                                       &pDirEntry->NameInformation.FileName,
1244                                       pCurrentObject->FileId.Cell,
1245                                       pCurrentObject->FileId.Volume,
1246                                       pCurrentObject->FileId.Vnode,
1247                                       pCurrentObject->FileId.Unique,
1248                                       ntStatus));
1249
1250                         try_return( ntStatus);
1251                     }
1252                 }
1253
1254                 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1255             }
1256             else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1257             {
1258
1259                 if( uniPathName.Length > 0)
1260                 {
1261
1262                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1263                                   AFS_TRACE_LEVEL_ERROR,
1264                                   "AFSLocateNameEntry (FO: %p) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1265                                   FileObject,
1266                                   &pDirEntry->NameInformation.FileName,
1267                                   pCurrentObject->FileId.Cell,
1268                                   pCurrentObject->FileId.Volume,
1269                                   pCurrentObject->FileId.Vnode,
1270                                   pCurrentObject->FileId.Unique));
1271
1272                     // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1273                     // one of the components of the path is not a directory.  However, returning
1274                     // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1275                     // Instead IIS insists on treating the target file as if it is a directory containing
1276                     // a potential web.config file.  NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1277                     // AFS will follow suit.
1278
1279                     ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1280                 }
1281                 else
1282                 {
1283
1284                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1285                                   AFS_TRACE_LEVEL_VERBOSE,
1286                                   "AFSLocateNameEntry (FO: %p) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1287                                   FileObject,
1288                                   &pDirEntry->NameInformation.FileName,
1289                                   pCurrentObject->FileId.Cell,
1290                                   pCurrentObject->FileId.Volume,
1291                                   pCurrentObject->FileId.Vnode,
1292                                   pCurrentObject->FileId.Unique));
1293
1294                     //
1295                     // Pass back the directory entries
1296                     //
1297
1298                     *OutParentDirectoryCB = pParentDirEntry;
1299
1300                     pParentDirEntry = NULL;
1301
1302                     *OutDirectoryCB = pDirEntry;
1303
1304                     pDirEntry = NULL;
1305
1306                     *OutVolumeCB = pCurrentVolume;
1307
1308                     *OutVolumeReferenceReason = VolumeReferenceReason;
1309
1310                     bReleaseCurrentVolume = FALSE;
1311
1312                     *RootPathName = uniFullPathName;
1313                 }
1314
1315                 try_return( ntStatus);
1316             }
1317
1318             //
1319             // If we are at the end of the processing, set our returned information and get out
1320             //
1321
1322             if( uniPathName.Length == 0)
1323             {
1324
1325                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1326                               AFS_TRACE_LEVEL_VERBOSE,
1327                               "AFSLocateNameEntry (FO: %p) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1328                               FileObject,
1329                               &pDirEntry->NameInformation.FileName,
1330                               pCurrentObject->FileId.Cell,
1331                               pCurrentObject->FileId.Volume,
1332                               pCurrentObject->FileId.Vnode,
1333                               pCurrentObject->FileId.Unique));
1334
1335                 //
1336                 // Pass back the directory entries
1337                 //
1338
1339                 *OutParentDirectoryCB = pParentDirEntry;
1340
1341                 pParentDirEntry = NULL;
1342
1343                 *OutDirectoryCB = pDirEntry;
1344
1345                 pDirEntry = NULL;
1346
1347                 *OutVolumeCB = pCurrentVolume;
1348
1349                 *OutVolumeReferenceReason = VolumeReferenceReason;
1350
1351                 bReleaseCurrentVolume = FALSE;
1352
1353                 *RootPathName = uniFullPathName;
1354
1355                 try_return( ntStatus);
1356             }
1357
1358             //
1359             // We may have returned to the top of the while( TRUE)
1360             //
1361             if( bSubstituteName &&
1362                 uniSearchName.Buffer != NULL)
1363             {
1364
1365                 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1366
1367                 bSubstituteName = FALSE;
1368
1369                 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1370                 uniSearchName.Buffer = NULL;
1371             }
1372
1373             ulSubstituteIndex = 1;
1374
1375             ntStatus = STATUS_SUCCESS;
1376
1377             //
1378             // Get the next component name
1379             //
1380
1381             FsRtlDissectName( uniPathName,
1382                               &uniComponentName,
1383                               &uniRemainingPath);
1384
1385             //
1386             // Check for the . and .. in the path
1387             //
1388
1389             if( RtlCompareUnicodeString( &uniComponentName,
1390                                          &uniNoOpName,
1391                                          TRUE) == 0)
1392             {
1393
1394                 uniPathName = uniRemainingPath;
1395
1396                 continue;
1397             }
1398
1399             if( RtlCompareUnicodeString( &uniComponentName,
1400                                          &uniRelativeName,
1401                                          TRUE) == 0)
1402             {
1403
1404                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1405                               AFS_TRACE_LEVEL_VERBOSE,
1406                               "AFSLocateNameEntry (FO: %p) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1407                               FileObject,
1408                               &pDirEntry->NameInformation.FileName,
1409                               pCurrentObject->FileId.Cell,
1410                               pCurrentObject->FileId.Volume,
1411                               pCurrentObject->FileId.Vnode,
1412                               pCurrentObject->FileId.Unique));
1413
1414                 //
1415                 // Need to back up one entry in the name array
1416                 //
1417                 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1418
1419                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1420                               AFS_TRACE_LEVEL_VERBOSE,
1421                               "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1422                               &pDirEntry->NameInformation.FileName,
1423                               pDirEntry,
1424                               NULL,
1425                               lCount));
1426
1427                 ASSERT( lCount >= 0);
1428
1429                 pDirEntry = AFSBackupEntry( NameArray);
1430
1431                 if( pDirEntry == NULL)
1432                 {
1433
1434                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1435                                   AFS_TRACE_LEVEL_ERROR,
1436                                   "AFSLocateNameEntry AFSBackupEntry failed\n"));
1437
1438                     try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1439                 }
1440
1441                 pCurrentObject = pDirEntry->ObjectInformation;
1442
1443                 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1444
1445                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1446                               AFS_TRACE_LEVEL_VERBOSE,
1447                               "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1448                               &pDirEntry->NameInformation.FileName,
1449                               pDirEntry,
1450                               NULL,
1451                               lCount));
1452
1453                 if ( pParentDirEntry)
1454                 {
1455
1456                     lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1457
1458                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1459                                   AFS_TRACE_LEVEL_VERBOSE,
1460                                   "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1461                                   &pParentDirEntry->NameInformation.FileName,
1462                                   pParentDirEntry,
1463                                   NULL,
1464                                   lCount));
1465
1466                     pParentDirEntry = NULL;
1467                 }
1468
1469                 if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1470                 {
1471
1472                     pParentDirEntry = AFSGetParentEntry( pNameArray);
1473
1474                     ASSERT( pParentDirEntry != pDirEntry);
1475
1476                     if ( pParentDirEntry)
1477                     {
1478
1479                         lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
1480
1481                         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1482                                       AFS_TRACE_LEVEL_VERBOSE,
1483                                       "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
1484                                       &pParentDirEntry->NameInformation.FileName,
1485                                       pParentDirEntry,
1486                                       NULL,
1487                                       lCount));
1488                     }
1489                 }
1490
1491                 if ( pDirEntry->ObjectInformation->VolumeCB != pCurrentVolume)
1492                 {
1493
1494                     lCount = AFSVolumeDecrement( pCurrentVolume,
1495                                                  VolumeReferenceReason);
1496
1497                     AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1498                                   AFS_TRACE_LEVEL_VERBOSE,
1499                                   "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
1500                                   pCurrentVolume,
1501                                   VolumeReferenceReason,
1502                                   lCount));
1503
1504                     pCurrentVolume = pDirEntry->ObjectInformation->VolumeCB;
1505
1506                     VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
1507
1508                     lCount = AFSVolumeIncrement( pCurrentVolume,
1509                                                  VolumeReferenceReason);
1510
1511                     AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1512                                   AFS_TRACE_LEVEL_VERBOSE,
1513                                   "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
1514                                   pCurrentVolume,
1515                                   VolumeReferenceReason,
1516                                   lCount));
1517                 }
1518
1519                 uniPathName = uniRemainingPath;
1520
1521                 continue;
1522             }
1523
1524             //
1525             // Update our pointers
1526             //
1527
1528             if ( pParentDirEntry)
1529             {
1530
1531                 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1532
1533                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1534                               AFS_TRACE_LEVEL_VERBOSE,
1535                               "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1536                               &pParentDirEntry->NameInformation.FileName,
1537                               pParentDirEntry,
1538                               NULL,
1539                               lCount));
1540             }
1541
1542             pParentDirEntry = pDirEntry;
1543
1544             pDirEntry = NULL;
1545
1546             pCurrentObject = NULL;
1547
1548             uniSearchName = uniComponentName;
1549
1550             while( pDirEntry == NULL)
1551             {
1552
1553                 //
1554                 // If the SearchName contains @SYS then we perform the substitution.
1555                 // If there is no substitution we give up.
1556                 //
1557
1558                 if( !bSubstituteName &&
1559                     FsRtlIsNameInExpression( &uniSysName,
1560                                              &uniSearchName,
1561                                              TRUE,
1562                                              NULL))
1563                 {
1564
1565                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1566                                   AFS_TRACE_LEVEL_VERBOSE_2,
1567                                   "AFSLocateNameEntry (FO: %p) Processing @SYS substitution for %wZ Index %08lX\n",
1568                                   FileObject,
1569                                   &uniComponentName,
1570                                   ulSubstituteIndex));
1571
1572                     ntStatus = AFSSubstituteSysName( &uniComponentName,
1573                                                      &uniSearchName,
1574                                                      ulSubstituteIndex);
1575
1576                     if ( NT_SUCCESS( ntStatus))
1577                     {
1578
1579                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1580                                       AFS_TRACE_LEVEL_VERBOSE_2,
1581                                       "AFSLocateNameEntry (FO: %p) Located substitution %wZ for %wZ Index %08lX\n",
1582                                       FileObject,
1583                                       &uniSearchName,
1584                                       &uniComponentName,
1585                                       ulSubstituteIndex));
1586
1587                         //
1588                         // Go reparse the name again
1589                         //
1590
1591                         bSubstituteName = TRUE;
1592
1593                         ulSubstituteIndex++; // For the next entry, if needed
1594
1595                         continue;   // while( pDirEntry == NULL)
1596                     }
1597                     else
1598                     {
1599
1600                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1601                                       AFS_TRACE_LEVEL_ERROR,
1602                                       "AFSLocateNameEntry (FO: %p) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1603                                       FileObject,
1604                                       &uniComponentName,
1605                                       ulSubstituteIndex,
1606                                       ntStatus));
1607
1608                         if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1609                         {
1610
1611                             //
1612                             // Pass back the directory entries
1613                             //
1614
1615                             *OutParentDirectoryCB = pParentDirEntry;
1616
1617                             pParentDirEntry = NULL;
1618
1619                             *OutDirectoryCB = NULL;
1620
1621                             *OutVolumeCB = pCurrentVolume;
1622
1623                             *OutVolumeReferenceReason = VolumeReferenceReason;
1624
1625                             bReleaseCurrentVolume = FALSE;
1626
1627                             if( ComponentName != NULL)
1628                             {
1629
1630                                 *ComponentName = uniComponentName;
1631                             }
1632
1633                             *RootPathName = uniFullPathName;
1634                         }
1635
1636                         //
1637                         // We can't possibly have a pDirEntry since the lookup failed
1638                         //
1639                         try_return( ntStatus);
1640                     }
1641                 }
1642
1643                 //
1644                 // Generate the CRC on the node and perform a case sensitive lookup
1645                 //
1646
1647                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1648                               AFS_TRACE_LEVEL_VERBOSE_2,
1649                               "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case sensitive\n",
1650                               FileObject,
1651                               &uniSearchName));
1652
1653                 ulCRC = AFSGenerateCRC( &uniSearchName,
1654                                         FALSE);
1655
1656                 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1657                                   TRUE);
1658
1659                 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1660                                                 ulCRC,
1661                                                 &pDirEntry);
1662
1663                 if( pDirEntry == NULL)
1664                 {
1665
1666                     //
1667                     // Missed so perform a case insensitive lookup
1668                     //
1669
1670                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1671                                   AFS_TRACE_LEVEL_VERBOSE_2,
1672                                   "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case insensitive\n",
1673                                   FileObject,
1674                                   &uniSearchName));
1675
1676                     ulCRC = AFSGenerateCRC( &uniSearchName,
1677                                             TRUE);
1678
1679                     AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1680                                                       ulCRC,
1681                                                       &pDirEntry);
1682
1683                     if( pDirEntry == NULL)
1684                     {
1685
1686                         //
1687                         // OK, if this component is a valid short name then try
1688                         // a lookup in the short name tree
1689                         //
1690
1691                         if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1692                             RtlIsNameLegalDOS8Dot3( &uniSearchName,
1693                                                     NULL,
1694                                                     NULL))
1695                         {
1696
1697                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1698                                           AFS_TRACE_LEVEL_VERBOSE_2,
1699                                           "AFSLocateNameEntry (FO: %p) Searching for entry %wZ short name\n",
1700                                           FileObject,
1701                                           &uniSearchName));
1702
1703                             AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1704                                                         ulCRC,
1705                                                         &pDirEntry);
1706                         }
1707
1708                         if ( pDirEntry == NULL &&
1709                              pParentDirEntry->ObjectInformation->VolumeCB == AFSGlobalRoot)
1710                         {
1711
1712                             //
1713                             // Check with the service to see if this is a valid cell name
1714                             // that can be automatically resolved.  Drop the shared TreeLock
1715                             // since AFSCheckCellName must acquire it exclusively.
1716                             //
1717
1718                             AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1719
1720                             ntStatus = AFSCheckCellName( AuthGroup,
1721                                                          &uniSearchName,
1722                                                          &pDirEntry);
1723
1724                             AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1725                                               TRUE);
1726                         }
1727
1728                         if( pDirEntry == NULL)
1729                         {
1730
1731                             //
1732                             // If we substituted a name then reset our search name and try again
1733                             //
1734
1735                             if( bSubstituteName)
1736                             {
1737
1738                                 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1739
1740                                 uniSearchName = uniComponentName;
1741
1742                                 bSubstituteName = FALSE;
1743
1744                                 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1745
1746                                 continue;       // while( pDirEntry == NULL)
1747                             }
1748
1749                             //
1750                             // Node name not found so get out
1751                             //
1752
1753                             AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1754
1755                             if( uniRemainingPath.Length > 0)
1756                             {
1757
1758                                 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1759
1760                                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1761                                               AFS_TRACE_LEVEL_VERBOSE,
1762                                               "AFSLocateNameEntry (FO: %p) Returning path not found for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
1763                                               FileObject,
1764                                               &uniSearchName,
1765                                               pParentDirEntry->ObjectInformation->FileId.Cell,
1766                                               pParentDirEntry->ObjectInformation->FileId.Volume,
1767                                               pParentDirEntry->ObjectInformation->FileId.Vnode,
1768                                               pParentDirEntry->ObjectInformation->FileId.Unique));
1769                             }
1770                             else
1771                             {
1772
1773                                 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1774
1775                                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1776                                               AFS_TRACE_LEVEL_VERBOSE,
1777                                               "AFSLocateNameEntry (FO: %p) Returning name not found for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
1778                                               FileObject,
1779                                               &uniSearchName,
1780                                               pParentDirEntry->ObjectInformation->FileId.Cell,
1781                                               pParentDirEntry->ObjectInformation->FileId.Volume,
1782                                               pParentDirEntry->ObjectInformation->FileId.Vnode,
1783                                               pParentDirEntry->ObjectInformation->FileId.Unique));
1784
1785                                 //
1786                                 // Pass back the directory entries
1787                                 //
1788
1789                                 *OutParentDirectoryCB = pParentDirEntry;
1790
1791                                 pParentDirEntry = NULL;
1792
1793                                 *OutDirectoryCB = NULL;
1794
1795                                 *OutVolumeCB = pCurrentVolume;
1796
1797                                 *OutVolumeReferenceReason = VolumeReferenceReason;
1798
1799                                 bReleaseCurrentVolume = FALSE;
1800
1801                                 if( ComponentName != NULL)
1802                                 {
1803
1804                                     *ComponentName = uniComponentName;
1805                                 }
1806
1807                                 *RootPathName = uniFullPathName;
1808                             }
1809
1810                             try_return( ntStatus);
1811                         }
1812                     }
1813                     else
1814                     {
1815
1816                         //
1817                         // Here we have a match on the case insensitive lookup for the name. If there
1818                         // Is more than one link entry for this node then fail the lookup request
1819                         //
1820
1821                         pCurrentObject = pDirEntry->ObjectInformation;
1822
1823                         if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1824                             pDirEntry->CaseInsensitiveList.fLink != NULL)
1825                         {
1826
1827                             //
1828                             // Increment our dir entry ref count since we will decrement it on exit
1829                             //
1830
1831                             lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1832
1833                             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1834                                           AFS_TRACE_LEVEL_VERBOSE,
1835                                           "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1836                                           &pDirEntry->NameInformation.FileName,
1837                                           pDirEntry,
1838                                           NULL,
1839                                           lCount));
1840
1841                             AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1842
1843                             try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1844                         }
1845                     }
1846                 }
1847
1848                 if( pDirEntry != NULL)
1849                 {
1850
1851                     //
1852                     // If the verify flag is set on the parent and the current entry is deleted
1853                     // revalidate the parent and search again.
1854                     //
1855
1856                     pCurrentObject = pDirEntry->ObjectInformation;
1857
1858                     if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1859                         BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1860                     {
1861
1862                         AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1863
1864                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1865                                       AFS_TRACE_LEVEL_VERBOSE,
1866                                       "AFSLocateNameEntry (FO: %p) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1867                                       FileObject,
1868                                       &pParentDirEntry->NameInformation.FileName,
1869                                       pParentDirEntry->ObjectInformation->FileId.Cell,
1870                                       pParentDirEntry->ObjectInformation->FileId.Volume,
1871                                       pParentDirEntry->ObjectInformation->FileId.Vnode,
1872                                       pParentDirEntry->ObjectInformation->FileId.Unique));
1873
1874                         //
1875                         // Directory TreeLock should be exclusively held
1876                         //
1877
1878                         AFSAcquireExcl( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1879                                         TRUE);
1880
1881                         ntStatus = AFSVerifyEntry( AuthGroup,
1882                                                    pParentDirEntry);
1883
1884                         AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1885
1886                         if( !NT_SUCCESS( ntStatus))
1887                         {
1888
1889                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1890                                           AFS_TRACE_LEVEL_ERROR,
1891                                           "AFSLocateNameEntry (FO: %p) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1892                                           FileObject,
1893                                           &pParentDirEntry->NameInformation.FileName,
1894                                           pParentDirEntry->ObjectInformation->FileId.Cell,
1895                                           pParentDirEntry->ObjectInformation->FileId.Volume,
1896                                           pParentDirEntry->ObjectInformation->FileId.Vnode,
1897                                           pParentDirEntry->ObjectInformation->FileId.Unique,
1898                                           ntStatus));
1899
1900                             try_return( ntStatus);
1901                         }
1902
1903                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1904                                       AFS_TRACE_LEVEL_VERBOSE,
1905                                       "AFSLocateNameEntry (FO: %p) Reprocessing component %wZ in parent %wZ\n",
1906                                       FileObject,
1907                                       &uniSearchName,
1908                                       &pParentDirEntry->NameInformation.FileName));
1909
1910
1911                         pDirEntry = NULL;
1912
1913                         pCurrentObject = NULL;
1914
1915                         continue;
1916                     }
1917
1918                     //
1919                     // Increment our dir entry ref count
1920                     //
1921
1922                     lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1923
1924                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1925                                   AFS_TRACE_LEVEL_VERBOSE,
1926                                   "AFSLocateNameEntry Increment6 count on %wZ DE %p Ccb %p Cnt %d\n",
1927                                   &pDirEntry->NameInformation.FileName,
1928                                   pDirEntry,
1929                                   NULL,
1930                                   lCount));
1931                 }
1932
1933                 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1934
1935             } // End while( pDirEntry == NULL)
1936
1937             //
1938             // If we have a dirEntry for this component, perform some basic validation on it
1939             //
1940
1941             if( pDirEntry != NULL)
1942             {
1943
1944                 pCurrentObject = pDirEntry->ObjectInformation;
1945
1946                 if (BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1947                 {
1948
1949                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1950                                   AFS_TRACE_LEVEL_ERROR,
1951                                   "AFSLocateNameEntry (FO: %p) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1952                                   FileObject,
1953                                   &pDirEntry->NameInformation.FileName,
1954                                   pCurrentObject->FileId.Cell,
1955                                   pCurrentObject->FileId.Volume,
1956                                   pCurrentObject->FileId.Vnode,
1957                                   pCurrentObject->FileId.Unique));
1958
1959                     //
1960                     // This entry was deleted through the invalidation call back so perform cleanup
1961                     // on the entry
1962                     //
1963
1964                     if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1965                     {
1966
1967                         pParentObjectInfo = AFSFindObjectInfo( pCurrentObject->VolumeCB,
1968                                                                &pCurrentObject->ParentFileId,
1969                                                                FALSE);
1970                     }
1971
1972                     ASSERT( pParentObjectInfo != NULL);
1973
1974                     AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1975                                     TRUE);
1976
1977                     AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1978                                     TRUE);
1979
1980                     lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1981
1982                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1983                                   AFS_TRACE_LEVEL_VERBOSE,
1984                                   "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1985                                   &pDirEntry->NameInformation.FileName,
1986                                   pDirEntry,
1987                                   NULL,
1988                                   lCount));
1989
1990                     ASSERT( lCount >= 0);
1991
1992                     if( lCount == 0 &&
1993                         pDirEntry->NameArrayReferenceCount <= 0)
1994                     {
1995
1996                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1997                                       AFS_TRACE_LEVEL_VERBOSE,
1998                                       "AFSLocateNameEntry Deleting dir entry %p (%p) for %wZ\n",
1999                                       pDirEntry,
2000                                       pCurrentObject,
2001                                       &pDirEntry->NameInformation.FileName));
2002
2003                         //
2004                         // Remove and delete the directory entry from the parent list
2005                         //
2006
2007                         AFSDeleteDirEntry( pParentObjectInfo,
2008                                            &pDirEntry);
2009
2010                         AFSAcquireShared( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
2011                                           TRUE);
2012
2013                         if( pCurrentObject->ObjectReferenceCount <= 0)
2014                         {
2015
2016                             if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
2017                             {
2018
2019                                 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2020                                               AFS_TRACE_LEVEL_VERBOSE,
2021                                               "AFSLocateNameEntry Removing object %p from volume tree\n",
2022                                               pCurrentObject));
2023
2024                                 AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
2025                                                     &pCurrentObject->TreeEntry);
2026
2027                                 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
2028                             }
2029                         }
2030
2031                         AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
2032                     }
2033                     else
2034                     {
2035
2036                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2037                                       AFS_TRACE_LEVEL_VERBOSE,
2038                                       "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
2039                                       pDirEntry,
2040                                       &pDirEntry->NameInformation.FileName));
2041
2042                         SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
2043
2044                         AFSRemoveNameEntry( pParentObjectInfo,
2045                                             pDirEntry);
2046                     }
2047
2048                     AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2049
2050                     AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
2051
2052                     //
2053                     // We deleted the dir entry so check if there is any remaining portion
2054                     // of the name to process.
2055                     //
2056
2057                     if( uniRemainingPath.Length > 0)
2058                     {
2059
2060                         ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
2061
2062                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2063                                       AFS_TRACE_LEVEL_VERBOSE,
2064                                       "AFSLocateNameEntry (FO: %p) Returning path not found(2) for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
2065                                       FileObject,
2066                                       &uniComponentName,
2067                                       pParentObjectInfo->FileId.Cell,
2068                                       pParentObjectInfo->FileId.Volume,
2069                                       pParentObjectInfo->FileId.Vnode,
2070                                       pParentObjectInfo->FileId.Unique));
2071
2072                         AFSReleaseObjectInfo( &pParentObjectInfo);
2073                     }
2074                     else
2075                     {
2076
2077                         ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
2078
2079                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2080                                       AFS_TRACE_LEVEL_VERBOSE,
2081                                       "AFSLocateNameEntry (FO: %p) Returning name not found(2) for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
2082                                       FileObject,
2083                                       &uniComponentName,
2084                                       pParentObjectInfo->FileId.Cell,
2085                                       pParentObjectInfo->FileId.Volume,
2086                                       pParentObjectInfo->FileId.Vnode,
2087                                       pParentObjectInfo->FileId.Unique));
2088
2089                         AFSReleaseObjectInfo( &pParentObjectInfo);
2090
2091                         //
2092                         // Pass back the directory entries
2093                         //
2094
2095                         *OutParentDirectoryCB = pParentDirEntry;
2096
2097                         pParentDirEntry = NULL;
2098
2099                         *OutDirectoryCB = NULL;
2100
2101                         *OutVolumeCB = pCurrentVolume;
2102
2103                         *OutVolumeReferenceReason = VolumeReferenceReason;
2104
2105                         bReleaseCurrentVolume = FALSE;
2106
2107                         if( ComponentName != NULL)
2108                         {
2109
2110                             *ComponentName = uniComponentName;
2111                         }
2112
2113                         *RootPathName = uniFullPathName;
2114                     }
2115                 }
2116             }
2117
2118             if( ntStatus != STATUS_SUCCESS)
2119             {
2120
2121                 try_return( ntStatus);
2122             }
2123
2124             //
2125             // If we ended up substituting a name in the component then update
2126             // the full path and update the pointers
2127             //
2128
2129             if( bSubstituteName)
2130             {
2131
2132                 BOOLEAN bRelativeOpen = FALSE;
2133
2134                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2135                               AFS_TRACE_LEVEL_VERBOSE_2,
2136                               "AFSLocateNameEntry (FO: %p) Substituting %wZ into %wZ Index %08lX\n",
2137                               FileObject,
2138                               &uniSearchName,
2139                               &uniComponentName,
2140                               ulSubstituteIndex));
2141
2142                 if( FileObject != NULL &&
2143                     FileObject->RelatedFileObject != NULL)
2144                 {
2145
2146                     bRelativeOpen = TRUE;
2147                 }
2148
2149                 //
2150                 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
2151                 // and free the prior Buffer contents but only if the fourth
2152                 // parameter is TRUE.
2153                 //
2154
2155                 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
2156                                                     &uniComponentName,
2157                                                     &uniSearchName,
2158                                                     &uniRemainingPath,
2159                                                     bRelativeOpen ||
2160                                                     bAllocatedSymLinkBuffer ||
2161                                                     bSubstitutedName);
2162
2163                 if( !NT_SUCCESS( ntStatus))
2164                 {
2165
2166                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2167                                   AFS_TRACE_LEVEL_ERROR,
2168                                   "AFSLocateNameEntry (FO: %p) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
2169                                   FileObject,
2170                                   &uniSearchName,
2171                                   &uniComponentName,
2172                                   ulSubstituteIndex,
2173                                   ntStatus));
2174
2175                     try_return( ntStatus);
2176                 }
2177
2178                 //
2179                 // We have substituted a name into the buffer so if we do this again for this
2180                 // path, we need to free up the buffer we allocated.
2181                 //
2182
2183                 bSubstitutedName = TRUE;
2184             }
2185
2186             //
2187             // Update the search parameters
2188             //
2189
2190             uniPathName = uniRemainingPath;
2191
2192             //
2193             // Check if the is a SymLink entry but has no Target FileID or Name. In this
2194             // case it might be a DFS Link so let's go and evaluate it to be sure
2195             //
2196
2197             if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
2198                 ( pCurrentObject->TargetFileId.Vnode == 0 ||
2199                   pDirEntry->NameInformation.TargetName.Length == 0))
2200             {
2201
2202                 ntStatus = AFSValidateSymLink( AuthGroup,
2203                                                pDirEntry);
2204
2205                 if( !NT_SUCCESS( ntStatus))
2206                 {
2207
2208                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2209                                   AFS_TRACE_LEVEL_ERROR,
2210                                   "AFSLocateNameEntry (FO: %p) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2211                                   FileObject,
2212                                   &pDirEntry->NameInformation.FileName,
2213                                   pCurrentObject->FileId.Cell,
2214                                   pCurrentObject->FileId.Volume,
2215                                   pCurrentObject->FileId.Vnode,
2216                                   pCurrentObject->FileId.Unique,
2217                                   ntStatus));
2218
2219                     try_return( ntStatus);
2220                 }
2221             }
2222
2223             //
2224             // Update the name array
2225             //
2226
2227             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2228                           AFS_TRACE_LEVEL_VERBOSE,
2229                           "AFSLocateNameEntry (FO: %p) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2230                           FileObject,
2231                           &pDirEntry->NameInformation.FileName,
2232                           pCurrentObject->FileId.Cell,
2233                           pCurrentObject->FileId.Volume,
2234                           pCurrentObject->FileId.Vnode,
2235                           pCurrentObject->FileId.Unique));
2236
2237             ntStatus = AFSInsertNextElement( pNameArray,
2238                                              pDirEntry);
2239
2240             if( !NT_SUCCESS( ntStatus))
2241             {
2242
2243                 try_return( ntStatus);
2244             }
2245         }       // while (TRUE)
2246
2247 try_exit:
2248
2249         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2250                       AFS_TRACE_LEVEL_VERBOSE,
2251                       "AFSLocateNameEntry (FO: %p) Completed processing %wZ Status %08lX\n",
2252                       FileObject,
2253                       RootPathName,
2254                       ntStatus));
2255
2256         if( ( !NT_SUCCESS( ntStatus) &&
2257               ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
2258             ntStatus == STATUS_REPARSE)
2259         {
2260             if( RootPathName->Buffer != uniFullPathName.Buffer)
2261             {
2262
2263                 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
2264             }
2265         }
2266         else
2267         {
2268
2269             if( *OutParentDirectoryCB != NULL)
2270             {
2271
2272                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2273                               AFS_TRACE_LEVEL_VERBOSE,
2274                               "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
2275                               &(*OutParentDirectoryCB)->NameInformation.FileName,
2276                               *OutParentDirectoryCB,
2277                               NULL,
2278                               (*OutParentDirectoryCB)->DirOpenReferenceCount));
2279             }
2280
2281             if( *OutDirectoryCB != NULL)
2282             {
2283
2284                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2285                               AFS_TRACE_LEVEL_VERBOSE,
2286                               "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
2287                               &(*OutDirectoryCB)->NameInformation.FileName,
2288                               *OutDirectoryCB,
2289                               NULL,
2290                               (*OutDirectoryCB)->DirOpenReferenceCount));
2291             }
2292         }
2293
2294         if( pDirEntry != NULL)
2295         {
2296
2297             lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
2298
2299             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2300                           AFS_TRACE_LEVEL_VERBOSE,
2301                           "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
2302                           &pDirEntry->NameInformation.FileName,
2303                           pDirEntry,
2304                           NULL,
2305                           lCount));
2306
2307             ASSERT( lCount >= 0);
2308         }
2309
2310         if( pParentDirEntry != NULL)
2311         {
2312
2313             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
2314
2315             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2316                           AFS_TRACE_LEVEL_VERBOSE,
2317                           "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
2318                           &pParentDirEntry->NameInformation.FileName,
2319                           pParentDirEntry,
2320                           NULL,
2321                           lCount));
2322
2323             ASSERT( lCount >= 0);
2324         }
2325
2326         if( bReleaseCurrentVolume)
2327         {
2328
2329             ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
2330
2331             lCount = AFSVolumeDecrement( pCurrentVolume,
2332                                          VolumeReferenceReason);
2333
2334             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2335                           AFS_TRACE_LEVEL_VERBOSE,
2336                           "AFSLocateNameEntry Decrement7 count on volume %p Reason %u Cnt %d\n",
2337                           pCurrentVolume,
2338                           VolumeReferenceReason,
2339                           lCount));
2340
2341             bReleaseCurrentVolume = FALSE;
2342         }
2343
2344         if( bSubstituteName &&
2345             uniSearchName.Buffer != NULL)
2346         {
2347
2348             AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
2349         }
2350     }
2351
2352     return ntStatus;
2353 }
2354
2355 NTSTATUS
2356 AFSCreateDirEntry( IN GUID            *AuthGroup,
2357                    IN AFSObjectInfoCB *ParentObjectInfo,
2358                    IN AFSDirectoryCB *ParentDirCB,
2359                    IN PUNICODE_STRING FileName,
2360                    IN PUNICODE_STRING ComponentName,
2361                    IN ULONG Attributes,
2362                    IN OUT AFSDirectoryCB **DirEntry)
2363 {
2364
2365     UNREFERENCED_PARAMETER(FileName);
2366     NTSTATUS ntStatus = STATUS_SUCCESS;
2367     AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
2368     LARGE_INTEGER liFileSize = {0,0};
2369     LONG lCount;
2370
2371     __Enter
2372     {
2373
2374         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2375                       AFS_TRACE_LEVEL_VERBOSE_2,
2376                       "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
2377                       &ParentDirCB->NameInformation.FileName,
2378                       ParentObjectInfo->FileId.Cell,
2379                       ParentObjectInfo->FileId.Volume,
2380                       ParentObjectInfo->FileId.Vnode,
2381                       ParentObjectInfo->FileId.Unique,
2382                       ComponentName,
2383                       Attributes));
2384
2385         //
2386         // OK, before inserting the node into the parent tree, issue
2387         // the request to the service for node creation
2388         // We will need to drop the lock on the parent node since the create
2389         // could cause a callback into the file system to invalidate it's cache
2390         //
2391
2392         ntStatus = AFSNotifyFileCreate( AuthGroup,
2393                                         ParentObjectInfo,
2394                                         &liFileSize,
2395                                         Attributes,
2396                                         ComponentName,
2397                                         &pDirNode);
2398
2399         //
2400         // If the returned status is STATUS_REPARSE then the entry exists
2401         // and we raced, get out.
2402
2403         if( ntStatus == STATUS_REPARSE)
2404         {
2405
2406             *DirEntry = pDirNode;
2407
2408             try_return( ntStatus = STATUS_SUCCESS);
2409         }
2410
2411         if( !NT_SUCCESS( ntStatus))
2412         {
2413
2414             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2415                           AFS_TRACE_LEVEL_ERROR,
2416                           "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
2417                           &ParentDirCB->NameInformation.FileName,
2418                           ParentObjectInfo->FileId.Cell,
2419                           ParentObjectInfo->FileId.Volume,
2420                           ParentObjectInfo->FileId.Vnode,
2421                           ParentObjectInfo->FileId.Unique,
2422                           ComponentName,
2423                           Attributes,
2424                           ntStatus));
2425
2426             try_return( ntStatus);
2427         }
2428
2429         //
2430         // If AFSNotifyFileCreate returns pDirNode != NULL, then its
2431         // DirOpenReferenceCount is held.
2432         //
2433
2434         AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2435                         TRUE);
2436
2437         //
2438         // Before attempting to insert the new entry, check if we need to validate the parent
2439         //
2440
2441         if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2442         {
2443
2444             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2445                           AFS_TRACE_LEVEL_VERBOSE,
2446                           "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2447                           &ParentDirCB->NameInformation.FileName,
2448                           ParentObjectInfo->FileId.Cell,
2449                           ParentObjectInfo->FileId.Volume,
2450                           ParentObjectInfo->FileId.Vnode,
2451                           ParentObjectInfo->FileId.Unique));
2452
2453             ntStatus = AFSVerifyEntry( AuthGroup,
2454                                        ParentDirCB);
2455
2456             if( !NT_SUCCESS( ntStatus))
2457             {
2458
2459                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2460                               AFS_TRACE_LEVEL_ERROR,
2461                               "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2462                               &ParentDirCB->NameInformation.FileName,
2463                               ParentObjectInfo->FileId.Cell,
2464                               ParentObjectInfo->FileId.Volume,
2465                               ParentObjectInfo->FileId.Vnode,
2466                               ParentObjectInfo->FileId.Unique,
2467                               ntStatus));
2468
2469                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2470
2471                 try_return( ntStatus);
2472             }
2473         }
2474
2475         //
2476         // Check for the entry in the event we raced with some other thread
2477         //
2478
2479         AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2480                                         (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2481                                         &pExistingDirNode);
2482
2483         if( pExistingDirNode != NULL)
2484         {
2485             if (AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2486                                &pExistingDirNode->ObjectInformation->FileId))
2487             {
2488
2489                 if ( pExistingDirNode != pDirNode)
2490                 {
2491
2492                     lCount = InterlockedDecrement( &pDirNode->DirOpenReferenceCount);
2493
2494                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2495                                   AFS_TRACE_LEVEL_VERBOSE,
2496                                   "AFSCreateDirEntry Decrement count on %wZ DE %p Cnt %d\n",
2497                                   &pDirNode->NameInformation.FileName,
2498                                   pDirNode,
2499                                   lCount));
2500
2501                     AFSDeleteDirEntry( ParentObjectInfo,
2502                                        &pDirNode);
2503
2504                     lCount = InterlockedIncrement( &pExistingDirNode->DirOpenReferenceCount);
2505
2506                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2507                                   AFS_TRACE_LEVEL_VERBOSE,
2508                                   "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2509                                   &pExistingDirNode->NameInformation.FileName,
2510                                   pExistingDirNode,
2511                                   lCount));
2512
2513                     *DirEntry = pExistingDirNode;
2514                 }
2515
2516                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2517
2518                 try_return( ntStatus = STATUS_SUCCESS);
2519             }
2520             else
2521             {
2522
2523                 //
2524                 // Need to tear down this entry and rebuild it below
2525                 //
2526
2527                 if( pExistingDirNode->DirOpenReferenceCount <= 0 &&
2528                     pExistingDirNode->NameArrayReferenceCount <= 0)
2529                 {
2530
2531                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2532                                   AFS_TRACE_LEVEL_VERBOSE,
2533                                   "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2534                                   pExistingDirNode,
2535                                   &pExistingDirNode->NameInformation.FileName,
2536                                   pExistingDirNode->ObjectInformation->FileId.Cell,
2537                                   pExistingDirNode->ObjectInformation->FileId.Volume,
2538                                   pExistingDirNode->ObjectInformation->FileId.Vnode,
2539                                   pExistingDirNode->ObjectInformation->FileId.Unique,
2540                                   pDirNode->ObjectInformation->FileId.Cell,
2541                                   pDirNode->ObjectInformation->FileId.Volume,
2542                                   pDirNode->ObjectInformation->FileId.Vnode,
2543                                   pDirNode->ObjectInformation->FileId.Unique));
2544
2545                     AFSDeleteDirEntry( ParentObjectInfo,
2546                                        &pExistingDirNode);
2547                 }
2548                 else
2549                 {
2550
2551                     SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2552
2553                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2554                                   AFS_TRACE_LEVEL_VERBOSE,
2555                                   "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2556                                   pExistingDirNode,
2557                                   &pExistingDirNode->NameInformation.FileName,
2558                                   pExistingDirNode->ObjectInformation->FileId.Cell,
2559                                   pExistingDirNode->ObjectInformation->FileId.Volume,
2560                                   pExistingDirNode->ObjectInformation->FileId.Vnode,
2561                                   pExistingDirNode->ObjectInformation->FileId.Unique,
2562                                   pDirNode->ObjectInformation->FileId.Cell,
2563                                   pDirNode->ObjectInformation->FileId.Volume,
2564                                   pDirNode->ObjectInformation->FileId.Vnode,
2565                                   pDirNode->ObjectInformation->FileId.Unique));
2566
2567                     AFSRemoveNameEntry( ParentObjectInfo,
2568                                         pExistingDirNode);
2569                 }
2570             }
2571         }
2572
2573         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2574                       AFS_TRACE_LEVEL_VERBOSE_2,
2575                       "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2576                       &ParentDirCB->NameInformation.FileName,
2577                       ParentObjectInfo->FileId.Cell,
2578                       ParentObjectInfo->FileId.Volume,
2579                       ParentObjectInfo->FileId.Vnode,
2580                       ParentObjectInfo->FileId.Unique,
2581                       ComponentName));
2582
2583         //
2584         // Insert the directory node
2585         //
2586
2587         AFSInsertDirectoryNode( ParentObjectInfo,
2588                                 pDirNode,
2589                                 TRUE);
2590
2591         //
2592         // Pass back the dir entry
2593         //
2594
2595         *DirEntry = pDirNode;
2596
2597         AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2598
2599 try_exit:
2600
2601         NOTHING;
2602     }
2603
2604     return ntStatus;
2605 }
2606
2607 void
2608 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2609                         IN AFSDirectoryCB *DirEntry,
2610                         IN BOOLEAN InsertInEnumList)
2611 {
2612
2613     LONG lCount;
2614
2615     __Enter
2616     {
2617
2618         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2619
2620         //
2621         // Insert the node into the directory node tree
2622         //
2623
2624         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2625                       AFS_TRACE_LEVEL_VERBOSE,
2626                       "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2627                       DirEntry,
2628                       &DirEntry->NameInformation.FileName));
2629
2630         ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2631
2632         if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2633         {
2634
2635             ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2636
2637             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2638                           AFS_TRACE_LEVEL_VERBOSE,
2639                           "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2640                           DirEntry,
2641                           &DirEntry->NameInformation.FileName));
2642         }
2643         else
2644         {
2645
2646             AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2647                                             DirEntry);
2648
2649             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2650                           AFS_TRACE_LEVEL_VERBOSE,
2651                           "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2652                           DirEntry,
2653                           &DirEntry->NameInformation.FileName));
2654         }
2655
2656         if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2657         {
2658
2659             ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2660
2661             SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2662
2663             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2664                           AFS_TRACE_LEVEL_VERBOSE,
2665                           "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2666                           DirEntry,
2667                           &DirEntry->NameInformation.FileName));
2668         }
2669         else
2670         {
2671
2672             AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2673                                               DirEntry);
2674
2675             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2676                           AFS_TRACE_LEVEL_VERBOSE,
2677                           "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2678                           DirEntry,
2679                           &DirEntry->NameInformation.FileName));
2680         }
2681
2682         //
2683         // Into the shortname tree
2684         //
2685
2686         if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2687         {
2688
2689             if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2690             {
2691
2692                 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2693
2694                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2695                               AFS_TRACE_LEVEL_VERBOSE,
2696                               "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2697                               DirEntry,
2698                               &DirEntry->NameInformation.FileName));
2699
2700                 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2701             }
2702             else
2703             {
2704
2705                 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2706                                                              DirEntry)))
2707                 {
2708                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2709                                   AFS_TRACE_LEVEL_VERBOSE,
2710                                   "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2711                                   DirEntry,
2712                                   &DirEntry->NameInformation.FileName));
2713                 }
2714                 else
2715                 {
2716                     SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2717
2718                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2719                                   AFS_TRACE_LEVEL_VERBOSE,
2720                                   "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2721                                   DirEntry,
2722                                   &DirEntry->NameInformation.FileName));
2723                 }
2724             }
2725         }
2726
2727         if( InsertInEnumList)
2728         {
2729
2730             //
2731             // And insert the node into the directory list
2732             //
2733
2734             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2735                           AFS_TRACE_LEVEL_VERBOSE,
2736                           "AFSInsertDirectoryNode Inserting entry %p %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2737                           DirEntry,
2738                           &DirEntry->NameInformation.FileName,
2739                           DirEntry->ObjectInformation->FileId.Cell,
2740                           DirEntry->ObjectInformation->FileId.Volume,
2741                           DirEntry->ObjectInformation->FileId.Vnode,
2742                           DirEntry->ObjectInformation->FileId.Unique));
2743
2744             if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2745             {
2746
2747                 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2748             }
2749             else
2750             {
2751
2752                 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2753
2754                 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2755             }
2756
2757             ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2758
2759             SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2760
2761             lCount = InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2762
2763             AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2764                           AFS_TRACE_LEVEL_VERBOSE,
2765                           "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2766                           &DirEntry->NameInformation.FileName,
2767                           lCount,
2768                           ParentObjectInfo->FileId.Cell,
2769                           ParentObjectInfo->FileId.Volume,
2770                           ParentObjectInfo->FileId.Vnode,
2771                           ParentObjectInfo->FileId.Unique));
2772         }
2773     }
2774
2775     return;
2776 }
2777
2778 void
2779 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2780                    IN AFSDirectoryCB **ppDirEntry)
2781 {