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