Windows: Test NameArrayReferenceCount before deletion
[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         AFSDbgLogMsg( 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         AFSDbgLogMsg( 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         AFSDbgLogMsg( 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                 AFSDbgLogMsg( 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                 AFSDbgLogMsg( 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                 AFSDbgLogMsg( 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                     AFSDbgLogMsg( 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                 AFSDbgLogMsg( 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                             AFSDbgLogMsg( 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                             AFSDbgLogMsg( 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                         AFSDbgLogMsg( 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                         AFSDbgLogMsg( 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                             AFSDbgLogMsg( 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                         AFSDbgLogMsg( 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                         AFSDbgLogMsg( 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                         AFSDbgLogMsg( 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                         //
645                         // Increment our reference on this dir entry
646                         //
647
648                         lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
649
650                         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
651                                       AFS_TRACE_LEVEL_VERBOSE,
652                                       "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
653                                       &pDirEntry->NameInformation.FileName,
654                                       pDirEntry,
655                                       NULL,
656                                       lCount);
657
658                         if ( pParentDirEntry)
659                         {
660
661                             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
662
663                             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
664                                           AFS_TRACE_LEVEL_VERBOSE,
665                                           "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
666                                           &pParentDirEntry->NameInformation.FileName,
667                                           pParentDirEntry,
668                                           NULL,
669                                           lCount);
670
671                             pParentDirEntry = NULL;
672                         }
673
674                         if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
675                         {
676
677                             pParentDirEntry = AFSGetParentEntry( pNameArray);
678
679                             ASSERT( pParentDirEntry != pDirEntry);
680
681                             lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
682
683                             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
684                                           AFS_TRACE_LEVEL_VERBOSE,
685                                           "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
686                                           &pParentDirEntry->NameInformation.FileName,
687                                           pParentDirEntry,
688                                           NULL,
689                                           lCount);
690                         }
691                     }
692                     else
693                     {
694
695                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
696                                       AFS_TRACE_LEVEL_VERBOSE,
697                                       "AFSLocateNameEntry (FO: %p) Processing absolute symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
698                                       FileObject,
699                                       &pDirEntry->NameInformation.TargetName,
700                                       &pDirEntry->NameInformation.FileName,
701                                       pCurrentObject->FileId.Cell,
702                                       pCurrentObject->FileId.Volume,
703                                       pCurrentObject->FileId.Vnode,
704                                       pCurrentObject->FileId.Unique);
705
706                         if ( !AFSIsAbsoluteAFSName( &pDirEntry->NameInformation.TargetName))
707                         {
708
709                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
710                                           AFS_TRACE_LEVEL_ERROR,
711                                           "AFSLocateNameEntry Name %wZ contains invalid server name\n",
712                                           &pDirEntry->NameInformation.TargetName);
713
714                             //
715                             // The correct response would be STATUS_OBJECT_PATH_INVALID
716                             // but that prevents cmd.exe from performing a recursive
717                             // directory enumeration when opening a directory entry
718                             // that represents a symlink to an invalid path is discovered.
719                             //
720
721                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
722
723                             try_return( ntStatus = STATUS_OBJECT_PATH_NOT_FOUND);
724                         }
725
726                         //
727                         // We'll substitute this name into the current process name
728                         // starting at where we sit in the path
729                         //
730
731                         uniTempName.Length = 0;
732                         uniTempName.MaximumLength = pDirEntry->NameInformation.TargetName.Length +
733                                                                     sizeof( WCHAR) +
734                                                                     uniRemainingPath.Length;
735
736                         uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
737                                                                                 uniTempName.MaximumLength,
738                                                                                 AFS_NAME_BUFFER_TWO_TAG);
739
740                         if( uniTempName.Buffer == NULL)
741                         {
742
743                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
744
745                             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
746                         }
747
748                         if( bAllocatedSymLinkBuffer ||
749                             bSubstitutedName)
750                         {
751
752                             pTmpBuffer = uniFullPathName.Buffer;
753                         }
754
755                         bAllocatedSymLinkBuffer = TRUE;
756
757                         //
758                         // Have we parsed this name yet? Better have at least once ...
759                         //
760
761                         if( uniComponentName.Length == 0)
762                         {
763                             ASSERT( FALSE);
764                         }
765
766                         //
767                         // Copy in the target name ...
768                         //
769
770                         RtlCopyMemory( uniTempName.Buffer,
771                                        &pDirEntry->NameInformation.TargetName.Buffer[ AFSMountRootName.Length/sizeof( WCHAR)],
772                                        pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length);
773
774                         uniTempName.Length = pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length;
775
776                         //
777                         // And now any remaining portion of the name
778                         //
779
780                         if( uniRemainingPath.Length > 0)
781                         {
782
783                             if( uniRemainingPath.Buffer[ 0] != L'\\')
784                             {
785
786                                 uniRemainingPath.Buffer--;
787                                 uniRemainingPath.Length += sizeof( WCHAR);
788                             }
789
790                             RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
791                                            uniRemainingPath.Buffer,
792                                            uniRemainingPath.Length);
793
794                             uniTempName.Length += uniRemainingPath.Length;
795                         }
796
797                         uniFullPathName = uniTempName;
798
799                         uniPathName = uniTempName;
800
801                         if( pTmpBuffer != NULL)
802                         {
803
804                             AFSExFreePoolWithTag( pTmpBuffer, 0);
805                         }
806
807                         AFSReleaseResource( &pDirEntry->NonPaged->Lock);
808
809                         //
810                         // If our current volume is not the global root then make it so ...
811                         //
812
813                         if( pCurrentVolume != AFSGlobalRoot)
814                         {
815
816                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
817                                           AFS_TRACE_LEVEL_VERBOSE,
818                                           "AFSLocateNameEntry (FO: %p) Current volume not global, resetting for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
819                                           FileObject,
820                                           &pDirEntry->NameInformation.FileName,
821                                           pCurrentObject->FileId.Cell,
822                                           pCurrentObject->FileId.Volume,
823                                           pCurrentObject->FileId.Vnode,
824                                           pCurrentObject->FileId.Unique);
825
826                             lCount = AFSVolumeDecrement( pCurrentVolume,
827                                                          VolumeReferenceReason);
828
829                             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
830                                           AFS_TRACE_LEVEL_VERBOSE,
831                                           "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
832                                           pCurrentVolume,
833                                           VolumeReferenceReason,
834                                           lCount);
835
836                             pCurrentVolume = AFSGlobalRoot;
837
838                             VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
839
840                             lCount = AFSVolumeIncrement( pCurrentVolume,
841                                                          VolumeReferenceReason);
842
843                             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
844                                           AFS_TRACE_LEVEL_VERBOSE,
845                                           "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
846                                           pCurrentVolume,
847                                           VolumeReferenceReason,
848                                           lCount);
849                         }
850
851                         //
852                         // Dereference our current dir entry
853                         //
854
855                         lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
856
857                         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
858                                       AFS_TRACE_LEVEL_VERBOSE,
859                                       "AFSLocateNameEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
860                                       &pDirEntry->NameInformation.FileName,
861                                       pDirEntry,
862                                       NULL,
863                                       lCount);
864
865                         ASSERT( lCount >= 0);
866
867                         pDirEntry = pCurrentVolume->DirectoryCB;
868
869                         //
870                         // Reference the new dir entry
871                         //
872
873                         lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
874
875                         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
876                                       AFS_TRACE_LEVEL_VERBOSE,
877                                       "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
878                                       &pDirEntry->NameInformation.FileName,
879                                       pDirEntry,
880                                       NULL,
881                                       lCount);
882
883                         //
884                         // Reset the name array
885                         // Persist the link count in the name array
886                         //
887
888                         lLinkCount = pNameArray->LinkCount;
889
890                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
891                                       AFS_TRACE_LEVEL_VERBOSE,
892                                       "AFSLocateNameEntry (FO: %p) Resetting name array for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
893                                       FileObject,
894                                       &pDirEntry->NameInformation.FileName,
895                                       pCurrentObject->FileId.Cell,
896                                       pCurrentObject->FileId.Volume,
897                                       pCurrentObject->FileId.Vnode,
898                                       pCurrentObject->FileId.Unique);
899
900                         AFSResetNameArray( pNameArray,
901                                            pDirEntry);
902
903                         pNameArray->LinkCount = lLinkCount;
904
905                         if ( pParentDirEntry)
906                         {
907
908                             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
909
910                             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
911                                           AFS_TRACE_LEVEL_VERBOSE,
912                                           "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
913                                           &pParentDirEntry->NameInformation.FileName,
914                                           pParentDirEntry,
915                                           NULL,
916                                           lCount);
917
918                             pParentDirEntry = NULL;
919                         }
920                     }
921
922                     //
923                     // Increment our link count
924                     //
925
926                     lCount = InterlockedIncrement( &pNameArray->LinkCount);
927
928                     continue;
929                 }
930
931                 case AFS_FILE_TYPE_MOUNTPOINT:
932                 {
933
934                     //
935                     // Check if the flag is set to NOT evaluate a mount point
936                     // and we are done with the parsing
937                     //
938
939                     if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL) &&
940                         uniRemainingPath.Length == 0)
941                     {
942
943                         //
944                         // Pass back the directory entries
945                         //
946
947                         *OutParentDirectoryCB = pParentDirEntry;
948
949                         pParentDirEntry = NULL;
950
951                         *OutDirectoryCB = pDirEntry;
952
953                         pDirEntry = NULL;
954
955                         *OutVolumeCB = pCurrentVolume;
956
957                         *OutVolumeReferenceReason = VolumeReferenceReason;
958
959                         bReleaseCurrentVolume = FALSE;
960
961                         *RootPathName = uniFullPathName;
962
963                         try_return( ntStatus);
964                     }
965
966                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
967                                   AFS_TRACE_LEVEL_VERBOSE,
968                                   "AFSLocateNameEntry (FO: %p) Building MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
969                                   FileObject,
970                                   &pDirEntry->NameInformation.FileName,
971                                   pCurrentObject->FileId.Cell,
972                                   pCurrentObject->FileId.Volume,
973                                   pCurrentObject->FileId.Vnode,
974                                   pCurrentObject->FileId.Unique);
975
976                     //
977                     // Go retrieve the target entry for this node
978                     // Release the current volume cb entry since we would
979                     // have lock inversion in the following call
980                     // Also decrement the ref count on the volume
981                     //
982
983                     ntStatus = AFSBuildMountPointTarget( AuthGroup,
984                                                          pDirEntry,
985                                                          &pTargetVolume);
986
987                     if( !NT_SUCCESS( ntStatus))
988                     {
989
990                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
991                                       AFS_TRACE_LEVEL_ERROR,
992                                       "AFSLocateNameEntry (FO: %p) Failed to build MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
993                                       FileObject,
994                                       &pDirEntry->NameInformation.FileName,
995                                       pCurrentObject->FileId.Cell,
996                                       pCurrentObject->FileId.Volume,
997                                       pCurrentObject->FileId.Vnode,
998                                       pCurrentObject->FileId.Unique,
999                                       ntStatus);
1000
1001                         try_return( ntStatus);
1002                     }
1003
1004                     ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
1005
1006                     lCount = AFSVolumeDecrement( pCurrentVolume,
1007                                                  VolumeReferenceReason);
1008
1009                     AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1010                                   AFS_TRACE_LEVEL_VERBOSE,
1011                                   "AFSLocateNameEntry Decrement2 count on volume %p Reason %u Cnt %d\n",
1012                                   pCurrentVolume,
1013                                   VolumeReferenceReason,
1014                                   lCount);
1015
1016                     pCurrentVolume = pTargetVolume;
1017
1018                     pTargetVolume = NULL;
1019
1020                     ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
1021
1022                     VolumeReferenceReason = AFS_VOLUME_REFERENCE_MOUNTPT;
1023
1024                     //
1025                     // We want to restart processing here on the new parent ...
1026                     // Deref and ref count the entries
1027                     //
1028
1029                     lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1030
1031                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1032                                   AFS_TRACE_LEVEL_VERBOSE,
1033                                   "AFSLocateNameEntry Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
1034                                   &pDirEntry->NameInformation.FileName,
1035                                   pDirEntry,
1036                                   NULL,
1037                                   lCount);
1038
1039                     ASSERT( lCount >= 0);
1040
1041                     pDirEntry = pCurrentVolume->DirectoryCB;
1042
1043                     lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1044
1045                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1046                                   AFS_TRACE_LEVEL_VERBOSE,
1047                                   "AFSLocateNameEntry Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
1048                                   &pDirEntry->NameInformation.FileName,
1049                                   pDirEntry,
1050                                   NULL,
1051                                   lCount);
1052
1053                     //
1054                     // The name array stores both the mount point and the target.
1055                     // Insert the target.
1056                     //
1057
1058                     AFSInsertNextElement( pNameArray,
1059                                           pDirEntry);
1060
1061                     if ( pParentDirEntry)
1062                     {
1063
1064                         lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1065
1066                         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1067                                       AFS_TRACE_LEVEL_VERBOSE,
1068                                       "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1069                                       &pParentDirEntry->NameInformation.FileName,
1070                                       pParentDirEntry,
1071                                       NULL,
1072                                       lCount);
1073
1074                         pParentDirEntry = NULL;
1075                     }
1076
1077                     //
1078                     // Increment our link count
1079                     //
1080
1081                     lCount = InterlockedIncrement( &pNameArray->LinkCount);
1082
1083                     continue;
1084                 }
1085
1086                 case AFS_FILE_TYPE_DFSLINK:
1087                 {
1088
1089                     if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL))
1090                     {
1091
1092                         //
1093                         // Pass back the directory entries
1094                         //
1095
1096                         *OutParentDirectoryCB = pParentDirEntry;
1097
1098                         pParentDirEntry = NULL;
1099
1100                         *OutDirectoryCB = pDirEntry;
1101
1102                         pDirEntry = NULL;
1103
1104                         *OutVolumeCB = pCurrentVolume;
1105
1106                         *OutVolumeReferenceReason = VolumeReferenceReason;
1107
1108                         bReleaseCurrentVolume = FALSE;
1109
1110                         *RootPathName = uniFullPathName;
1111
1112                         try_return( ntStatus);
1113                     }
1114
1115                     //
1116                     // This is a DFS link so we need to update the file name and return STATUS_REPARSE to the
1117                     // system for it to reevaluate it
1118                     //
1119
1120                     if( FileObject != NULL)
1121                     {
1122
1123                         ntStatus = AFSProcessDFSLink( pDirEntry,
1124                                                       FileObject,
1125                                                       &uniRemainingPath,
1126                                                       AuthGroup);
1127                     }
1128                     else
1129                     {
1130
1131                         //
1132                         // This is where we have been re-entered from an NP evaluation call via the BuildBranch()
1133                         // routine.
1134                         //
1135
1136                         ntStatus = STATUS_INVALID_PARAMETER;
1137                     }
1138
1139                     if( ntStatus != STATUS_SUCCESS &&
1140                         ntStatus != STATUS_REPARSE)
1141                     {
1142
1143                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1144                                       AFS_TRACE_LEVEL_ERROR,
1145                                       "AFSLocateNameEntry (FO: %p) Failed to process DFSLink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1146                                       FileObject,
1147                                       &pDirEntry->NameInformation.FileName,
1148                                       pCurrentObject->FileId.Cell,
1149                                       pCurrentObject->FileId.Volume,
1150                                       pCurrentObject->FileId.Vnode,
1151                                       pCurrentObject->FileId.Unique,
1152                                       ntStatus);
1153                     }
1154
1155                     try_return( ntStatus);
1156                 }
1157
1158                 case AFS_FILE_TYPE_UNKNOWN:
1159                 case AFS_FILE_TYPE_INVALID:
1160                 {
1161
1162                     //
1163                     // Something was not processed ...
1164                     //
1165
1166                     try_return( ntStatus = STATUS_ACCESS_DENIED);
1167                 }
1168
1169             }   /* end of switch */
1170
1171             //
1172             // If the parent is not initialized then do it now
1173             //
1174
1175             if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1176                 !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED) &&
1177                 uniPathName.Length > 0)
1178             {
1179
1180                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1181                               AFS_TRACE_LEVEL_VERBOSE,
1182                               "AFSLocateNameEntry (FO: %p) Enumerating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1183                               FileObject,
1184                               &pDirEntry->NameInformation.FileName,
1185                               pCurrentObject->FileId.Cell,
1186                               pCurrentObject->FileId.Volume,
1187                               pCurrentObject->FileId.Vnode,
1188                               pCurrentObject->FileId.Unique);
1189
1190                 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1191                                 TRUE);
1192
1193                 if( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1194                 {
1195
1196                     ntStatus = AFSEnumerateDirectory( AuthGroup,
1197                                                       pCurrentObject,
1198                                                       TRUE);
1199
1200                     if( !NT_SUCCESS( ntStatus))
1201                     {
1202
1203                         AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1204
1205                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1206                                       AFS_TRACE_LEVEL_ERROR,
1207                                       "AFSLocateNameEntry (FO: %p) Failed to enumerate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1208                                       FileObject,
1209                                       &pDirEntry->NameInformation.FileName,
1210                                       pCurrentObject->FileId.Cell,
1211                                       pCurrentObject->FileId.Volume,
1212                                       pCurrentObject->FileId.Vnode,
1213                                       pCurrentObject->FileId.Unique,
1214                                       ntStatus);
1215
1216                         try_return( ntStatus);
1217                     }
1218                 }
1219
1220                 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1221             }
1222             else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1223             {
1224
1225                 if( uniPathName.Length > 0)
1226                 {
1227
1228                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1229                                   AFS_TRACE_LEVEL_ERROR,
1230                                   "AFSLocateNameEntry (FO: %p) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1231                                   FileObject,
1232                                   &pDirEntry->NameInformation.FileName,
1233                                   pCurrentObject->FileId.Cell,
1234                                   pCurrentObject->FileId.Volume,
1235                                   pCurrentObject->FileId.Vnode,
1236                                   pCurrentObject->FileId.Unique);
1237
1238                     // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1239                     // one of the components of the path is not a directory.  However, returning
1240                     // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1241                     // Instead IIS insists on treating the target file as if it is a directory containing
1242                     // a potential web.config file.  NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1243                     // AFS will follow suit.
1244
1245                     ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1246                 }
1247                 else
1248                 {
1249
1250                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1251                                   AFS_TRACE_LEVEL_VERBOSE,
1252                                   "AFSLocateNameEntry (FO: %p) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1253                                   FileObject,
1254                                   &pDirEntry->NameInformation.FileName,
1255                                   pCurrentObject->FileId.Cell,
1256                                   pCurrentObject->FileId.Volume,
1257                                   pCurrentObject->FileId.Vnode,
1258                                   pCurrentObject->FileId.Unique);
1259
1260                     //
1261                     // Pass back the directory entries
1262                     //
1263
1264                     *OutParentDirectoryCB = pParentDirEntry;
1265
1266                     pParentDirEntry = NULL;
1267
1268                     *OutDirectoryCB = pDirEntry;
1269
1270                     pDirEntry = NULL;
1271
1272                     *OutVolumeCB = pCurrentVolume;
1273
1274                     *OutVolumeReferenceReason = VolumeReferenceReason;
1275
1276                     bReleaseCurrentVolume = FALSE;
1277
1278                     *RootPathName = uniFullPathName;
1279                 }
1280
1281                 try_return( ntStatus);
1282             }
1283
1284             //
1285             // If we are at the end of the processing, set our returned information and get out
1286             //
1287
1288             if( uniPathName.Length == 0)
1289             {
1290
1291                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1292                               AFS_TRACE_LEVEL_VERBOSE,
1293                               "AFSLocateNameEntry (FO: %p) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1294                               FileObject,
1295                               &pDirEntry->NameInformation.FileName,
1296                               pCurrentObject->FileId.Cell,
1297                               pCurrentObject->FileId.Volume,
1298                               pCurrentObject->FileId.Vnode,
1299                               pCurrentObject->FileId.Unique);
1300
1301                 //
1302                 // Pass back the directory entries
1303                 //
1304
1305                 *OutParentDirectoryCB = pParentDirEntry;
1306
1307                 pParentDirEntry = NULL;
1308
1309                 *OutDirectoryCB = pDirEntry;
1310
1311                 pDirEntry = NULL;
1312
1313                 *OutVolumeCB = pCurrentVolume;
1314
1315                 *OutVolumeReferenceReason = VolumeReferenceReason;
1316
1317                 bReleaseCurrentVolume = FALSE;
1318
1319                 *RootPathName = uniFullPathName;
1320
1321                 try_return( ntStatus);
1322             }
1323
1324             //
1325             // We may have returned to the top of the while( TRUE)
1326             //
1327             if( bSubstituteName &&
1328                 uniSearchName.Buffer != NULL)
1329             {
1330
1331                 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1332
1333                 bSubstituteName = FALSE;
1334
1335                 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1336                 uniSearchName.Buffer = NULL;
1337             }
1338
1339             ulSubstituteIndex = 1;
1340
1341             ntStatus = STATUS_SUCCESS;
1342
1343             //
1344             // Get the next component name
1345             //
1346
1347             FsRtlDissectName( uniPathName,
1348                               &uniComponentName,
1349                               &uniRemainingPath);
1350
1351             //
1352             // Check for the . and .. in the path
1353             //
1354
1355             if( RtlCompareUnicodeString( &uniComponentName,
1356                                          &uniNoOpName,
1357                                          TRUE) == 0)
1358             {
1359
1360                 uniPathName = uniRemainingPath;
1361
1362                 continue;
1363             }
1364
1365             if( RtlCompareUnicodeString( &uniComponentName,
1366                                          &uniRelativeName,
1367                                          TRUE) == 0)
1368             {
1369
1370                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1371                               AFS_TRACE_LEVEL_VERBOSE,
1372                               "AFSLocateNameEntry (FO: %p) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1373                               FileObject,
1374                               &pDirEntry->NameInformation.FileName,
1375                               pCurrentObject->FileId.Cell,
1376                               pCurrentObject->FileId.Volume,
1377                               pCurrentObject->FileId.Vnode,
1378                               pCurrentObject->FileId.Unique);
1379
1380                 //
1381                 // Need to back up one entry in the name array
1382                 //
1383                 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1384
1385                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1386                               AFS_TRACE_LEVEL_VERBOSE,
1387                               "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1388                               &pDirEntry->NameInformation.FileName,
1389                               pDirEntry,
1390                               NULL,
1391                               lCount);
1392
1393                 ASSERT( lCount >= 0);
1394
1395                 pDirEntry = AFSBackupEntry( NameArray);
1396
1397                 if( pDirEntry == NULL)
1398                 {
1399
1400                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1401                                   AFS_TRACE_LEVEL_ERROR,
1402                                   "AFSLocateNameEntry AFSBackupEntry failed\n");
1403
1404                     try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1405                 }
1406
1407                 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1408
1409                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1410                               AFS_TRACE_LEVEL_VERBOSE,
1411                               "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1412                               &pDirEntry->NameInformation.FileName,
1413                               pDirEntry,
1414                               NULL,
1415                               lCount);
1416
1417                 if ( pParentDirEntry)
1418                 {
1419
1420                     lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1421
1422                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1423                                   AFS_TRACE_LEVEL_VERBOSE,
1424                                   "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1425                                   &pParentDirEntry->NameInformation.FileName,
1426                                   pParentDirEntry,
1427                                   NULL,
1428                                   lCount);
1429
1430                     pParentDirEntry = NULL;
1431                 }
1432
1433                 if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1434                 {
1435
1436                     pParentDirEntry = AFSGetParentEntry( pNameArray);
1437
1438                     ASSERT( pParentDirEntry != pDirEntry);
1439
1440                     if ( pParentDirEntry)
1441                     {
1442
1443                         lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
1444
1445                         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1446                                       AFS_TRACE_LEVEL_VERBOSE,
1447                                       "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
1448                                       &pParentDirEntry->NameInformation.FileName,
1449                                       pParentDirEntry,
1450                                       NULL,
1451                                       lCount);
1452                     }
1453                 }
1454
1455                 uniPathName = uniRemainingPath;
1456
1457                 continue;
1458             }
1459
1460             //
1461             // Update our pointers
1462             //
1463
1464             if ( pParentDirEntry)
1465             {
1466
1467                 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1468
1469                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1470                               AFS_TRACE_LEVEL_VERBOSE,
1471                               "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1472                               &pParentDirEntry->NameInformation.FileName,
1473                               pParentDirEntry,
1474                               NULL,
1475                               lCount);
1476             }
1477
1478             pParentDirEntry = pDirEntry;
1479
1480             pDirEntry = NULL;
1481
1482             uniSearchName = uniComponentName;
1483
1484             while( pDirEntry == NULL)
1485             {
1486
1487                 //
1488                 // If the SearchName contains @SYS then we perform the substitution.
1489                 // If there is no substitution we give up.
1490                 //
1491
1492                 if( !bSubstituteName &&
1493                     FsRtlIsNameInExpression( &uniSysName,
1494                                              &uniSearchName,
1495                                              TRUE,
1496                                              NULL))
1497                 {
1498
1499                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1500                                   AFS_TRACE_LEVEL_VERBOSE_2,
1501                                   "AFSLocateNameEntry (FO: %p) Processing @SYS substitution for %wZ Index %08lX\n",
1502                                   FileObject,
1503                                   &uniComponentName,
1504                                   ulSubstituteIndex);
1505
1506                     ntStatus = AFSSubstituteSysName( &uniComponentName,
1507                                                      &uniSearchName,
1508                                                      ulSubstituteIndex);
1509
1510                     if ( NT_SUCCESS( ntStatus))
1511                     {
1512
1513                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1514                                       AFS_TRACE_LEVEL_VERBOSE_2,
1515                                       "AFSLocateNameEntry (FO: %p) Located substitution %wZ for %wZ Index %08lX\n",
1516                                       FileObject,
1517                                       &uniSearchName,
1518                                       &uniComponentName,
1519                                       ulSubstituteIndex);
1520
1521                         //
1522                         // Go reparse the name again
1523                         //
1524
1525                         bSubstituteName = TRUE;
1526
1527                         ulSubstituteIndex++; // For the next entry, if needed
1528
1529                         continue;   // while( pDirEntry == NULL)
1530                     }
1531                     else
1532                     {
1533
1534                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1535                                       AFS_TRACE_LEVEL_ERROR,
1536                                       "AFSLocateNameEntry (FO: %p) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1537                                       FileObject,
1538                                       &uniComponentName,
1539                                       ulSubstituteIndex,
1540                                       ntStatus);
1541
1542                         if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1543                         {
1544
1545                             //
1546                             // Pass back the directory entries
1547                             //
1548
1549                             *OutParentDirectoryCB = pParentDirEntry;
1550
1551                             pParentDirEntry = NULL;
1552
1553                             *OutDirectoryCB = NULL;
1554
1555                             *OutVolumeCB = pCurrentVolume;
1556
1557                             *OutVolumeReferenceReason = VolumeReferenceReason;
1558
1559                             bReleaseCurrentVolume = FALSE;
1560
1561                             if( ComponentName != NULL)
1562                             {
1563
1564                                 *ComponentName = uniComponentName;
1565                             }
1566
1567                             *RootPathName = uniFullPathName;
1568                         }
1569
1570                         //
1571                         // We can't possibly have a pDirEntry since the lookup failed
1572                         //
1573                         try_return( ntStatus);
1574                     }
1575                 }
1576
1577                 //
1578                 // Generate the CRC on the node and perform a case sensitive lookup
1579                 //
1580
1581                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1582                               AFS_TRACE_LEVEL_VERBOSE_2,
1583                               "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case sensitive\n",
1584                               FileObject,
1585                               &uniSearchName);
1586
1587                 ulCRC = AFSGenerateCRC( &uniSearchName,
1588                                         FALSE);
1589
1590                 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1591                                   TRUE);
1592
1593                 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1594                                                 ulCRC,
1595                                                 &pDirEntry);
1596
1597                 if( pDirEntry == NULL)
1598                 {
1599
1600                     //
1601                     // Missed so perform a case insensitive lookup
1602                     //
1603
1604                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1605                                   AFS_TRACE_LEVEL_VERBOSE_2,
1606                                   "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case insensitive\n",
1607                                   FileObject,
1608                                   &uniSearchName);
1609
1610                     ulCRC = AFSGenerateCRC( &uniSearchName,
1611                                             TRUE);
1612
1613                     AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1614                                                       ulCRC,
1615                                                       &pDirEntry);
1616
1617                     if( pDirEntry == NULL)
1618                     {
1619
1620                         //
1621                         // OK, if this component is a valid short name then try
1622                         // a lookup in the short name tree
1623                         //
1624
1625                         if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1626                             RtlIsNameLegalDOS8Dot3( &uniSearchName,
1627                                                     NULL,
1628                                                     NULL))
1629                         {
1630
1631                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1632                                           AFS_TRACE_LEVEL_VERBOSE_2,
1633                                           "AFSLocateNameEntry (FO: %p) Searching for entry %wZ short name\n",
1634                                           FileObject,
1635                                           &uniSearchName);
1636
1637                             AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1638                                                         ulCRC,
1639                                                         &pDirEntry);
1640                         }
1641
1642                         if ( pDirEntry == NULL &&
1643                              pParentDirEntry->ObjectInformation->VolumeCB == AFSGlobalRoot)
1644                         {
1645
1646                             //
1647                             // Check with the service to see if this is a valid cell name
1648                             // that can be automatically resolved.  Drop the shared TreeLock
1649                             // since AFSCheckCellName must acquire it exclusively.
1650                             //
1651
1652                             AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1653
1654                             ntStatus = AFSCheckCellName( AuthGroup,
1655                                                          &uniSearchName,
1656                                                          &pDirEntry);
1657
1658                             AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1659                                               TRUE);
1660                         }
1661
1662                         if( pDirEntry == NULL)
1663                         {
1664
1665                             //
1666                             // If we substituted a name then reset our search name and try again
1667                             //
1668
1669                             if( bSubstituteName)
1670                             {
1671
1672                                 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1673
1674                                 uniSearchName = uniComponentName;
1675
1676                                 bSubstituteName = FALSE;
1677
1678                                 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1679
1680                                 continue;       // while( pDirEntry == NULL)
1681                             }
1682
1683                             //
1684                             // Node name not found so get out
1685                             //
1686
1687                             AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1688
1689                             if( uniRemainingPath.Length > 0)
1690                             {
1691
1692                                 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1693
1694                                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1695                                               AFS_TRACE_LEVEL_VERBOSE,
1696                                               "AFSLocateNameEntry (FO: %p) Returning path not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1697                                               FileObject,
1698                                               &uniSearchName,
1699                                               pCurrentObject->FileId.Cell,
1700                                               pCurrentObject->FileId.Volume,
1701                                               pCurrentObject->FileId.Vnode,
1702                                               pCurrentObject->FileId.Unique);
1703                             }
1704                             else
1705                             {
1706
1707                                 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1708
1709                                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1710                                               AFS_TRACE_LEVEL_VERBOSE,
1711                                               "AFSLocateNameEntry (FO: %p) Returning name not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1712                                               FileObject,
1713                                               &uniSearchName,
1714                                               pCurrentObject->FileId.Cell,
1715                                               pCurrentObject->FileId.Volume,
1716                                               pCurrentObject->FileId.Vnode,
1717                                               pCurrentObject->FileId.Unique);
1718
1719                                 //
1720                                 // Pass back the directory entries
1721                                 //
1722
1723                                 *OutParentDirectoryCB = pParentDirEntry;
1724
1725                                 pParentDirEntry = NULL;
1726
1727                                 *OutDirectoryCB = NULL;
1728
1729                                 *OutVolumeCB = pCurrentVolume;
1730
1731                                 *OutVolumeReferenceReason = VolumeReferenceReason;
1732
1733                                 bReleaseCurrentVolume = FALSE;
1734
1735                                 if( ComponentName != NULL)
1736                                 {
1737
1738                                     *ComponentName = uniComponentName;
1739                                 }
1740
1741                                 *RootPathName = uniFullPathName;
1742                             }
1743
1744                             try_return( ntStatus);
1745                         }
1746                     }
1747                     else
1748                     {
1749
1750                         //
1751                         // Here we have a match on the case insensitive lookup for the name. If there
1752                         // Is more than one link entry for this node then fail the lookup request
1753                         //
1754
1755                         if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1756                             pDirEntry->CaseInsensitiveList.fLink != NULL)
1757                         {
1758
1759                             //
1760                             // Increment our dir entry ref count since we will decrement it on exit
1761                             //
1762
1763                             lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1764
1765                             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1766                                           AFS_TRACE_LEVEL_VERBOSE,
1767                                           "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1768                                           &pDirEntry->NameInformation.FileName,
1769                                           pDirEntry,
1770                                           NULL,
1771                                           lCount);
1772
1773                             AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1774
1775                             try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1776                         }
1777                     }
1778                 }
1779
1780                 if( pDirEntry != NULL)
1781                 {
1782
1783                     //
1784                     // If the verify flag is set on the parent and the current entry is deleted
1785                     // revalidate the parent and search again.
1786                     //
1787
1788                     if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1789                         BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1790                     {
1791
1792                         AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1793
1794                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1795                                       AFS_TRACE_LEVEL_VERBOSE,
1796                                       "AFSLocateNameEntry (FO: %p) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1797                                       FileObject,
1798                                       &pParentDirEntry->NameInformation.FileName,
1799                                       pParentDirEntry->ObjectInformation->FileId.Cell,
1800                                       pParentDirEntry->ObjectInformation->FileId.Volume,
1801                                       pParentDirEntry->ObjectInformation->FileId.Vnode,
1802                                       pParentDirEntry->ObjectInformation->FileId.Unique);
1803
1804                         //
1805                         // Directory TreeLock should be exclusively held
1806                         //
1807
1808                         AFSAcquireExcl( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1809                                         TRUE);
1810
1811                         ntStatus = AFSVerifyEntry( AuthGroup,
1812                                                    pParentDirEntry);
1813
1814                         AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1815
1816                         if( !NT_SUCCESS( ntStatus))
1817                         {
1818
1819                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1820                                           AFS_TRACE_LEVEL_ERROR,
1821                                           "AFSLocateNameEntry (FO: %p) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1822                                           FileObject,
1823                                           &pParentDirEntry->NameInformation.FileName,
1824                                           pParentDirEntry->ObjectInformation->FileId.Cell,
1825                                           pParentDirEntry->ObjectInformation->FileId.Volume,
1826                                           pParentDirEntry->ObjectInformation->FileId.Vnode,
1827                                           pParentDirEntry->ObjectInformation->FileId.Unique,
1828                                           ntStatus);
1829
1830                             try_return( ntStatus);
1831                         }
1832
1833                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1834                                       AFS_TRACE_LEVEL_VERBOSE,
1835                                       "AFSLocateNameEntry (FO: %p) Reprocessing component %wZ in parent %wZ\n",
1836                                       FileObject,
1837                                       &uniSearchName,
1838                                       &pParentDirEntry->NameInformation.FileName);
1839
1840
1841                         pDirEntry = NULL;
1842
1843                         continue;
1844                     }
1845
1846                     //
1847                     // Increment our dir entry ref count
1848                     //
1849
1850                     lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1851
1852                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1853                                   AFS_TRACE_LEVEL_VERBOSE,
1854                                   "AFSLocateNameEntry Increment6 count on %wZ DE %p Ccb %p Cnt %d\n",
1855                                   &pDirEntry->NameInformation.FileName,
1856                                   pDirEntry,
1857                                   NULL,
1858                                   lCount);
1859                 }
1860
1861                 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1862
1863             } // End while( pDirEntry == NULL)
1864
1865             //
1866             // If we have a dirEntry for this component, perform some basic validation on it
1867             //
1868
1869             if( pDirEntry != NULL &&
1870                 BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1871             {
1872
1873                 pCurrentObject = pDirEntry->ObjectInformation;
1874
1875                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1876                               AFS_TRACE_LEVEL_ERROR,
1877                               "AFSLocateNameEntry (FO: %p) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1878                               FileObject,
1879                               &pDirEntry->NameInformation.FileName,
1880                               pCurrentObject->FileId.Cell,
1881                               pCurrentObject->FileId.Volume,
1882                               pCurrentObject->FileId.Vnode,
1883                               pCurrentObject->FileId.Unique);
1884
1885                 //
1886                 // This entry was deleted through the invalidation call back so perform cleanup
1887                 // on the entry
1888                 //
1889
1890                 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1891                 {
1892
1893                     pParentObjectInfo = AFSFindObjectInfo( pCurrentObject->VolumeCB,
1894                                                            &pCurrentObject->ParentFileId);
1895                 }
1896
1897                 ASSERT( pParentObjectInfo != NULL);
1898
1899                 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1900                                 TRUE);
1901
1902                 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1903                                 TRUE);
1904
1905                 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1906
1907                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1908                               AFS_TRACE_LEVEL_VERBOSE,
1909                               "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1910                               &pDirEntry->NameInformation.FileName,
1911                               pDirEntry,
1912                               NULL,
1913                               lCount);
1914
1915                 ASSERT( lCount >= 0);
1916
1917                 if( lCount == 0 &&
1918                     pDirEntry->NameArrayReferenceCount <= 0)
1919                 {
1920
1921                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1922                                   AFS_TRACE_LEVEL_VERBOSE,
1923                                   "AFSLocateNameEntry Deleting dir entry %p (%p) for %wZ\n",
1924                                   pDirEntry,
1925                                   pCurrentObject,
1926                                   &pDirEntry->NameInformation.FileName);
1927
1928                     //
1929                     // Remove and delete the directory entry from the parent list
1930                     //
1931
1932                     AFSDeleteDirEntry( pParentObjectInfo,
1933                                        pDirEntry);
1934
1935                     AFSAcquireShared( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1936                                       TRUE);
1937
1938                     if( pCurrentObject->ObjectReferenceCount <= 0)
1939                     {
1940
1941                         if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
1942                         {
1943
1944                             AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1945                                           AFS_TRACE_LEVEL_VERBOSE,
1946                                           "AFSLocateNameEntry Removing object %p from volume tree\n",
1947                                           pCurrentObject);
1948
1949                             AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
1950                                                 &pCurrentObject->TreeEntry);
1951
1952                             ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
1953                         }
1954                     }
1955
1956                     AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1957                 }
1958                 else
1959                 {
1960
1961                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1962                                   AFS_TRACE_LEVEL_VERBOSE,
1963                                   "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
1964                                   pDirEntry,
1965                                   &pDirEntry->NameInformation.FileName);
1966
1967                     SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
1968
1969                     AFSRemoveNameEntry( pParentObjectInfo,
1970                                         pDirEntry);
1971                 }
1972
1973                 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1974
1975                 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
1976
1977                 AFSReleaseObjectInfo( &pParentObjectInfo);
1978
1979                 //
1980                 // We deleted the dir entry so check if there is any remaining portion
1981                 // of the name to process.
1982                 //
1983
1984                 if( uniRemainingPath.Length > 0)
1985                 {
1986
1987                     ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1988
1989                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1990                                   AFS_TRACE_LEVEL_VERBOSE,
1991                                   "AFSLocateNameEntry (FO: %p) Returning path not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1992                                   FileObject,
1993                                   &uniComponentName,
1994                                   pCurrentObject->FileId.Cell,
1995                                   pCurrentObject->FileId.Volume,
1996                                   pCurrentObject->FileId.Vnode,
1997                                   pCurrentObject->FileId.Unique);
1998                 }
1999                 else
2000                 {
2001
2002                     ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
2003
2004                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2005                                   AFS_TRACE_LEVEL_VERBOSE,
2006                                   "AFSLocateNameEntry (FO: %p) Returning name not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2007                                   FileObject,
2008                                   &uniComponentName,
2009                                   pCurrentObject->FileId.Cell,
2010                                   pCurrentObject->FileId.Volume,
2011                                   pCurrentObject->FileId.Vnode,
2012                                   pCurrentObject->FileId.Unique);
2013
2014                     //
2015                     // Pass back the directory entries
2016                     //
2017
2018                     *OutParentDirectoryCB = pParentDirEntry;
2019
2020                     pParentDirEntry = NULL;
2021
2022                     *OutDirectoryCB = NULL;
2023
2024                     *OutVolumeCB = pCurrentVolume;
2025
2026                     *OutVolumeReferenceReason = VolumeReferenceReason;
2027
2028                     bReleaseCurrentVolume = FALSE;
2029
2030                     if( ComponentName != NULL)
2031                     {
2032
2033                         *ComponentName = uniComponentName;
2034                     }
2035
2036                     *RootPathName = uniFullPathName;
2037                 }
2038             }
2039
2040             if( ntStatus != STATUS_SUCCESS)
2041             {
2042
2043                 try_return( ntStatus);
2044             }
2045
2046             //
2047             // If we ended up substituting a name in the component then update
2048             // the full path and update the pointers
2049             //
2050
2051             if( bSubstituteName)
2052             {
2053
2054                 BOOLEAN bRelativeOpen = FALSE;
2055
2056                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2057                               AFS_TRACE_LEVEL_VERBOSE_2,
2058                               "AFSLocateNameEntry (FO: %p) Substituting %wZ into %wZ Index %08lX\n",
2059                               FileObject,
2060                               &uniSearchName,
2061                               &uniComponentName,
2062                               ulSubstituteIndex);
2063
2064                 if( FileObject != NULL &&
2065                     FileObject->RelatedFileObject != NULL)
2066                 {
2067
2068                     bRelativeOpen = TRUE;
2069                 }
2070
2071                 //
2072                 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
2073                 // and free the prior Buffer contents but only if the fourth
2074                 // parameter is TRUE.
2075                 //
2076
2077                 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
2078                                                     &uniComponentName,
2079                                                     &uniSearchName,
2080                                                     &uniRemainingPath,
2081                                                     bRelativeOpen ||
2082                                                     bAllocatedSymLinkBuffer ||
2083                                                     bSubstitutedName);
2084
2085                 if( !NT_SUCCESS( ntStatus))
2086                 {
2087
2088                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2089                                   AFS_TRACE_LEVEL_ERROR,
2090                                   "AFSLocateNameEntry (FO: %p) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
2091                                   FileObject,
2092                                   &uniSearchName,
2093                                   &uniComponentName,
2094                                   ulSubstituteIndex,
2095                                   ntStatus);
2096
2097                     try_return( ntStatus);
2098                 }
2099
2100                 //
2101                 // We have substituted a name into the buffer so if we do this again for this
2102                 // path, we need to free up the buffer we allocated.
2103                 //
2104
2105                 bSubstitutedName = TRUE;
2106             }
2107
2108             //
2109             // Update the search parameters
2110             //
2111
2112             uniPathName = uniRemainingPath;
2113
2114             //
2115             // Check if the is a SymLink entry but has no Target FileID or Name. In this
2116             // case it might be a DFS Link so let's go and evaluate it to be sure
2117             //
2118
2119             if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
2120                 ( pCurrentObject->TargetFileId.Vnode == 0 ||
2121                   pDirEntry->NameInformation.TargetName.Length == 0))
2122             {
2123
2124                 ntStatus = AFSValidateSymLink( AuthGroup,
2125                                                pDirEntry);
2126
2127                 if( !NT_SUCCESS( ntStatus))
2128                 {
2129
2130                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2131                                   AFS_TRACE_LEVEL_ERROR,
2132                                   "AFSLocateNameEntry (FO: %p) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2133                                   FileObject,
2134                                   &pDirEntry->NameInformation.FileName,
2135                                   pCurrentObject->FileId.Cell,
2136                                   pCurrentObject->FileId.Volume,
2137                                   pCurrentObject->FileId.Vnode,
2138                                   pCurrentObject->FileId.Unique,
2139                                   ntStatus);
2140
2141                     try_return( ntStatus);
2142                 }
2143             }
2144
2145             //
2146             // Update the name array
2147             //
2148
2149             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2150                           AFS_TRACE_LEVEL_VERBOSE,
2151                           "AFSLocateNameEntry (FO: %p) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2152                           FileObject,
2153                           &pDirEntry->NameInformation.FileName,
2154                           pCurrentObject->FileId.Cell,
2155                           pCurrentObject->FileId.Volume,
2156                           pCurrentObject->FileId.Vnode,
2157                           pCurrentObject->FileId.Unique);
2158
2159             ntStatus = AFSInsertNextElement( pNameArray,
2160                                              pDirEntry);
2161
2162             if( !NT_SUCCESS( ntStatus))
2163             {
2164
2165                 try_return( ntStatus);
2166             }
2167         }       // while (TRUE)
2168
2169 try_exit:
2170
2171         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2172                       AFS_TRACE_LEVEL_VERBOSE,
2173                       "AFSLocateNameEntry (FO: %p) Completed processing %wZ Status %08lX\n",
2174                       FileObject,
2175                       RootPathName,
2176                       ntStatus);
2177
2178         if( ( !NT_SUCCESS( ntStatus) &&
2179               ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
2180             ntStatus == STATUS_REPARSE)
2181         {
2182             if( RootPathName->Buffer != uniFullPathName.Buffer)
2183             {
2184
2185                 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
2186             }
2187         }
2188         else
2189         {
2190
2191             if( *OutParentDirectoryCB != NULL)
2192             {
2193
2194                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2195                               AFS_TRACE_LEVEL_VERBOSE,
2196                               "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
2197                               &(*OutParentDirectoryCB)->NameInformation.FileName,
2198                               *OutParentDirectoryCB,
2199                               NULL,
2200                               (*OutParentDirectoryCB)->DirOpenReferenceCount);
2201             }
2202
2203             if( *OutDirectoryCB != NULL)
2204             {
2205
2206                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2207                               AFS_TRACE_LEVEL_VERBOSE,
2208                               "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
2209                               &(*OutDirectoryCB)->NameInformation.FileName,
2210                               *OutDirectoryCB,
2211                               NULL,
2212                               (*OutDirectoryCB)->DirOpenReferenceCount);
2213             }
2214         }
2215
2216         if( pDirEntry != NULL)
2217         {
2218
2219             lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
2220
2221             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2222                           AFS_TRACE_LEVEL_VERBOSE,
2223                           "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
2224                           &pDirEntry->NameInformation.FileName,
2225                           pDirEntry,
2226                           NULL,
2227                           lCount);
2228
2229             ASSERT( lCount >= 0);
2230         }
2231
2232         if( pParentDirEntry != NULL)
2233         {
2234
2235             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
2236
2237             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2238                           AFS_TRACE_LEVEL_VERBOSE,
2239                           "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
2240                           &pParentDirEntry->NameInformation.FileName,
2241                           pParentDirEntry,
2242                           NULL,
2243                           lCount);
2244
2245             ASSERT( lCount >= 0);
2246         }
2247
2248         if( bReleaseCurrentVolume)
2249         {
2250
2251             ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
2252
2253             lCount = AFSVolumeDecrement( pCurrentVolume,
2254                                          VolumeReferenceReason);
2255
2256             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2257                           AFS_TRACE_LEVEL_VERBOSE,
2258                           "AFSLocateNameEntry Decrement7 count on volume %p Reason %u Cnt %d\n",
2259                           pCurrentVolume,
2260                           VolumeReferenceReason,
2261                           lCount);
2262
2263             bReleaseCurrentVolume = FALSE;
2264         }
2265
2266         if( bSubstituteName &&
2267             uniSearchName.Buffer != NULL)
2268         {
2269
2270             AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
2271         }
2272     }
2273
2274     return ntStatus;
2275 }
2276
2277 NTSTATUS
2278 AFSCreateDirEntry( IN GUID            *AuthGroup,
2279                    IN AFSObjectInfoCB *ParentObjectInfo,
2280                    IN AFSDirectoryCB *ParentDirCB,
2281                    IN PUNICODE_STRING FileName,
2282                    IN PUNICODE_STRING ComponentName,
2283                    IN ULONG Attributes,
2284                    IN OUT AFSDirectoryCB **DirEntry)
2285 {
2286
2287     UNREFERENCED_PARAMETER(FileName);
2288     NTSTATUS ntStatus = STATUS_SUCCESS;
2289     AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
2290     LARGE_INTEGER liFileSize = {0,0};
2291     LONG lCount;
2292
2293     __Enter
2294     {
2295
2296         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2297                       AFS_TRACE_LEVEL_VERBOSE_2,
2298                       "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
2299                       &ParentDirCB->NameInformation.FileName,
2300                       ParentObjectInfo->FileId.Cell,
2301                       ParentObjectInfo->FileId.Volume,
2302                       ParentObjectInfo->FileId.Vnode,
2303                       ParentObjectInfo->FileId.Unique,
2304                       ComponentName,
2305                       Attributes);
2306
2307         //
2308         // OK, before inserting the node into the parent tree, issue
2309         // the request to the service for node creation
2310         // We will need to drop the lock on the parent node since the create
2311         // could cause a callback into the file system to invalidate it's cache
2312         //
2313
2314         ntStatus = AFSNotifyFileCreate( AuthGroup,
2315                                         ParentObjectInfo,
2316                                         &liFileSize,
2317                                         Attributes,
2318                                         ComponentName,
2319                                         &pDirNode);
2320
2321         //
2322         // If the returned status is STATUS_REPARSE then the entry exists
2323         // and we raced, get out.
2324
2325         if( ntStatus == STATUS_REPARSE)
2326         {
2327
2328             *DirEntry = pDirNode;
2329
2330             try_return( ntStatus = STATUS_SUCCESS);
2331         }
2332
2333         if( !NT_SUCCESS( ntStatus))
2334         {
2335
2336             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2337                           AFS_TRACE_LEVEL_ERROR,
2338                           "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
2339                           &ParentDirCB->NameInformation.FileName,
2340                           ParentObjectInfo->FileId.Cell,
2341                           ParentObjectInfo->FileId.Volume,
2342                           ParentObjectInfo->FileId.Vnode,
2343                           ParentObjectInfo->FileId.Unique,
2344                           ComponentName,
2345                           Attributes,
2346                           ntStatus);
2347
2348             try_return( ntStatus);
2349         }
2350
2351         //
2352         // If AFSNotifyFileCreate returns pDirNode != NULL, then its
2353         // DirOpenReferenceCount is held.
2354         //
2355
2356         AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2357                         TRUE);
2358
2359         //
2360         // Before attempting to insert the new entry, check if we need to validate the parent
2361         //
2362
2363         if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2364         {
2365
2366             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2367                           AFS_TRACE_LEVEL_VERBOSE,
2368                           "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2369                           &ParentDirCB->NameInformation.FileName,
2370                           ParentObjectInfo->FileId.Cell,
2371                           ParentObjectInfo->FileId.Volume,
2372                           ParentObjectInfo->FileId.Vnode,
2373                           ParentObjectInfo->FileId.Unique);
2374
2375             ntStatus = AFSVerifyEntry( AuthGroup,
2376                                        ParentDirCB);
2377
2378             if( !NT_SUCCESS( ntStatus))
2379             {
2380
2381                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2382                               AFS_TRACE_LEVEL_ERROR,
2383                               "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2384                               &ParentDirCB->NameInformation.FileName,
2385                               ParentObjectInfo->FileId.Cell,
2386                               ParentObjectInfo->FileId.Volume,
2387                               ParentObjectInfo->FileId.Vnode,
2388                               ParentObjectInfo->FileId.Unique,
2389                               ntStatus);
2390
2391                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2392
2393                 try_return( ntStatus);
2394             }
2395         }
2396
2397         //
2398         // Check for the entry in the event we raced with some other thread
2399         //
2400
2401         AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2402                                         (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2403                                         &pExistingDirNode);
2404
2405         if( pExistingDirNode != NULL)
2406         {
2407             if (AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2408                                &pExistingDirNode->ObjectInformation->FileId))
2409             {
2410
2411                 if ( pExistingDirNode != pDirNode)
2412                 {
2413
2414                     lCount = InterlockedDecrement( &pDirNode->DirOpenReferenceCount);
2415
2416                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2417                                   AFS_TRACE_LEVEL_VERBOSE,
2418                                   "AFSCreateDirEntry Decrement count on %wZ DE %p Cnt %d\n",
2419                                   &pDirNode->NameInformation.FileName,
2420                                   pDirNode,
2421                                   lCount);
2422
2423                     AFSDeleteDirEntry( ParentObjectInfo,
2424                                        pDirNode);
2425
2426                     lCount = InterlockedIncrement( &pExistingDirNode->DirOpenReferenceCount);
2427
2428                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2429                                   AFS_TRACE_LEVEL_VERBOSE,
2430                                   "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2431                                   &pExistingDirNode->NameInformation.FileName,
2432                                   pExistingDirNode,
2433                                   lCount);
2434
2435                     *DirEntry = pExistingDirNode;
2436                 }
2437
2438                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2439
2440                 try_return( ntStatus = STATUS_SUCCESS);
2441             }
2442             else
2443             {
2444
2445                 //
2446                 // Need to tear down this entry and rebuild it below
2447                 //
2448
2449                 if( pExistingDirNode->DirOpenReferenceCount <= 0 &&
2450                     pExistingDirNode->NameArrayReferenceCount <= 0)
2451                 {
2452
2453                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2454                                   AFS_TRACE_LEVEL_VERBOSE,
2455                                   "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2456                                   pExistingDirNode,
2457                                   &pExistingDirNode->NameInformation.FileName,
2458                                   pExistingDirNode->ObjectInformation->FileId.Cell,
2459                                   pExistingDirNode->ObjectInformation->FileId.Volume,
2460                                   pExistingDirNode->ObjectInformation->FileId.Vnode,
2461                                   pExistingDirNode->ObjectInformation->FileId.Unique,
2462                                   pDirNode->ObjectInformation->FileId.Cell,
2463                                   pDirNode->ObjectInformation->FileId.Volume,
2464                                   pDirNode->ObjectInformation->FileId.Vnode,
2465                                   pDirNode->ObjectInformation->FileId.Unique);
2466
2467                     AFSDeleteDirEntry( ParentObjectInfo,
2468                                        pExistingDirNode);
2469                 }
2470                 else
2471                 {
2472
2473                     SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2474
2475                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2476                                   AFS_TRACE_LEVEL_VERBOSE,
2477                                   "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2478                                   pExistingDirNode,
2479                                   &pExistingDirNode->NameInformation.FileName,
2480                                   pExistingDirNode->ObjectInformation->FileId.Cell,
2481                                   pExistingDirNode->ObjectInformation->FileId.Volume,
2482                                   pExistingDirNode->ObjectInformation->FileId.Vnode,
2483                                   pExistingDirNode->ObjectInformation->FileId.Unique,
2484                                   pDirNode->ObjectInformation->FileId.Cell,
2485                                   pDirNode->ObjectInformation->FileId.Volume,
2486                                   pDirNode->ObjectInformation->FileId.Vnode,
2487                                   pDirNode->ObjectInformation->FileId.Unique);
2488
2489                     AFSRemoveNameEntry( ParentObjectInfo,
2490                                         pExistingDirNode);
2491                 }
2492             }
2493         }
2494
2495         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2496                       AFS_TRACE_LEVEL_VERBOSE_2,
2497                       "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2498                       &ParentDirCB->NameInformation.FileName,
2499                       ParentObjectInfo->FileId.Cell,
2500                       ParentObjectInfo->FileId.Volume,
2501                       ParentObjectInfo->FileId.Vnode,
2502                       ParentObjectInfo->FileId.Unique,
2503                       ComponentName);
2504
2505         //
2506         // Insert the directory node
2507         //
2508
2509         AFSInsertDirectoryNode( ParentObjectInfo,
2510                                 pDirNode,
2511                                 TRUE);
2512
2513         //
2514         // Pass back the dir entry
2515         //
2516
2517         *DirEntry = pDirNode;
2518
2519         AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2520
2521 try_exit:
2522
2523         NOTHING;
2524     }
2525
2526     return ntStatus;
2527 }
2528
2529 void
2530 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2531                         IN AFSDirectoryCB *DirEntry,
2532                         IN BOOLEAN InsertInEnumList)
2533 {
2534
2535     LONG lCount;
2536
2537     __Enter
2538     {
2539
2540         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2541
2542         //
2543         // Insert the node into the directory node tree
2544         //
2545
2546         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2547                       AFS_TRACE_LEVEL_VERBOSE,
2548                       "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2549                       DirEntry,
2550                       &DirEntry->NameInformation.FileName);
2551
2552         ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2553
2554         if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2555         {
2556
2557             ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2558
2559             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2560                           AFS_TRACE_LEVEL_VERBOSE,
2561                           "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2562                           DirEntry,
2563                           &DirEntry->NameInformation.FileName);
2564         }
2565         else
2566         {
2567
2568             AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2569                                             DirEntry);
2570
2571             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2572                           AFS_TRACE_LEVEL_VERBOSE,
2573                           "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2574                           DirEntry,
2575                           &DirEntry->NameInformation.FileName);
2576         }
2577
2578         if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2579         {
2580
2581             ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2582
2583             SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2584
2585             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2586                           AFS_TRACE_LEVEL_VERBOSE,
2587                           "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2588                           DirEntry,
2589                           &DirEntry->NameInformation.FileName);
2590         }
2591         else
2592         {
2593
2594             AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2595                                               DirEntry);
2596
2597             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2598                           AFS_TRACE_LEVEL_VERBOSE,
2599                           "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2600                           DirEntry,
2601                           &DirEntry->NameInformation.FileName);
2602         }
2603
2604         //
2605         // Into the shortname tree
2606         //
2607
2608         if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2609         {
2610
2611             if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2612             {
2613
2614                 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2615
2616                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2617                               AFS_TRACE_LEVEL_VERBOSE,
2618                               "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2619                               DirEntry,
2620                               &DirEntry->NameInformation.FileName);
2621
2622                 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2623             }
2624             else
2625             {
2626
2627                 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2628                                                              DirEntry)))
2629                 {
2630                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2631                                   AFS_TRACE_LEVEL_VERBOSE,
2632                                   "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2633                                   DirEntry,
2634                                   &DirEntry->NameInformation.FileName);
2635                 }
2636                 else
2637                 {
2638                     SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2639
2640                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2641                                   AFS_TRACE_LEVEL_VERBOSE,
2642                                   "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2643                                   DirEntry,
2644                                   &DirEntry->NameInformation.FileName);
2645                 }
2646             }
2647         }
2648
2649         if( InsertInEnumList)
2650         {
2651
2652             //
2653             // And insert the node into the directory list
2654             //
2655
2656             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2657                           AFS_TRACE_LEVEL_VERBOSE,
2658                           "AFSInsertDirectoryNode Inserting entry %p %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2659                           DirEntry,
2660                           &DirEntry->NameInformation.FileName,
2661                           DirEntry->ObjectInformation->FileId.Cell,
2662                           DirEntry->ObjectInformation->FileId.Volume,
2663                           DirEntry->ObjectInformation->FileId.Vnode,
2664                           DirEntry->ObjectInformation->FileId.Unique);
2665
2666             if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2667             {
2668
2669                 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2670             }
2671             else
2672             {
2673
2674                 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2675
2676                 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2677             }
2678
2679             ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2680
2681             SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2682
2683             lCount = InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2684
2685             AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2686                           AFS_TRACE_LEVEL_VERBOSE,
2687                           "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2688                           &DirEntry->NameInformation.FileName,
2689                           lCount,
2690                           ParentObjectInfo->FileId.Cell,
2691                           ParentObjectInfo->FileId.Volume,
2692                           ParentObjectInfo->FileId.Vnode,
2693                           ParentObjectInfo->FileId.Unique);
2694         }
2695     }
2696
2697     return;
2698 }
2699
2700 void
2701 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2702                    IN AFSDirectoryCB *DirEntry)
2703 {
2704
2705     LONG lCount;
2706
2707     __Enter
2708     {
2709
2710         AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2711                       AFS_TRACE_LEVEL_VERBOSE,
2712                       "AFSDeleteDirEntry Deleting dir entry in parent %p Entry %p %wZ FID %08lX-%08lX-%08lX-%08lX RefCount %d\n",
2713                       ParentObjectInfo,
2714                       DirEntry,
2715                       &DirEntry->NameInformation.FileName,
2716                       DirEntry->ObjectInformation->FileId.Cell,
2717                       DirEntry->ObjectInformation->FileId.Volume,
2718                       DirEntry->ObjectInformation->FileId.Vnode,
2719                       DirEntry->ObjectInformation->FileId.Unique,
2720                       DirEntry->DirOpenReferenceCount);
2721
2722         ASSERT( DirEntry->DirOpenReferenceCount == 0);
2723
2724         AFSRemoveDirNodeFromParent( ParentObjectInfo,
2725                                     DirEntry,
2726                                     TRUE);
2727
2728         //
2729         // Free up the name buffer if it was reallocated
2730         //
2731
2732         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2733         {
2734
2735             AFSExFreePoolWithTag( DirEntry->NameInformation.FileName.Buffer, 0);
2736         }
2737
2738         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2739         {
2740
2741             AFSExFreePoolWithTag( DirEntry->NameInformation.TargetName.Buffer, 0);
2742         }
2743
2744         //
2745         // Dereference the object for this dir entry
2746         //
2747
2748         lCount = AFSObjectInfoDecrement( DirEntry->ObjectInformation,
2749                                          AFS_OBJECT_REFERENCE_DIRENTRY);
2750
2751         AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2752                       AFS_TRACE_LEVEL_VERBOSE,
2753                       "AFSDeleteDirEntry Decrement count on object %p Cnt %d\n",
2754                       DirEntry->ObjectInformation,
2755                       lCount);
2756
2757         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
2758             DirEntry->ObjectInformation->Links == 0)
2759         {
2760
2761             SetFlag( DirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2762         }
2763
2764         ExDeleteResourceLite( &DirEntry->NonPaged->Lock);
2765
2766         AFSExFreePoolWithTag( DirEntry->NonPaged, AFS_DIR_ENTRY_NP_TAG);
2767
2768         //
2769         // Free up the dir entry
2770         //
2771
2772         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
2773                       AFS_TRACE_LEVEL_VERBOSE,
2774                       "AFSDeleteDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
2775                       DirEntry);
2776
2777         AFSExFreePoolWithTag( DirEntry, AFS_DIR_ENTRY_TAG);
2778     }
2779 }
2780
2781 NTSTATUS
2782 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2783                             IN AFSDirectoryCB *DirEntry,
2784                             IN BOOLEAN RemoveFromEnumList)
2785 {
2786
2787     NTSTATUS ntStatus = STATUS_SUCCESS;
2788     LONG lCount;
2789
2790     __Enter
2791     {
2792
2793
2794         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2795
2796         AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2797                       AFS_TRACE_LEVEL_VERBOSE,
2798                       "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %p\n",
2799                       DirEntry,
2800                       &DirEntry->NameInformation.FileName,
2801                       DirEntry->ObjectInformation->FileId.Cell,
2802                       DirEntry->ObjectInformation->FileId.Volume,
2803                       DirEntry->ObjectInformation->FileId.Vnode,
2804                       DirEntry->ObjectInformation->FileId.Unique,
2805                       ParentObjectInfo);
2806
2807         if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))