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