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