Windows: AFSLocateNameEntry tracking DirectoryCB IN/OUT
[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             {
1178
1179                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1180                               AFS_TRACE_LEVEL_VERBOSE,
1181                               "AFSLocateNameEntry (FO: %p) Enumerating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1182                               FileObject,
1183                               &pDirEntry->NameInformation.FileName,
1184                               pCurrentObject->FileId.Cell,
1185                               pCurrentObject->FileId.Volume,
1186                               pCurrentObject->FileId.Vnode,
1187                               pCurrentObject->FileId.Unique);
1188
1189                 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1190                                 TRUE);
1191
1192                 if( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1193                 {
1194
1195                     ntStatus = AFSEnumerateDirectory( AuthGroup,
1196                                                       pCurrentObject,
1197                                                       TRUE);
1198
1199                     if( !NT_SUCCESS( ntStatus))
1200                     {
1201
1202                         AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1203
1204                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1205                                       AFS_TRACE_LEVEL_ERROR,
1206                                       "AFSLocateNameEntry (FO: %p) Failed to enumerate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1207                                       FileObject,
1208                                       &pDirEntry->NameInformation.FileName,
1209                                       pCurrentObject->FileId.Cell,
1210                                       pCurrentObject->FileId.Volume,
1211                                       pCurrentObject->FileId.Vnode,
1212                                       pCurrentObject->FileId.Unique,
1213                                       ntStatus);
1214
1215                         try_return( ntStatus);
1216                     }
1217
1218                     SetFlag( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1219                 }
1220
1221                 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1222             }
1223             else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1224             {
1225
1226                 if( uniPathName.Length > 0)
1227                 {
1228
1229                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1230                                   AFS_TRACE_LEVEL_ERROR,
1231                                   "AFSLocateNameEntry (FO: %p) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1232                                   FileObject,
1233                                   &pDirEntry->NameInformation.FileName,
1234                                   pCurrentObject->FileId.Cell,
1235                                   pCurrentObject->FileId.Volume,
1236                                   pCurrentObject->FileId.Vnode,
1237                                   pCurrentObject->FileId.Unique);
1238
1239                     // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1240                     // one of the components of the path is not a directory.  However, returning
1241                     // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1242                     // Instead IIS insists on treating the target file as if it is a directory containing
1243                     // a potential web.config file.  NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1244                     // AFS will follow suit.
1245
1246                     ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1247                 }
1248                 else
1249                 {
1250
1251                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1252                                   AFS_TRACE_LEVEL_VERBOSE,
1253                                   "AFSLocateNameEntry (FO: %p) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1254                                   FileObject,
1255                                   &pDirEntry->NameInformation.FileName,
1256                                   pCurrentObject->FileId.Cell,
1257                                   pCurrentObject->FileId.Volume,
1258                                   pCurrentObject->FileId.Vnode,
1259                                   pCurrentObject->FileId.Unique);
1260
1261                     //
1262                     // Pass back the directory entries
1263                     //
1264
1265                     *OutParentDirectoryCB = pParentDirEntry;
1266
1267                     pParentDirEntry = NULL;
1268
1269                     *OutDirectoryCB = pDirEntry;
1270
1271                     pDirEntry = NULL;
1272
1273                     *OutVolumeCB = pCurrentVolume;
1274
1275                     *OutVolumeReferenceReason = VolumeReferenceReason;
1276
1277                     bReleaseCurrentVolume = FALSE;
1278
1279                     *RootPathName = uniFullPathName;
1280                 }
1281
1282                 try_return( ntStatus);
1283             }
1284
1285             //
1286             // If we are at the end of the processing, set our returned information and get out
1287             //
1288
1289             if( uniPathName.Length == 0)
1290             {
1291
1292                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1293                               AFS_TRACE_LEVEL_VERBOSE,
1294                               "AFSLocateNameEntry (FO: %p) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1295                               FileObject,
1296                               &pDirEntry->NameInformation.FileName,
1297                               pCurrentObject->FileId.Cell,
1298                               pCurrentObject->FileId.Volume,
1299                               pCurrentObject->FileId.Vnode,
1300                               pCurrentObject->FileId.Unique);
1301
1302                 //
1303                 // Pass back the directory entries
1304                 //
1305
1306                 *OutParentDirectoryCB = pParentDirEntry;
1307
1308                 pParentDirEntry = NULL;
1309
1310                 *OutDirectoryCB = pDirEntry;
1311
1312                 pDirEntry = NULL;
1313
1314                 *OutVolumeCB = pCurrentVolume;
1315
1316                 *OutVolumeReferenceReason = VolumeReferenceReason;
1317
1318                 bReleaseCurrentVolume = FALSE;
1319
1320                 *RootPathName = uniFullPathName;
1321
1322                 try_return( ntStatus);
1323             }
1324
1325             //
1326             // We may have returned to the top of the while( TRUE)
1327             //
1328             if( bSubstituteName &&
1329                 uniSearchName.Buffer != NULL)
1330             {
1331
1332                 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1333
1334                 bSubstituteName = FALSE;
1335
1336                 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1337                 uniSearchName.Buffer = NULL;
1338             }
1339
1340             ulSubstituteIndex = 1;
1341
1342             ntStatus = STATUS_SUCCESS;
1343
1344             //
1345             // Get the next component name
1346             //
1347
1348             FsRtlDissectName( uniPathName,
1349                               &uniComponentName,
1350                               &uniRemainingPath);
1351
1352             //
1353             // Check for the . and .. in the path
1354             //
1355
1356             if( RtlCompareUnicodeString( &uniComponentName,
1357                                          &uniNoOpName,
1358                                          TRUE) == 0)
1359             {
1360
1361                 uniPathName = uniRemainingPath;
1362
1363                 continue;
1364             }
1365
1366             if( RtlCompareUnicodeString( &uniComponentName,
1367                                          &uniRelativeName,
1368                                          TRUE) == 0)
1369             {
1370
1371                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1372                               AFS_TRACE_LEVEL_VERBOSE,
1373                               "AFSLocateNameEntry (FO: %p) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1374                               FileObject,
1375                               &pDirEntry->NameInformation.FileName,
1376                               pCurrentObject->FileId.Cell,
1377                               pCurrentObject->FileId.Volume,
1378                               pCurrentObject->FileId.Vnode,
1379                               pCurrentObject->FileId.Unique);
1380
1381                 //
1382                 // Need to back up one entry in the name array
1383                 //
1384                 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1385
1386                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1387                               AFS_TRACE_LEVEL_VERBOSE,
1388                               "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1389                               &pDirEntry->NameInformation.FileName,
1390                               pDirEntry,
1391                               NULL,
1392                               lCount);
1393
1394                 ASSERT( lCount >= 0);
1395
1396                 pDirEntry = AFSBackupEntry( NameArray);
1397
1398                 if( pDirEntry == NULL)
1399                 {
1400
1401                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1402                                   AFS_TRACE_LEVEL_ERROR,
1403                                   "AFSLocateNameEntry AFSBackupEntry failed\n");
1404
1405                     try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1406                 }
1407
1408                 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1409
1410                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1411                               AFS_TRACE_LEVEL_VERBOSE,
1412                               "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1413                               &pDirEntry->NameInformation.FileName,
1414                               pDirEntry,
1415                               NULL,
1416                               lCount);
1417
1418                 if ( pParentDirEntry)
1419                 {
1420
1421                     lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1422
1423                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1424                                   AFS_TRACE_LEVEL_VERBOSE,
1425                                   "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1426                                   &pParentDirEntry->NameInformation.FileName,
1427                                   pParentDirEntry,
1428                                   NULL,
1429                                   lCount);
1430
1431                     pParentDirEntry = NULL;
1432                 }
1433
1434                 if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1435                 {
1436
1437                     pParentDirEntry = AFSGetParentEntry( pNameArray);
1438
1439                     ASSERT( pParentDirEntry != pDirEntry);
1440
1441                     if ( pParentDirEntry)
1442                     {
1443
1444                         lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
1445
1446                         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1447                                       AFS_TRACE_LEVEL_VERBOSE,
1448                                       "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
1449                                       &pParentDirEntry->NameInformation.FileName,
1450                                       pParentDirEntry,
1451                                       NULL,
1452                                       lCount);
1453                     }
1454                 }
1455
1456                 uniPathName = uniRemainingPath;
1457
1458                 continue;
1459             }
1460
1461             //
1462             // Update our pointers
1463             //
1464
1465             if ( pParentDirEntry)
1466             {
1467
1468                 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1469
1470                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1471                               AFS_TRACE_LEVEL_VERBOSE,
1472                               "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1473                               &pParentDirEntry->NameInformation.FileName,
1474                               pParentDirEntry,
1475                               NULL,
1476                               lCount);
1477             }
1478
1479             pParentDirEntry = pDirEntry;
1480
1481             pDirEntry = NULL;
1482
1483             uniSearchName = uniComponentName;
1484
1485             while( pDirEntry == NULL)
1486             {
1487
1488                 //
1489                 // If the SearchName contains @SYS then we perform the substitution.
1490                 // If there is no substitution we give up.
1491                 //
1492
1493                 if( !bSubstituteName &&
1494                     FsRtlIsNameInExpression( &uniSysName,
1495                                              &uniSearchName,
1496                                              TRUE,
1497                                              NULL))
1498                 {
1499
1500                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1501                                   AFS_TRACE_LEVEL_VERBOSE_2,
1502                                   "AFSLocateNameEntry (FO: %p) Processing @SYS substitution for %wZ Index %08lX\n",
1503                                   FileObject,
1504                                   &uniComponentName,
1505                                   ulSubstituteIndex);
1506
1507                     ntStatus = AFSSubstituteSysName( &uniComponentName,
1508                                                      &uniSearchName,
1509                                                      ulSubstituteIndex);
1510
1511                     if ( NT_SUCCESS( ntStatus))
1512                     {
1513
1514                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1515                                       AFS_TRACE_LEVEL_VERBOSE_2,
1516                                       "AFSLocateNameEntry (FO: %p) Located substitution %wZ for %wZ Index %08lX\n",
1517                                       FileObject,
1518                                       &uniSearchName,
1519                                       &uniComponentName,
1520                                       ulSubstituteIndex);
1521
1522                         //
1523                         // Go reparse the name again
1524                         //
1525
1526                         bSubstituteName = TRUE;
1527
1528                         ulSubstituteIndex++; // For the next entry, if needed
1529
1530                         continue;   // while( pDirEntry == NULL)
1531                     }
1532                     else
1533                     {
1534
1535                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1536                                       AFS_TRACE_LEVEL_ERROR,
1537                                       "AFSLocateNameEntry (FO: %p) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1538                                       FileObject,
1539                                       &uniComponentName,
1540                                       ulSubstituteIndex,
1541                                       ntStatus);
1542
1543                         if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1544                         {
1545
1546                             //
1547                             // Pass back the directory entries
1548                             //
1549
1550                             *OutParentDirectoryCB = pParentDirEntry;
1551
1552                             pParentDirEntry = NULL;
1553
1554                             *OutDirectoryCB = NULL;
1555
1556                             *OutVolumeCB = pCurrentVolume;
1557
1558                             *OutVolumeReferenceReason = VolumeReferenceReason;
1559
1560                             bReleaseCurrentVolume = FALSE;
1561
1562                             if( ComponentName != NULL)
1563                             {
1564
1565                                 *ComponentName = uniComponentName;
1566                             }
1567
1568                             *RootPathName = uniFullPathName;
1569                         }
1570
1571                         //
1572                         // We can't possibly have a pDirEntry since the lookup failed
1573                         //
1574                         try_return( ntStatus);
1575                     }
1576                 }
1577
1578                 //
1579                 // Generate the CRC on the node and perform a case sensitive lookup
1580                 //
1581
1582                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1583                               AFS_TRACE_LEVEL_VERBOSE_2,
1584                               "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case sensitive\n",
1585                               FileObject,
1586                               &uniSearchName);
1587
1588                 ulCRC = AFSGenerateCRC( &uniSearchName,
1589                                         FALSE);
1590
1591                 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1592                                   TRUE);
1593
1594                 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1595                                                 ulCRC,
1596                                                 &pDirEntry);
1597
1598                 if( pDirEntry == NULL)
1599                 {
1600
1601                     //
1602                     // Missed so perform a case insensitive lookup
1603                     //
1604
1605                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1606                                   AFS_TRACE_LEVEL_VERBOSE_2,
1607                                   "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case insensitive\n",
1608                                   FileObject,
1609                                   &uniSearchName);
1610
1611                     ulCRC = AFSGenerateCRC( &uniSearchName,
1612                                             TRUE);
1613
1614                     AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1615                                                       ulCRC,
1616                                                       &pDirEntry);
1617
1618                     if( pDirEntry == NULL)
1619                     {
1620
1621                         //
1622                         // OK, if this component is a valid short name then try
1623                         // a lookup in the short name tree
1624                         //
1625
1626                         if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1627                             RtlIsNameLegalDOS8Dot3( &uniSearchName,
1628                                                     NULL,
1629                                                     NULL))
1630                         {
1631
1632                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1633                                           AFS_TRACE_LEVEL_VERBOSE_2,
1634                                           "AFSLocateNameEntry (FO: %p) Searching for entry %wZ short name\n",
1635                                           FileObject,
1636                                           &uniSearchName);
1637
1638                             AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1639                                                         ulCRC,
1640                                                         &pDirEntry);
1641                         }
1642
1643                         if ( pDirEntry == NULL &&
1644                              pParentDirEntry->ObjectInformation->VolumeCB == AFSGlobalRoot)
1645                         {
1646
1647                             //
1648                             // Check with the service to see if this is a valid cell name
1649                             // that can be automatically resolved.  Drop the shared TreeLock
1650                             // since AFSCheckCellName must acquire it exclusively.
1651                             //
1652
1653                             AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1654
1655                             ntStatus = AFSCheckCellName( AuthGroup,
1656                                                          &uniSearchName,
1657                                                          &pDirEntry);
1658
1659                             AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1660                                               TRUE);
1661                         }
1662
1663                         if( pDirEntry == NULL)
1664                         {
1665
1666                             //
1667                             // If we substituted a name then reset our search name and try again
1668                             //
1669
1670                             if( bSubstituteName)
1671                             {
1672
1673                                 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1674
1675                                 uniSearchName = uniComponentName;
1676
1677                                 bSubstituteName = FALSE;
1678
1679                                 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1680
1681                                 continue;       // while( pDirEntry == NULL)
1682                             }
1683
1684                             //
1685                             // Node name not found so get out
1686                             //
1687
1688                             AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1689
1690                             if( uniRemainingPath.Length > 0)
1691                             {
1692
1693                                 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1694
1695                                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1696                                               AFS_TRACE_LEVEL_VERBOSE,
1697                                               "AFSLocateNameEntry (FO: %p) Returning path not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1698                                               FileObject,
1699                                               &uniSearchName,
1700                                               pCurrentObject->FileId.Cell,
1701                                               pCurrentObject->FileId.Volume,
1702                                               pCurrentObject->FileId.Vnode,
1703                                               pCurrentObject->FileId.Unique);
1704                             }
1705                             else
1706                             {
1707
1708                                 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1709
1710                                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1711                                               AFS_TRACE_LEVEL_VERBOSE,
1712                                               "AFSLocateNameEntry (FO: %p) Returning name not found for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1713                                               FileObject,
1714                                               &uniSearchName,
1715                                               pCurrentObject->FileId.Cell,
1716                                               pCurrentObject->FileId.Volume,
1717                                               pCurrentObject->FileId.Vnode,
1718                                               pCurrentObject->FileId.Unique);
1719
1720                                 //
1721                                 // Pass back the directory entries
1722                                 //
1723
1724                                 *OutParentDirectoryCB = pParentDirEntry;
1725
1726                                 pParentDirEntry = NULL;
1727
1728                                 *OutDirectoryCB = NULL;
1729
1730                                 *OutVolumeCB = pCurrentVolume;
1731
1732                                 *OutVolumeReferenceReason = VolumeReferenceReason;
1733
1734                                 bReleaseCurrentVolume = FALSE;
1735
1736                                 if( ComponentName != NULL)
1737                                 {
1738
1739                                     *ComponentName = uniComponentName;
1740                                 }
1741
1742                                 *RootPathName = uniFullPathName;
1743                             }
1744
1745                             try_return( ntStatus);
1746                         }
1747                     }
1748                     else
1749                     {
1750
1751                         //
1752                         // Here we have a match on the case insensitive lookup for the name. If there
1753                         // Is more than one link entry for this node then fail the lookup request
1754                         //
1755
1756                         if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1757                             pDirEntry->CaseInsensitiveList.fLink != NULL)
1758                         {
1759
1760                             //
1761                             // Increment our dir entry ref count since we will decrement it on exit
1762                             //
1763
1764                             lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1765
1766                             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1767                                           AFS_TRACE_LEVEL_VERBOSE,
1768                                           "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1769                                           &pDirEntry->NameInformation.FileName,
1770                                           pDirEntry,
1771                                           NULL,
1772                                           lCount);
1773
1774                             AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1775
1776                             try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1777                         }
1778                     }
1779                 }
1780
1781                 if( pDirEntry != NULL)
1782                 {
1783
1784                     //
1785                     // If the verify flag is set on the parent and the current entry is deleted
1786                     // revalidate the parent and search again.
1787                     //
1788
1789                     if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1790                         BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1791                     {
1792
1793                         AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1794
1795                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1796                                       AFS_TRACE_LEVEL_VERBOSE,
1797                                       "AFSLocateNameEntry (FO: %p) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1798                                       FileObject,
1799                                       &pParentDirEntry->NameInformation.FileName,
1800                                       pParentDirEntry->ObjectInformation->FileId.Cell,
1801                                       pParentDirEntry->ObjectInformation->FileId.Volume,
1802                                       pParentDirEntry->ObjectInformation->FileId.Vnode,
1803                                       pParentDirEntry->ObjectInformation->FileId.Unique);
1804
1805                         //
1806                         // Directory TreeLock should be exclusively held
1807                         //
1808
1809                         AFSAcquireExcl( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1810                                         TRUE);
1811
1812                         ntStatus = AFSVerifyEntry( AuthGroup,
1813                                                    pParentDirEntry);
1814
1815                         AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1816
1817                         if( !NT_SUCCESS( ntStatus))
1818                         {
1819
1820                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1821                                           AFS_TRACE_LEVEL_ERROR,
1822                                           "AFSLocateNameEntry (FO: %p) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1823                                           FileObject,
1824                                           &pParentDirEntry->NameInformation.FileName,
1825                                           pParentDirEntry->ObjectInformation->FileId.Cell,
1826                                           pParentDirEntry->ObjectInformation->FileId.Volume,
1827                                           pParentDirEntry->ObjectInformation->FileId.Vnode,
1828                                           pParentDirEntry->ObjectInformation->FileId.Unique,
1829                                           ntStatus);
1830
1831                             try_return( ntStatus);
1832                         }
1833
1834                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1835                                       AFS_TRACE_LEVEL_VERBOSE,
1836                                       "AFSLocateNameEntry (FO: %p) Reprocessing component %wZ in parent %wZ\n",
1837                                       FileObject,
1838                                       &uniSearchName,
1839                                       &pParentDirEntry->NameInformation.FileName);
1840
1841
1842                         pDirEntry = NULL;
1843
1844                         continue;
1845                     }
1846
1847                     //
1848                     // Increment our dir entry ref count
1849                     //
1850
1851                     lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1852
1853                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1854                                   AFS_TRACE_LEVEL_VERBOSE,
1855                                   "AFSLocateNameEntry Increment6 count on %wZ DE %p Ccb %p Cnt %d\n",
1856                                   &pDirEntry->NameInformation.FileName,
1857                                   pDirEntry,
1858                                   NULL,
1859                                   lCount);
1860                 }
1861
1862                 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1863
1864             } // End while( pDirEntry == NULL)
1865
1866             //
1867             // If we have a dirEntry for this component, perform some basic validation on it
1868             //
1869
1870             if( pDirEntry != NULL &&
1871                 BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1872             {
1873
1874                 pCurrentObject = pDirEntry->ObjectInformation;
1875
1876                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1877                               AFS_TRACE_LEVEL_ERROR,
1878                               "AFSLocateNameEntry (FO: %p) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1879                               FileObject,
1880                               &pDirEntry->NameInformation.FileName,
1881                               pCurrentObject->FileId.Cell,
1882                               pCurrentObject->FileId.Volume,
1883                               pCurrentObject->FileId.Vnode,
1884                               pCurrentObject->FileId.Unique);
1885
1886                 //
1887                 // This entry was deleted through the invalidation call back so perform cleanup
1888                 // on the entry
1889                 //
1890
1891                 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1892                 {
1893
1894                     pParentObjectInfo = AFSFindObjectInfo( pCurrentObject->VolumeCB,
1895                                                            &pCurrentObject->ParentFileId);
1896                 }
1897
1898                 ASSERT( pParentObjectInfo != NULL);
1899
1900                 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1901                                 TRUE);
1902
1903                 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1904                                 TRUE);
1905
1906                 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1907
1908                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1909                               AFS_TRACE_LEVEL_VERBOSE,
1910                               "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1911                               &pDirEntry->NameInformation.FileName,
1912                               pDirEntry,
1913                               NULL,
1914                               lCount);
1915
1916                 ASSERT( lCount >= 0);
1917
1918                 if( lCount == 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                 {
2451
2452                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2453                                   AFS_TRACE_LEVEL_VERBOSE,
2454                                   "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2455                                   pExistingDirNode,
2456                                   &pExistingDirNode->NameInformation.FileName,
2457                                   pExistingDirNode->ObjectInformation->FileId.Cell,
2458                                   pExistingDirNode->ObjectInformation->FileId.Volume,
2459                                   pExistingDirNode->ObjectInformation->FileId.Vnode,
2460                                   pExistingDirNode->ObjectInformation->FileId.Unique,
2461                                   pDirNode->ObjectInformation->FileId.Cell,
2462                                   pDirNode->ObjectInformation->FileId.Volume,
2463                                   pDirNode->ObjectInformation->FileId.Vnode,
2464                                   pDirNode->ObjectInformation->FileId.Unique);
2465
2466                     AFSDeleteDirEntry( ParentObjectInfo,
2467                                        pExistingDirNode);
2468                 }
2469                 else
2470                 {
2471
2472                     SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2473
2474                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2475                                   AFS_TRACE_LEVEL_VERBOSE,
2476                                   "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2477                                   pExistingDirNode,
2478                                   &pExistingDirNode->NameInformation.FileName,
2479                                   pExistingDirNode->ObjectInformation->FileId.Cell,
2480                                   pExistingDirNode->ObjectInformation->FileId.Volume,
2481                                   pExistingDirNode->ObjectInformation->FileId.Vnode,
2482                                   pExistingDirNode->ObjectInformation->FileId.Unique,
2483                                   pDirNode->ObjectInformation->FileId.Cell,
2484                                   pDirNode->ObjectInformation->FileId.Volume,
2485                                   pDirNode->ObjectInformation->FileId.Vnode,
2486                                   pDirNode->ObjectInformation->FileId.Unique);
2487
2488                     AFSRemoveNameEntry( ParentObjectInfo,
2489                                         pExistingDirNode);
2490                 }
2491             }
2492         }
2493
2494         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2495                       AFS_TRACE_LEVEL_VERBOSE_2,
2496                       "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2497                       &ParentDirCB->NameInformation.FileName,
2498                       ParentObjectInfo->FileId.Cell,
2499                       ParentObjectInfo->FileId.Volume,
2500                       ParentObjectInfo->FileId.Vnode,
2501                       ParentObjectInfo->FileId.Unique,
2502                       ComponentName);
2503
2504         //
2505         // Insert the directory node
2506         //
2507
2508         AFSInsertDirectoryNode( ParentObjectInfo,
2509                                 pDirNode,
2510                                 TRUE);
2511
2512         //
2513         // Pass back the dir entry
2514         //
2515
2516         *DirEntry = pDirNode;
2517
2518         AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2519
2520 try_exit:
2521
2522         NOTHING;
2523     }
2524
2525     return ntStatus;
2526 }
2527
2528 void
2529 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2530                         IN AFSDirectoryCB *DirEntry,
2531                         IN BOOLEAN InsertInEnumList)
2532 {
2533
2534     LONG lCount;
2535
2536     __Enter
2537     {
2538
2539         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2540
2541         //
2542         // Insert the node into the directory node tree
2543         //
2544
2545         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2546                       AFS_TRACE_LEVEL_VERBOSE,
2547                       "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2548                       DirEntry,
2549                       &DirEntry->NameInformation.FileName);
2550
2551         ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2552
2553         if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2554         {
2555
2556             ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2557
2558             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2559                           AFS_TRACE_LEVEL_VERBOSE,
2560                           "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2561                           DirEntry,
2562                           &DirEntry->NameInformation.FileName);
2563         }
2564         else
2565         {
2566
2567             AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2568                                             DirEntry);
2569
2570             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2571                           AFS_TRACE_LEVEL_VERBOSE,
2572                           "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2573                           DirEntry,
2574                           &DirEntry->NameInformation.FileName);
2575         }
2576
2577         if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2578         {
2579
2580             ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2581
2582             SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2583
2584             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2585                           AFS_TRACE_LEVEL_VERBOSE,
2586                           "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2587                           DirEntry,
2588                           &DirEntry->NameInformation.FileName);
2589         }
2590         else
2591         {
2592
2593             AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2594                                               DirEntry);
2595
2596             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2597                           AFS_TRACE_LEVEL_VERBOSE,
2598                           "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2599                           DirEntry,
2600                           &DirEntry->NameInformation.FileName);
2601         }
2602
2603         //
2604         // Into the shortname tree
2605         //
2606
2607         if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2608         {
2609
2610             if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2611             {
2612
2613                 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2614
2615                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2616                               AFS_TRACE_LEVEL_VERBOSE,
2617                               "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2618                               DirEntry,
2619                               &DirEntry->NameInformation.FileName);
2620
2621                 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2622             }
2623             else
2624             {
2625
2626                 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2627                                                              DirEntry)))
2628                 {
2629                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2630                                   AFS_TRACE_LEVEL_VERBOSE,
2631                                   "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2632                                   DirEntry,
2633                                   &DirEntry->NameInformation.FileName);
2634                 }
2635                 else
2636                 {
2637                     SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2638
2639                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2640                                   AFS_TRACE_LEVEL_VERBOSE,
2641                                   "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2642                                   DirEntry,
2643                                   &DirEntry->NameInformation.FileName);
2644                 }
2645             }
2646         }
2647
2648         if( InsertInEnumList)
2649         {
2650
2651             //
2652             // And insert the node into the directory list
2653             //
2654
2655             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2656                           AFS_TRACE_LEVEL_VERBOSE,
2657                           "AFSInsertDirectoryNode Inserting entry %p %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2658                           DirEntry,
2659                           &DirEntry->NameInformation.FileName,
2660                           DirEntry->ObjectInformation->FileId.Cell,
2661                           DirEntry->ObjectInformation->FileId.Volume,
2662                           DirEntry->ObjectInformation->FileId.Vnode,
2663                           DirEntry->ObjectInformation->FileId.Unique);
2664
2665             if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2666             {
2667
2668                 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2669             }
2670             else
2671             {
2672
2673                 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2674
2675                 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2676             }
2677
2678             ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2679
2680             SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2681
2682             lCount = InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2683
2684             AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2685                           AFS_TRACE_LEVEL_VERBOSE,
2686                           "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2687                           &DirEntry->NameInformation.FileName,
2688                           lCount,
2689                           ParentObjectInfo->FileId.Cell,
2690                           ParentObjectInfo->FileId.Volume,
2691                           ParentObjectInfo->FileId.Vnode,
2692                           ParentObjectInfo->FileId.Unique);
2693         }
2694     }
2695
2696     return;
2697 }
2698
2699 void
2700 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2701                    IN AFSDirectoryCB *DirEntry)
2702 {
2703
2704     LONG lCount;
2705
2706     __Enter
2707     {
2708
2709         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2710                       AFS_TRACE_LEVEL_VERBOSE,
2711                       "AFSDeleteDirEntry Deleting dir entry in parent %p Entry %p %wZ FID %08lX-%08lX-%08lX-%08lX RefCount %d\n",
2712                       ParentObjectInfo,
2713                       DirEntry,
2714                       &DirEntry->NameInformation.FileName,
2715                       DirEntry->ObjectInformation->FileId.Cell,
2716                       DirEntry->ObjectInformation->FileId.Volume,
2717                       DirEntry->ObjectInformation->FileId.Vnode,
2718                       DirEntry->ObjectInformation->FileId.Unique,
2719                       DirEntry->DirOpenReferenceCount);
2720
2721         ASSERT( DirEntry->DirOpenReferenceCount == 0);
2722
2723         AFSRemoveDirNodeFromParent( ParentObjectInfo,
2724                                     DirEntry,
2725                                     TRUE);
2726
2727         //
2728         // Free up the name buffer if it was reallocated
2729         //
2730
2731         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2732         {
2733
2734             AFSExFreePoolWithTag( DirEntry->NameInformation.FileName.Buffer, 0);
2735         }
2736
2737         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2738         {
2739
2740             AFSExFreePoolWithTag( DirEntry->NameInformation.TargetName.Buffer, 0);
2741         }
2742
2743         //
2744         // Dereference the object for this dir entry
2745         //
2746
2747         lCount = AFSObjectInfoDecrement( DirEntry->ObjectInformation,
2748                                          AFS_OBJECT_REFERENCE_DIRENTRY);
2749
2750         AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2751                       AFS_TRACE_LEVEL_VERBOSE,
2752                       "AFSDeleteDirEntry Decrement count on object %p Cnt %d\n",
2753                       DirEntry->ObjectInformation,
2754                       lCount);
2755
2756         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
2757             DirEntry->ObjectInformation->Links == 0)
2758         {
2759
2760             SetFlag( DirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2761         }
2762
2763         ExDeleteResourceLite( &DirEntry->NonPaged->Lock);
2764
2765         AFSExFreePoolWithTag( DirEntry->NonPaged, AFS_DIR_ENTRY_NP_TAG);
2766
2767         //
2768         // Free up the dir entry
2769         //
2770
2771         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
2772                       AFS_TRACE_LEVEL_VERBOSE,
2773                       "AFSDeleteDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
2774                       DirEntry);
2775
2776         AFSExFreePoolWithTag( DirEntry, AFS_DIR_ENTRY_TAG);
2777     }
2778 }
2779
2780 NTSTATUS
2781 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2782                             IN AFSDirectoryCB *DirEntry,
2783                             IN BOOLEAN RemoveFromEnumList)
2784 {
2785
2786     NTSTATUS ntStatus = STATUS_SUCCESS;
2787     LONG lCount;
2788
2789     __Enter
2790     {
2791
2792
2793         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2794
2795         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2796                       AFS_TRACE_LEVEL_VERBOSE,
2797                       "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %p\n",
2798                       DirEntry,
2799                       &DirEntry->NameInformation.FileName,
2800                       DirEntry->ObjectInformation->FileId.Cell,
2801                       DirEntry->ObjectInformation->FileId.Volume,
2802                       DirEntry->ObjectInformation->FileId.Vnode,
2803                       DirEntry->ObjectInformation->FileId.Unique,
2804                       ParentObjectInfo);
2805
2806         if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2807         {
2808