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