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