Windows: Fix trace msg typo in AFSDeleteDirEntry
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSNameSupport.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright
13  *   notice,
14  *   this list of conditions and the following disclaimer in the
15  *   documentation
16  *   and/or other materials provided with the distribution.
17  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18  *   nor the names of their contributors may be used to endorse or promote
19  *   products derived from this software without specific prior written
20  *   permission from Kernel Drivers, LLC and Your File System, Inc.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 //
36 // File: AFSNameSupport.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 //
42 // AFSLocateNameEntry
43 //
44 // On entry, *VolumeCB must have a held ReferenceCount provided by
45 // the caller which will not be released.  On successful exit, *OutVolumeCB
46 // will be assigned the new current volume with a held ReferenceCount.
47 //
48 // On entry, *ParentDirectoryCB must have a held DirOpenReferenceCount
49 // provided by the caller.  This reference will not be released.
50 // On exit, if OutParentDirectoryCB is set, it will have a new reference.
51 //
52 // On exit, if OutDirectoryCB is set, it will have a reference.
53 //
54
55 NTSTATUS
56 AFSLocateNameEntry( IN GUID *AuthGroup,
57                     IN PFILE_OBJECT FileObject,
58                     IN OUT UNICODE_STRING *RootPathName,
59                     IN UNICODE_STRING *ParsedPathName,
60                     IN AFSNameArrayHdr *NameArray,
61                     IN ULONG Flags,
62                     IN AFSVolumeCB *VolumeCB,
63                     IN AFSDirectoryCB *ParentDirectoryCB,
64                     OUT AFSVolumeCB **OutVolumeCB,
65                     OUT LONG *OutVolumeReferenceReason,
66                     OUT AFSDirectoryCB **OutParentDirectoryCB,
67                     OUT AFSDirectoryCB **OutDirectoryCB,
68                     OUT PUNICODE_STRING ComponentName)
69 {
70
71     NTSTATUS          ntStatus = STATUS_SUCCESS;
72     UNICODE_STRING    uniPathName, uniComponentName, uniRemainingPath, uniSearchName, uniFullPathName;
73     ULONG             ulCRC = 0;
74     AFSDirectoryCB   *pDirEntry = NULL, *pParentDirEntry = NULL;
75     AFSDeviceExt     *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
76     UNICODE_STRING    uniSysName;
77     ULONG             ulSubstituteIndex = 0;
78     BOOLEAN           bSubstituteName = FALSE;
79     AFSNameArrayHdr  *pNameArray = NameArray;
80     BOOLEAN           bAllocatedSymLinkBuffer = FALSE;
81     UNICODE_STRING    uniRelativeName, uniNoOpName;
82     AFSObjectInfoCB  *pCurrentObject = NULL;
83     AFSObjectInfoCB  *pParentObjectInfo = NULL;
84     AFSVolumeCB      *pCurrentVolume = NULL;
85     AFSVolumeCB      *pTargetVolume = NULL;
86     BOOLEAN           bReleaseCurrentVolume = FALSE;
87     LONG              VolumeReferenceReason;
88     BOOLEAN           bSubstitutedName = FALSE;
89     LONG              lCount;
90
91     __Enter
92     {
93
94         ASSERT( *OutVolumeCB != VolumeCB);
95
96         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
97                       AFS_TRACE_LEVEL_VERBOSE_2,
98                       "AFSLocateNameEntry (FO: %p) Processing full name %wZ\n",
99                       FileObject,
100                       RootPathName));
101
102         RtlInitUnicodeString( &uniSysName,
103                               L"*@SYS");
104
105         RtlInitUnicodeString( &uniRelativeName,
106                               L"..");
107
108         RtlInitUnicodeString( &uniNoOpName,
109                               L".");
110
111         //
112         // Cleanup some parameters
113         //
114
115         if( ComponentName != NULL)
116         {
117
118             ComponentName->Length = 0;
119             ComponentName->MaximumLength = 0;
120             ComponentName->Buffer = NULL;
121         }
122
123         //
124         // We will parse through the filename, locating the directory nodes until we encounter a cache miss
125         // Starting at the root node
126         //
127
128         pParentDirEntry = NULL;
129
130         pDirEntry = ParentDirectoryCB;
131
132         //
133         // Increment our reference on this dir entry
134         //
135
136         lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
137
138         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
139                       AFS_TRACE_LEVEL_VERBOSE,
140                       "AFSLocateNameEntry Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
141                       &pDirEntry->NameInformation.FileName,
142                       pDirEntry,
143                       NULL,
144                       lCount));
145
146         pCurrentVolume = VolumeCB;
147
148         VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
149
150         lCount = AFSVolumeIncrement( pCurrentVolume,
151                                      VolumeReferenceReason);
152
153         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
154                       AFS_TRACE_LEVEL_VERBOSE,
155                       "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
156                       pCurrentVolume,
157                       VolumeReferenceReason,
158                       lCount));
159
160         bReleaseCurrentVolume = TRUE;
161
162         uniPathName = *ParsedPathName;
163
164         uniFullPathName = *RootPathName;
165
166         uniComponentName.Length = uniComponentName.MaximumLength = 0;
167         uniComponentName.Buffer = NULL;
168
169         uniRemainingPath.Length = uniRemainingPath.MaximumLength = 0;
170         uniRemainingPath.Buffer = NULL;
171
172         uniSearchName.Length = uniSearchName.MaximumLength = 0;
173         uniSearchName.Buffer = NULL;
174
175         while( TRUE)
176         {
177
178             ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
179
180             ASSERT( pDirEntry->DirOpenReferenceCount > 0);
181
182             //
183             // Check our total link count for this name array
184             //
185
186             if( pNameArray->LinkCount >= (LONG)pDevExt->Specific.RDR.MaxLinkCount)
187             {
188
189                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
190             }
191
192             pCurrentObject = pDirEntry->ObjectInformation;
193
194             KeQueryTickCount( &pCurrentObject->LastAccessCount);
195
196             //
197             // Check that the directory entry is not deleted or pending delete
198             //
199
200             if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
201             {
202
203                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
204                               AFS_TRACE_LEVEL_ERROR,
205                               "AFSLocateNameEntry (FO: %p) Deleted parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
206                               FileObject,
207                               &pDirEntry->NameInformation.FileName,
208                               pCurrentObject->FileId.Cell,
209                               pCurrentObject->FileId.Volume,
210                               pCurrentObject->FileId.Vnode,
211                               pCurrentObject->FileId.Unique,
212                               STATUS_FILE_DELETED));
213
214                 try_return( ntStatus = STATUS_FILE_DELETED);
215             }
216
217             if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
218             {
219
220                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
221                               AFS_TRACE_LEVEL_ERROR,
222                               "AFSLocateNameEntry (FO: %p) Delete pending on %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
223                               FileObject,
224                               &pDirEntry->NameInformation.FileName,
225                               pCurrentObject->FileId.Cell,
226                               pCurrentObject->FileId.Volume,
227                               pCurrentObject->FileId.Vnode,
228                               pCurrentObject->FileId.Unique,
229                               STATUS_DELETE_PENDING));
230
231                 try_return( ntStatus = STATUS_DELETE_PENDING);
232             }
233
234             //
235             // Check if the directory requires verification
236             //
237
238             if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
239                 ( pCurrentObject->FileType != AFS_FILE_TYPE_DIRECTORY ||
240                   !AFSIsEnumerationInProcess( pCurrentObject)))
241             {
242
243                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
244                               AFS_TRACE_LEVEL_VERBOSE,
245                               "AFSLocateNameEntry (FO: %p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
246                               FileObject,
247                               &pDirEntry->NameInformation.FileName,
248                               pCurrentObject->FileId.Cell,
249                               pCurrentObject->FileId.Volume,
250                               pCurrentObject->FileId.Vnode,
251                               pCurrentObject->FileId.Unique));
252
253                 //
254                 // Directory TreeLock should be exclusively held
255                 //
256
257                 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
258                                 TRUE);
259
260                 ntStatus = AFSVerifyEntry( AuthGroup,
261                                            pDirEntry);
262
263                 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
264
265                 if( !NT_SUCCESS( ntStatus))
266                 {
267
268                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
269                                   AFS_TRACE_LEVEL_ERROR,
270                                   "AFSLocateNameEntry (FO: %p) Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
271                                   FileObject,
272                                   &pDirEntry->NameInformation.FileName,
273                                   pCurrentObject->FileId.Cell,
274                                   pCurrentObject->FileId.Volume,
275                                   pCurrentObject->FileId.Vnode,
276                                   pCurrentObject->FileId.Unique,
277                                   ntStatus));
278
279                     try_return( ntStatus);
280                 }
281             }
282
283             //
284             // Ensure the parent node has been evaluated, if not then go do it now
285             //
286
287             if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) ||
288                 pCurrentObject->FileType == AFS_FILE_TYPE_UNKNOWN)
289             {
290
291                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
292                               AFS_TRACE_LEVEL_VERBOSE,
293                               "AFSLocateNameEntry (FO: %p) Evaluating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
294                               FileObject,
295                               &pDirEntry->NameInformation.FileName,
296                               pCurrentObject->FileId.Cell,
297                               pCurrentObject->FileId.Volume,
298                               pCurrentObject->FileId.Vnode,
299                               pCurrentObject->FileId.Unique));
300
301                 ntStatus = AFSEvaluateNode( AuthGroup,
302                                             pDirEntry);
303
304                 if( !NT_SUCCESS( ntStatus))
305                 {
306
307                     if ( ntStatus == STATUS_NOT_A_DIRECTORY)
308                     {
309
310                         if ( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
311                         {
312
313                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
314                                           AFS_TRACE_LEVEL_ERROR,
315                                           "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT NULL Status %08lX\n",
316                                           FileObject,
317                                           &pDirEntry->NameInformation.FileName,
318                                           pCurrentObject->FileId.Cell,
319                                           pCurrentObject->FileId.Volume,
320                                           pCurrentObject->FileId.Vnode,
321                                           pCurrentObject->FileId.Unique,
322                                           ntStatus));
323                         }
324                         else
325                         {
326
327                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
328                                           AFS_TRACE_LEVEL_ERROR,
329                                           "AFSLocateNameEntry (FO: %p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT %08lX-%08lX-%08lX-%08lX Status %08lX\n",
330                                           FileObject,
331                                           &pDirEntry->NameInformation.FileName,
332                                           pCurrentObject->FileId.Cell,
333                                           pCurrentObject->FileId.Volume,
334                                           pCurrentObject->FileId.Vnode,
335                                           pCurrentObject->FileId.Unique,
336                                           pCurrentObject->ParentFileId.Cell,
337                                           pCurrentObject->ParentFileId.Volume,
338                                           pCurrentObject->ParentFileId.Vnode,
339                                           pCurrentObject->ParentFileId.Unique,
340                                           ntStatus));
341                         }
342                     }
343                     else
344                     {
345                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
346                                       AFS_TRACE_LEVEL_ERROR,
347                                       "AFSLocateNameEntry (FO: %p) Failed to evaluate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
348                                       FileObject,
349                                       &pDirEntry->NameInformation.FileName,
350                                       pCurrentObject->FileId.Cell,
351                                       pCurrentObject->FileId.Volume,
352                                       pCurrentObject->FileId.Vnode,
353                                       pCurrentObject->FileId.Unique,
354                                       ntStatus));
355                     }
356
357                     try_return( ntStatus);
358                 }
359
360                 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
361             }
362
363             //
364             // If this is a mount point or symlink then go get the real directory node
365             //
366
367             switch( pCurrentObject->FileType)
368             {
369
370                 case AFS_FILE_TYPE_SYMLINK:
371                 {
372
373                     UNICODE_STRING uniTempName;
374                     WCHAR *pTmpBuffer = NULL;
375                     LONG lLinkCount = 0;
376
377                     //
378                     // Check if the flag is set to NOT evaluate a symlink
379                     // and we are done with the parsing
380                     //
381
382                     if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL) &&
383                         uniRemainingPath.Length == 0)
384                     {
385
386                         //
387                         // Pass back the directory entries
388                         //
389
390                         *OutParentDirectoryCB = pParentDirEntry;
391
392                         pParentDirEntry = NULL;
393
394                         *OutDirectoryCB = pDirEntry;
395
396                         pDirEntry = NULL;
397
398                         *OutVolumeCB = pCurrentVolume;
399
400                         *OutVolumeReferenceReason = VolumeReferenceReason;
401
402                         bReleaseCurrentVolume = FALSE;
403
404                         *RootPathName = uniFullPathName;
405
406                         try_return( ntStatus);
407                     }
408
409                     AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
410                                     TRUE);
411
412                     AFSAcquireExcl( &pDirEntry->NonPaged->Lock,
413                                     TRUE);
414
415                     if( pDirEntry->NameInformation.TargetName.Length == 0)
416                     {
417
418                         //
419                         // We'll reset the DV to ensure we validate the metadata content
420                         //
421
422                         pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
423
424                         SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
425
426                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
427                                       AFS_TRACE_LEVEL_VERBOSE,
428                                       "AFSLocateNameEntry (FO: %p) Verifying symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
429                                       FileObject,
430                                       &pDirEntry->NameInformation.FileName,
431                                       pCurrentObject->FileId.Cell,
432                                       pCurrentObject->FileId.Volume,
433                                       pCurrentObject->FileId.Vnode,
434                                       pCurrentObject->FileId.Unique));
435
436                         //
437                         // Directory TreeLock should be exclusively held
438                         //
439
440                         ntStatus = AFSVerifyEntry( AuthGroup,
441                                                    pDirEntry);
442
443                         AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
444
445                         if( !NT_SUCCESS( ntStatus))
446                         {
447
448                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
449                                           AFS_TRACE_LEVEL_ERROR,
450                                           "AFSLocateNameEntry (FO: %p) Failed to verify symlink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
451                                           FileObject,
452                                           &pDirEntry->NameInformation.FileName,
453                                           pCurrentObject->FileId.Cell,
454                                           pCurrentObject->FileId.Volume,
455                                           pCurrentObject->FileId.Vnode,
456                                           pCurrentObject->FileId.Unique,
457                                           ntStatus));
458
459                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
460
461                             try_return( ntStatus);
462                         }
463
464                         //
465                         // If the type changed then reprocess this entry
466                         //
467
468                         if( pCurrentObject->FileType != AFS_FILE_TYPE_SYMLINK)
469                         {
470
471                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
472
473                             continue;
474                         }
475                     }
476                     else
477                     {
478
479                         AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
480                     }
481
482                     //
483                     // If we were given a zero length target name then deny access to the entry
484                     //
485
486                     if( pDirEntry->NameInformation.TargetName.Length == 0)
487                     {
488
489                         ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
490
491                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
492                                       AFS_TRACE_LEVEL_ERROR,
493                                       "AFSLocateNameEntry (FO: %p) Failed to retrieve target name for symlink %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
494                                       FileObject,
495                                       &pDirEntry->NameInformation.FileName,
496                                       pCurrentObject->FileId.Cell,
497                                       pCurrentObject->FileId.Volume,
498                                       pCurrentObject->FileId.Vnode,
499                                       pCurrentObject->FileId.Unique,
500                                       ntStatus));
501
502                         AFSReleaseResource( &pDirEntry->NonPaged->Lock);
503
504                         try_return( ntStatus);
505                     }
506
507                     if( AFSIsRelativeName( &pDirEntry->NameInformation.TargetName))
508                     {
509
510                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
511                                       AFS_TRACE_LEVEL_VERBOSE,
512                                       "AFSLocateNameEntry (FO: %p) Processing relative symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
513                                       FileObject,
514                                       &pDirEntry->NameInformation.TargetName,
515                                       &pDirEntry->NameInformation.FileName,
516                                       pCurrentObject->FileId.Cell,
517                                       pCurrentObject->FileId.Volume,
518                                       pCurrentObject->FileId.Vnode,
519                                       pCurrentObject->FileId.Unique));
520
521                         //
522                         // We'll substitute this name into the current process name
523                         // starting at where we sit in the path
524                         //
525
526                         uniTempName.Length = 0;
527                         uniTempName.MaximumLength = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer) +
528                                                                     pDirEntry->NameInformation.TargetName.Length +
529                                                                     sizeof( WCHAR) +
530                                                                     uniRemainingPath.Length;
531
532                         uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
533                                                                                 uniTempName.MaximumLength,
534                                                                                 AFS_NAME_BUFFER_ONE_TAG);
535
536                         if( uniTempName.Buffer == NULL)
537                         {
538
539                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
540
541                             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
542                         }
543
544                         //
545                         // We have so first copy in the portion up to the component
546                         // name
547                         //
548
549                         RtlCopyMemory( uniTempName.Buffer,
550                                        uniFullPathName.Buffer,
551                                        (ULONG)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer));
552
553                         uniTempName.Length = (USHORT)((char *)uniComponentName.Buffer - (char *)uniFullPathName.Buffer);
554
555                         if( bAllocatedSymLinkBuffer ||
556                             bSubstitutedName)
557                         {
558
559                             pTmpBuffer = uniFullPathName.Buffer;
560                         }
561
562                         bAllocatedSymLinkBuffer = TRUE;
563
564                         //
565                         // Have we parsed this name yet? Better have at least once ...
566                         //
567
568                         if( uniComponentName.Length == 0)
569                         {
570                             ASSERT( FALSE);
571                         }
572
573                         //
574                         // Copy in the target name ...
575                         //
576
577                         RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
578                                        pDirEntry->NameInformation.TargetName.Buffer,
579                                        pDirEntry->NameInformation.TargetName.Length);
580
581                         uniPathName.Buffer = &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)];
582
583                         uniPathName.Length += pDirEntry->NameInformation.TargetName.Length;
584                         uniPathName.MaximumLength = uniTempName.MaximumLength;
585
586                         uniTempName.Length += pDirEntry->NameInformation.TargetName.Length;
587
588                         //
589                         // And now any remaining portion of the name
590                         //
591
592                         if( uniRemainingPath.Length > 0)
593                         {
594
595                             if( uniRemainingPath.Buffer[ 0] != L'\\')
596                             {
597
598                                 uniRemainingPath.Buffer--;
599                                 uniRemainingPath.Length += sizeof( WCHAR);
600
601                                 uniPathName.Length += sizeof( WCHAR);
602                             }
603
604                             RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
605                                            uniRemainingPath.Buffer,
606                                            uniRemainingPath.Length);
607
608                             uniTempName.Length += uniRemainingPath.Length;
609                         }
610
611                         uniFullPathName = uniTempName;
612
613                         if( pTmpBuffer != NULL)
614                         {
615
616                             AFSExFreePoolWithTag( pTmpBuffer, 0);
617                         }
618
619                         AFSReleaseResource( &pDirEntry->NonPaged->Lock);
620
621                         //
622                         // Dereference the current entry ..
623                         //
624
625                         lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
626
627                         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
628                                       AFS_TRACE_LEVEL_VERBOSE,
629                                       "AFSLocateNameEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
630                                       &pDirEntry->NameInformation.FileName,
631                                       pDirEntry,
632                                       NULL,
633                                       lCount));
634
635                         ASSERT( lCount >= 0);
636
637                         //
638                         // OK, need to back up one entry for the correct parent since the current
639                         // entry we are on is the symlink itself
640                         //
641
642                         pDirEntry = AFSBackupEntry( pNameArray);
643
644                         pCurrentObject = pDirEntry->ObjectInformation;
645
646                         //
647                         // Increment our reference on this dir entry
648                         //
649
650                         lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
651
652                         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
653                                       AFS_TRACE_LEVEL_VERBOSE,
654                                       "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
655                                       &pDirEntry->NameInformation.FileName,
656                                       pDirEntry,
657                                       NULL,
658                                       lCount));
659
660                         if ( pParentDirEntry)
661                         {
662
663                             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
664
665                             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
666                                           AFS_TRACE_LEVEL_VERBOSE,
667                                           "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
668                                           &pParentDirEntry->NameInformation.FileName,
669                                           pParentDirEntry,
670                                           NULL,
671                                           lCount));
672
673                             pParentDirEntry = NULL;
674                         }
675
676                         if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
677                         {
678
679                             pParentDirEntry = AFSGetParentEntry( pNameArray);
680
681                             ASSERT( pParentDirEntry != pDirEntry);
682
683                             lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
684
685                             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
686                                           AFS_TRACE_LEVEL_VERBOSE,
687                                           "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
688                                           &pParentDirEntry->NameInformation.FileName,
689                                           pParentDirEntry,
690                                           NULL,
691                                           lCount));
692                         }
693
694                         if ( pDirEntry->ObjectInformation->VolumeCB != pCurrentVolume)
695                         {
696
697                             lCount = AFSVolumeDecrement( pCurrentVolume,
698                                                          VolumeReferenceReason);
699
700                             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
701                                           AFS_TRACE_LEVEL_VERBOSE,
702                                           "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
703                                           pCurrentVolume,
704                                           VolumeReferenceReason,
705                                           lCount));
706
707                             pCurrentVolume = pDirEntry->ObjectInformation->VolumeCB;
708
709                             VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
710
711                             lCount = AFSVolumeIncrement( pCurrentVolume,
712                                                          VolumeReferenceReason);
713
714                             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
715                                           AFS_TRACE_LEVEL_VERBOSE,
716                                           "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
717                                           pCurrentVolume,
718                                           VolumeReferenceReason,
719                                           lCount));
720                         }
721                     }
722                     else
723                     {
724
725                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
726                                       AFS_TRACE_LEVEL_VERBOSE,
727                                       "AFSLocateNameEntry (FO: %p) Processing absolute symlink target %wZ for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
728                                       FileObject,
729                                       &pDirEntry->NameInformation.TargetName,
730                                       &pDirEntry->NameInformation.FileName,
731                                       pCurrentObject->FileId.Cell,
732                                       pCurrentObject->FileId.Volume,
733                                       pCurrentObject->FileId.Vnode,
734                                       pCurrentObject->FileId.Unique));
735
736                         if ( !AFSIsAbsoluteAFSName( &pDirEntry->NameInformation.TargetName))
737                         {
738
739                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
740                                           AFS_TRACE_LEVEL_ERROR,
741                                           "AFSLocateNameEntry Name %wZ contains invalid server name\n",
742                                           &pDirEntry->NameInformation.TargetName));
743
744                             //
745                             // The correct response would be STATUS_OBJECT_PATH_INVALID
746                             // but that prevents cmd.exe from performing a recursive
747                             // directory enumeration when opening a directory entry
748                             // that represents a symlink to an invalid path is discovered.
749                             //
750
751                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
752
753                             try_return( ntStatus = STATUS_OBJECT_PATH_NOT_FOUND);
754                         }
755
756                         //
757                         // We'll substitute this name into the current process name
758                         // starting at where we sit in the path
759                         //
760
761                         uniTempName.Length = 0;
762                         uniTempName.MaximumLength = pDirEntry->NameInformation.TargetName.Length +
763                                                                     sizeof( WCHAR) +
764                                                                     uniRemainingPath.Length;
765
766                         uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
767                                                                                 uniTempName.MaximumLength,
768                                                                                 AFS_NAME_BUFFER_TWO_TAG);
769
770                         if( uniTempName.Buffer == NULL)
771                         {
772
773                             AFSReleaseResource( &pDirEntry->NonPaged->Lock);
774
775                             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
776                         }
777
778                         if( bAllocatedSymLinkBuffer ||
779                             bSubstitutedName)
780                         {
781
782                             pTmpBuffer = uniFullPathName.Buffer;
783                         }
784
785                         bAllocatedSymLinkBuffer = TRUE;
786
787                         //
788                         // Have we parsed this name yet? Better have at least once ...
789                         //
790
791                         if( uniComponentName.Length == 0)
792                         {
793                             ASSERT( FALSE);
794                         }
795
796                         //
797                         // Copy in the target name ...
798                         //
799
800                         RtlCopyMemory( uniTempName.Buffer,
801                                        &pDirEntry->NameInformation.TargetName.Buffer[ AFSMountRootName.Length/sizeof( WCHAR)],
802                                        pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length);
803
804                         uniTempName.Length = pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length;
805
806                         //
807                         // And now any remaining portion of the name
808                         //
809
810                         if( uniRemainingPath.Length > 0)
811                         {
812
813                             if( uniRemainingPath.Buffer[ 0] != L'\\')
814                             {
815
816                                 uniRemainingPath.Buffer--;
817                                 uniRemainingPath.Length += sizeof( WCHAR);
818                             }
819
820                             RtlCopyMemory( &uniTempName.Buffer[ uniTempName.Length/sizeof( WCHAR)],
821                                            uniRemainingPath.Buffer,
822                                            uniRemainingPath.Length);
823
824                             uniTempName.Length += uniRemainingPath.Length;
825                         }
826
827                         uniFullPathName = uniTempName;
828
829                         uniPathName = uniTempName;
830
831                         if( pTmpBuffer != NULL)
832                         {
833
834                             AFSExFreePoolWithTag( pTmpBuffer, 0);
835                         }
836
837                         AFSReleaseResource( &pDirEntry->NonPaged->Lock);
838
839                         //
840                         // If our current volume is not the global root then make it so ...
841                         //
842
843                         if( pCurrentVolume != AFSGlobalRoot)
844                         {
845
846                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
847                                           AFS_TRACE_LEVEL_VERBOSE,
848                                           "AFSLocateNameEntry (FO: %p) Current volume not global, resetting for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
849                                           FileObject,
850                                           &pDirEntry->NameInformation.FileName,
851                                           pCurrentObject->FileId.Cell,
852                                           pCurrentObject->FileId.Volume,
853                                           pCurrentObject->FileId.Vnode,
854                                           pCurrentObject->FileId.Unique));
855
856                             lCount = AFSVolumeDecrement( pCurrentVolume,
857                                                          VolumeReferenceReason);
858
859                             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
860                                           AFS_TRACE_LEVEL_VERBOSE,
861                                           "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
862                                           pCurrentVolume,
863                                           VolumeReferenceReason,
864                                           lCount));
865
866                             pCurrentVolume = AFSGlobalRoot;
867
868                             VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
869
870                             lCount = AFSVolumeIncrement( pCurrentVolume,
871                                                          VolumeReferenceReason);
872
873                             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
874                                           AFS_TRACE_LEVEL_VERBOSE,
875                                           "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
876                                           pCurrentVolume,
877                                           VolumeReferenceReason,
878                                           lCount));
879                         }
880
881                         //
882                         // Dereference our current dir entry
883                         //
884
885                         lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
886
887                         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
888                                       AFS_TRACE_LEVEL_VERBOSE,
889                                       "AFSLocateNameEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
890                                       &pDirEntry->NameInformation.FileName,
891                                       pDirEntry,
892                                       NULL,
893                                       lCount));
894
895                         ASSERT( lCount >= 0);
896
897                         pDirEntry = pCurrentVolume->DirectoryCB;
898
899                         pCurrentObject = pDirEntry->ObjectInformation;
900
901                         //
902                         // Reference the new dir entry
903                         //
904
905                         lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
906
907                         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
908                                       AFS_TRACE_LEVEL_VERBOSE,
909                                       "AFSLocateNameEntry Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
910                                       &pDirEntry->NameInformation.FileName,
911                                       pDirEntry,
912                                       NULL,
913                                       lCount));
914
915                         //
916                         // Reset the name array
917                         // Persist the link count in the name array
918                         //
919
920                         lLinkCount = pNameArray->LinkCount;
921
922                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
923                                       AFS_TRACE_LEVEL_VERBOSE,
924                                       "AFSLocateNameEntry (FO: %p) Resetting name array for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
925                                       FileObject,
926                                       &pDirEntry->NameInformation.FileName,
927                                       pCurrentObject->FileId.Cell,
928                                       pCurrentObject->FileId.Volume,
929                                       pCurrentObject->FileId.Vnode,
930                                       pCurrentObject->FileId.Unique));
931
932                         AFSResetNameArray( pNameArray,
933                                            pDirEntry);
934
935                         pNameArray->LinkCount = lLinkCount;
936
937                         if ( pParentDirEntry)
938                         {
939
940                             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
941
942                             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
943                                           AFS_TRACE_LEVEL_VERBOSE,
944                                           "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
945                                           &pParentDirEntry->NameInformation.FileName,
946                                           pParentDirEntry,
947                                           NULL,
948                                           lCount));
949
950                             pParentDirEntry = NULL;
951                         }
952                     }
953
954                     //
955                     // Increment our link count
956                     //
957
958                     lCount = InterlockedIncrement( &pNameArray->LinkCount);
959
960                     continue;
961                 }
962
963                 case AFS_FILE_TYPE_MOUNTPOINT:
964                 {
965
966                     //
967                     // Check if the flag is set to NOT evaluate a mount point
968                     // and we are done with the parsing
969                     //
970
971                     if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL) &&
972                         uniRemainingPath.Length == 0)
973                     {
974
975                         //
976                         // Pass back the directory entries
977                         //
978
979                         *OutParentDirectoryCB = pParentDirEntry;
980
981                         pParentDirEntry = NULL;
982
983                         *OutDirectoryCB = pDirEntry;
984
985                         pDirEntry = NULL;
986
987                         *OutVolumeCB = pCurrentVolume;
988
989                         *OutVolumeReferenceReason = VolumeReferenceReason;
990
991                         bReleaseCurrentVolume = FALSE;
992
993                         *RootPathName = uniFullPathName;
994
995                         try_return( ntStatus);
996                     }
997
998                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
999                                   AFS_TRACE_LEVEL_VERBOSE,
1000                                   "AFSLocateNameEntry (FO: %p) Building MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1001                                   FileObject,
1002                                   &pDirEntry->NameInformation.FileName,
1003                                   pCurrentObject->FileId.Cell,
1004                                   pCurrentObject->FileId.Volume,
1005                                   pCurrentObject->FileId.Vnode,
1006                                   pCurrentObject->FileId.Unique));
1007
1008                     //
1009                     // Go retrieve the target entry for this node
1010                     // Release the current volume cb entry since we would
1011                     // have lock inversion in the following call
1012                     // Also decrement the ref count on the volume
1013                     //
1014
1015                     ntStatus = AFSBuildMountPointTarget( AuthGroup,
1016                                                          pDirEntry,
1017                                                          &pTargetVolume);
1018
1019                     if( !NT_SUCCESS( ntStatus))
1020                     {
1021
1022                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1023                                       AFS_TRACE_LEVEL_ERROR,
1024                                       "AFSLocateNameEntry (FO: %p) Failed to build MP target for parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1025                                       FileObject,
1026                                       &pDirEntry->NameInformation.FileName,
1027                                       pCurrentObject->FileId.Cell,
1028                                       pCurrentObject->FileId.Volume,
1029                                       pCurrentObject->FileId.Vnode,
1030                                       pCurrentObject->FileId.Unique,
1031                                       ntStatus));
1032
1033                         try_return( ntStatus);
1034                     }
1035
1036                     ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
1037
1038                     lCount = AFSVolumeDecrement( pCurrentVolume,
1039                                                  VolumeReferenceReason);
1040
1041                     AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1042                                   AFS_TRACE_LEVEL_VERBOSE,
1043                                   "AFSLocateNameEntry Decrement2 count on volume %p Reason %u Cnt %d\n",
1044                                   pCurrentVolume,
1045                                   VolumeReferenceReason,
1046                                   lCount));
1047
1048                     pCurrentVolume = pTargetVolume;
1049
1050                     pTargetVolume = NULL;
1051
1052                     ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
1053
1054                     VolumeReferenceReason = AFS_VOLUME_REFERENCE_MOUNTPT;
1055
1056                     //
1057                     // We want to restart processing here on the new parent ...
1058                     // Deref and ref count the entries
1059                     //
1060
1061                     lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1062
1063                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1064                                   AFS_TRACE_LEVEL_VERBOSE,
1065                                   "AFSLocateNameEntry Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
1066                                   &pDirEntry->NameInformation.FileName,
1067                                   pDirEntry,
1068                                   NULL,
1069                                   lCount));
1070
1071                     ASSERT( lCount >= 0);
1072
1073                     pDirEntry = pCurrentVolume->DirectoryCB;
1074
1075                     pCurrentObject = pDirEntry->ObjectInformation;
1076
1077                     lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1078
1079                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1080                                   AFS_TRACE_LEVEL_VERBOSE,
1081                                   "AFSLocateNameEntry Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
1082                                   &pDirEntry->NameInformation.FileName,
1083                                   pDirEntry,
1084                                   NULL,
1085                                   lCount));
1086
1087                     //
1088                     // The name array stores both the mount point and the target.
1089                     // Insert the target.
1090                     //
1091
1092                     AFSInsertNextElement( pNameArray,
1093                                           pDirEntry);
1094
1095                     if ( pParentDirEntry)
1096                     {
1097
1098                         lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1099
1100                         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1101                                       AFS_TRACE_LEVEL_VERBOSE,
1102                                       "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1103                                       &pParentDirEntry->NameInformation.FileName,
1104                                       pParentDirEntry,
1105                                       NULL,
1106                                       lCount));
1107
1108                         pParentDirEntry = NULL;
1109                     }
1110
1111                     //
1112                     // Increment our link count
1113                     //
1114
1115                     lCount = InterlockedIncrement( &pNameArray->LinkCount);
1116
1117                     continue;
1118                 }
1119
1120                 case AFS_FILE_TYPE_DFSLINK:
1121                 {
1122
1123                     if( BooleanFlagOn( Flags, AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL))
1124                     {
1125
1126                         //
1127                         // Pass back the directory entries
1128                         //
1129
1130                         *OutParentDirectoryCB = pParentDirEntry;
1131
1132                         pParentDirEntry = NULL;
1133
1134                         *OutDirectoryCB = pDirEntry;
1135
1136                         pDirEntry = NULL;
1137
1138                         *OutVolumeCB = pCurrentVolume;
1139
1140                         *OutVolumeReferenceReason = VolumeReferenceReason;
1141
1142                         bReleaseCurrentVolume = FALSE;
1143
1144                         *RootPathName = uniFullPathName;
1145
1146                         try_return( ntStatus);
1147                     }
1148
1149                     //
1150                     // This is a DFS link so we need to update the file name and return STATUS_REPARSE to the
1151                     // system for it to reevaluate it
1152                     //
1153
1154                     if( FileObject != NULL)
1155                     {
1156
1157                         ntStatus = AFSProcessDFSLink( pDirEntry,
1158                                                       FileObject,
1159                                                       &uniRemainingPath,
1160                                                       AuthGroup);
1161                     }
1162                     else
1163                     {
1164
1165                         //
1166                         // This is where we have been re-entered from an NP evaluation call via the BuildBranch()
1167                         // routine.
1168                         //
1169
1170                         ntStatus = STATUS_INVALID_PARAMETER;
1171                     }
1172
1173                     if( ntStatus != STATUS_SUCCESS &&
1174                         ntStatus != STATUS_REPARSE)
1175                     {
1176
1177                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1178                                       AFS_TRACE_LEVEL_ERROR,
1179                                       "AFSLocateNameEntry (FO: %p) Failed to process DFSLink parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1180                                       FileObject,
1181                                       &pDirEntry->NameInformation.FileName,
1182                                       pCurrentObject->FileId.Cell,
1183                                       pCurrentObject->FileId.Volume,
1184                                       pCurrentObject->FileId.Vnode,
1185                                       pCurrentObject->FileId.Unique,
1186                                       ntStatus));
1187                     }
1188
1189                     try_return( ntStatus);
1190                 }
1191
1192                 case AFS_FILE_TYPE_UNKNOWN:
1193                 case AFS_FILE_TYPE_INVALID:
1194                 {
1195
1196                     //
1197                     // Something was not processed ...
1198                     //
1199
1200                     try_return( ntStatus = STATUS_ACCESS_DENIED);
1201                 }
1202
1203             }   /* end of switch */
1204
1205             //
1206             // If the parent is not initialized then do it now
1207             //
1208
1209             if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1210                 !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED) &&
1211                 uniPathName.Length > 0)
1212             {
1213
1214                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1215                               AFS_TRACE_LEVEL_VERBOSE,
1216                               "AFSLocateNameEntry (FO: %p) Enumerating parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1217                               FileObject,
1218                               &pDirEntry->NameInformation.FileName,
1219                               pCurrentObject->FileId.Cell,
1220                               pCurrentObject->FileId.Volume,
1221                               pCurrentObject->FileId.Vnode,
1222                               pCurrentObject->FileId.Unique));
1223
1224                 AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1225                                 TRUE);
1226
1227                 if( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1228                 {
1229
1230                     ntStatus = AFSEnumerateDirectory( AuthGroup,
1231                                                       pCurrentObject,
1232                                                       TRUE);
1233
1234                     if( !NT_SUCCESS( ntStatus))
1235                     {
1236
1237                         AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1238
1239                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1240                                       AFS_TRACE_LEVEL_ERROR,
1241                                       "AFSLocateNameEntry (FO: %p) Failed to enumerate parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1242                                       FileObject,
1243                                       &pDirEntry->NameInformation.FileName,
1244                                       pCurrentObject->FileId.Cell,
1245                                       pCurrentObject->FileId.Volume,
1246                                       pCurrentObject->FileId.Vnode,
1247                                       pCurrentObject->FileId.Unique,
1248                                       ntStatus));
1249
1250                         try_return( ntStatus);
1251                     }
1252                 }
1253
1254                 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1255             }
1256             else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1257             {
1258
1259                 if( uniPathName.Length > 0)
1260                 {
1261
1262                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1263                                   AFS_TRACE_LEVEL_ERROR,
1264                                   "AFSLocateNameEntry (FO: %p) Encountered file node %wZ FID %08lX-%08lX-%08lX-%08lX in path processing\n",
1265                                   FileObject,
1266                                   &pDirEntry->NameInformation.FileName,
1267                                   pCurrentObject->FileId.Cell,
1268                                   pCurrentObject->FileId.Volume,
1269                                   pCurrentObject->FileId.Vnode,
1270                                   pCurrentObject->FileId.Unique));
1271
1272                     // The proper error code to return would be STATUS_OBJECT_PATH_INVALID because
1273                     // one of the components of the path is not a directory.  However, returning
1274                     // that error prevents IIS 7 and 7.5 from being able to serve data out of AFS.
1275                     // Instead IIS insists on treating the target file as if it is a directory containing
1276                     // a potential web.config file.  NTFS and LanMan return STATUS_OBJECT_PATH_NOT_FOUND.
1277                     // AFS will follow suit.
1278
1279                     ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1280                 }
1281                 else
1282                 {
1283
1284                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1285                                   AFS_TRACE_LEVEL_VERBOSE,
1286                                   "AFSLocateNameEntry (FO: %p) Returning file %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1287                                   FileObject,
1288                                   &pDirEntry->NameInformation.FileName,
1289                                   pCurrentObject->FileId.Cell,
1290                                   pCurrentObject->FileId.Volume,
1291                                   pCurrentObject->FileId.Vnode,
1292                                   pCurrentObject->FileId.Unique));
1293
1294                     //
1295                     // Pass back the directory entries
1296                     //
1297
1298                     *OutParentDirectoryCB = pParentDirEntry;
1299
1300                     pParentDirEntry = NULL;
1301
1302                     *OutDirectoryCB = pDirEntry;
1303
1304                     pDirEntry = NULL;
1305
1306                     *OutVolumeCB = pCurrentVolume;
1307
1308                     *OutVolumeReferenceReason = VolumeReferenceReason;
1309
1310                     bReleaseCurrentVolume = FALSE;
1311
1312                     *RootPathName = uniFullPathName;
1313                 }
1314
1315                 try_return( ntStatus);
1316             }
1317
1318             //
1319             // If we are at the end of the processing, set our returned information and get out
1320             //
1321
1322             if( uniPathName.Length == 0)
1323             {
1324
1325                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1326                               AFS_TRACE_LEVEL_VERBOSE,
1327                               "AFSLocateNameEntry (FO: %p) Completed processing returning %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1328                               FileObject,
1329                               &pDirEntry->NameInformation.FileName,
1330                               pCurrentObject->FileId.Cell,
1331                               pCurrentObject->FileId.Volume,
1332                               pCurrentObject->FileId.Vnode,
1333                               pCurrentObject->FileId.Unique));
1334
1335                 //
1336                 // Pass back the directory entries
1337                 //
1338
1339                 *OutParentDirectoryCB = pParentDirEntry;
1340
1341                 pParentDirEntry = NULL;
1342
1343                 *OutDirectoryCB = pDirEntry;
1344
1345                 pDirEntry = NULL;
1346
1347                 *OutVolumeCB = pCurrentVolume;
1348
1349                 *OutVolumeReferenceReason = VolumeReferenceReason;
1350
1351                 bReleaseCurrentVolume = FALSE;
1352
1353                 *RootPathName = uniFullPathName;
1354
1355                 try_return( ntStatus);
1356             }
1357
1358             //
1359             // We may have returned to the top of the while( TRUE)
1360             //
1361             if( bSubstituteName &&
1362                 uniSearchName.Buffer != NULL)
1363             {
1364
1365                 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1366
1367                 bSubstituteName = FALSE;
1368
1369                 uniSearchName.Length = uniSearchName.MaximumLength = 0;
1370                 uniSearchName.Buffer = NULL;
1371             }
1372
1373             ulSubstituteIndex = 1;
1374
1375             ntStatus = STATUS_SUCCESS;
1376
1377             //
1378             // Get the next component name
1379             //
1380
1381             FsRtlDissectName( uniPathName,
1382                               &uniComponentName,
1383                               &uniRemainingPath);
1384
1385             //
1386             // Check for the . and .. in the path
1387             //
1388
1389             if( RtlCompareUnicodeString( &uniComponentName,
1390                                          &uniNoOpName,
1391                                          TRUE) == 0)
1392             {
1393
1394                 uniPathName = uniRemainingPath;
1395
1396                 continue;
1397             }
1398
1399             if( RtlCompareUnicodeString( &uniComponentName,
1400                                          &uniRelativeName,
1401                                          TRUE) == 0)
1402             {
1403
1404                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1405                               AFS_TRACE_LEVEL_VERBOSE,
1406                               "AFSLocateNameEntry (FO: %p) Backing up entry from %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1407                               FileObject,
1408                               &pDirEntry->NameInformation.FileName,
1409                               pCurrentObject->FileId.Cell,
1410                               pCurrentObject->FileId.Volume,
1411                               pCurrentObject->FileId.Vnode,
1412                               pCurrentObject->FileId.Unique));
1413
1414                 //
1415                 // Need to back up one entry in the name array
1416                 //
1417                 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1418
1419                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1420                               AFS_TRACE_LEVEL_VERBOSE,
1421                               "AFSLocateNameEntry Decrement4 count on %wZ DE %p Ccb %p Cnt %d\n",
1422                               &pDirEntry->NameInformation.FileName,
1423                               pDirEntry,
1424                               NULL,
1425                               lCount));
1426
1427                 ASSERT( lCount >= 0);
1428
1429                 pDirEntry = AFSBackupEntry( NameArray);
1430
1431                 if( pDirEntry == NULL)
1432                 {
1433
1434                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1435                                   AFS_TRACE_LEVEL_ERROR,
1436                                   "AFSLocateNameEntry AFSBackupEntry failed\n"));
1437
1438                     try_return(ntStatus = STATUS_OBJECT_PATH_INVALID);
1439                 }
1440
1441                 pCurrentObject = pDirEntry->ObjectInformation;
1442
1443                 lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1444
1445                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1446                               AFS_TRACE_LEVEL_VERBOSE,
1447                               "AFSLocateNameEntry Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
1448                               &pDirEntry->NameInformation.FileName,
1449                               pDirEntry,
1450                               NULL,
1451                               lCount));
1452
1453                 if ( pParentDirEntry)
1454                 {
1455
1456                     lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1457
1458                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1459                                   AFS_TRACE_LEVEL_VERBOSE,
1460                                   "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1461                                   &pParentDirEntry->NameInformation.FileName,
1462                                   pParentDirEntry,
1463                                   NULL,
1464                                   lCount));
1465
1466                     pParentDirEntry = NULL;
1467                 }
1468
1469                 if( !BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_ROOT_VOLUME))
1470                 {
1471
1472                     pParentDirEntry = AFSGetParentEntry( pNameArray);
1473
1474                     ASSERT( pParentDirEntry != pDirEntry);
1475
1476                     if ( pParentDirEntry)
1477                     {
1478
1479                         lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
1480
1481                         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1482                                       AFS_TRACE_LEVEL_VERBOSE,
1483                                       "AFSLocateNameEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
1484                                       &pParentDirEntry->NameInformation.FileName,
1485                                       pParentDirEntry,
1486                                       NULL,
1487                                       lCount));
1488                     }
1489                 }
1490
1491                 if ( pDirEntry->ObjectInformation->VolumeCB != pCurrentVolume)
1492                 {
1493
1494                     lCount = AFSVolumeDecrement( pCurrentVolume,
1495                                                  VolumeReferenceReason);
1496
1497                     AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1498                                   AFS_TRACE_LEVEL_VERBOSE,
1499                                   "AFSLocateNameEntry Decrement count on volume %p Reason %u Cnt %d\n",
1500                                   pCurrentVolume,
1501                                   VolumeReferenceReason,
1502                                   lCount));
1503
1504                     pCurrentVolume = pDirEntry->ObjectInformation->VolumeCB;
1505
1506                     VolumeReferenceReason = AFS_VOLUME_REFERENCE_LOCATE_NAME;
1507
1508                     lCount = AFSVolumeIncrement( pCurrentVolume,
1509                                                  VolumeReferenceReason);
1510
1511                     AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1512                                   AFS_TRACE_LEVEL_VERBOSE,
1513                                   "AFSLocateNameEntry Increment count on volume %p Reason %u Cnt %d\n",
1514                                   pCurrentVolume,
1515                                   VolumeReferenceReason,
1516                                   lCount));
1517                 }
1518
1519                 uniPathName = uniRemainingPath;
1520
1521                 continue;
1522             }
1523
1524             //
1525             // Update our pointers
1526             //
1527
1528             if ( pParentDirEntry)
1529             {
1530
1531                 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1532
1533                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1534                               AFS_TRACE_LEVEL_VERBOSE,
1535                               "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1536                               &pParentDirEntry->NameInformation.FileName,
1537                               pParentDirEntry,
1538                               NULL,
1539                               lCount));
1540             }
1541
1542             pParentDirEntry = pDirEntry;
1543
1544             pDirEntry = NULL;
1545
1546             pCurrentObject = NULL;
1547
1548             uniSearchName = uniComponentName;
1549
1550             while( pDirEntry == NULL)
1551             {
1552
1553                 //
1554                 // If the SearchName contains @SYS then we perform the substitution.
1555                 // If there is no substitution we give up.
1556                 //
1557
1558                 if( !bSubstituteName &&
1559                     FsRtlIsNameInExpression( &uniSysName,
1560                                              &uniSearchName,
1561                                              TRUE,
1562                                              NULL))
1563                 {
1564
1565                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1566                                   AFS_TRACE_LEVEL_VERBOSE_2,
1567                                   "AFSLocateNameEntry (FO: %p) Processing @SYS substitution for %wZ Index %08lX\n",
1568                                   FileObject,
1569                                   &uniComponentName,
1570                                   ulSubstituteIndex));
1571
1572                     ntStatus = AFSSubstituteSysName( &uniComponentName,
1573                                                      &uniSearchName,
1574                                                      ulSubstituteIndex);
1575
1576                     if ( NT_SUCCESS( ntStatus))
1577                     {
1578
1579                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1580                                       AFS_TRACE_LEVEL_VERBOSE_2,
1581                                       "AFSLocateNameEntry (FO: %p) Located substitution %wZ for %wZ Index %08lX\n",
1582                                       FileObject,
1583                                       &uniSearchName,
1584                                       &uniComponentName,
1585                                       ulSubstituteIndex));
1586
1587                         //
1588                         // Go reparse the name again
1589                         //
1590
1591                         bSubstituteName = TRUE;
1592
1593                         ulSubstituteIndex++; // For the next entry, if needed
1594
1595                         continue;   // while( pDirEntry == NULL)
1596                     }
1597                     else
1598                     {
1599
1600                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1601                                       AFS_TRACE_LEVEL_ERROR,
1602                                       "AFSLocateNameEntry (FO: %p) Failed to locate substitute string for %wZ Index %08lX Status %08lX\n",
1603                                       FileObject,
1604                                       &uniComponentName,
1605                                       ulSubstituteIndex,
1606                                       ntStatus));
1607
1608                         if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
1609                         {
1610
1611                             //
1612                             // Pass back the directory entries
1613                             //
1614
1615                             *OutParentDirectoryCB = pParentDirEntry;
1616
1617                             pParentDirEntry = NULL;
1618
1619                             *OutDirectoryCB = NULL;
1620
1621                             *OutVolumeCB = pCurrentVolume;
1622
1623                             *OutVolumeReferenceReason = VolumeReferenceReason;
1624
1625                             bReleaseCurrentVolume = FALSE;
1626
1627                             if( ComponentName != NULL)
1628                             {
1629
1630                                 *ComponentName = uniComponentName;
1631                             }
1632
1633                             *RootPathName = uniFullPathName;
1634                         }
1635
1636                         //
1637                         // We can't possibly have a pDirEntry since the lookup failed
1638                         //
1639                         try_return( ntStatus);
1640                     }
1641                 }
1642
1643                 //
1644                 // Generate the CRC on the node and perform a case sensitive lookup
1645                 //
1646
1647                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1648                               AFS_TRACE_LEVEL_VERBOSE_2,
1649                               "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case sensitive\n",
1650                               FileObject,
1651                               &uniSearchName));
1652
1653                 ulCRC = AFSGenerateCRC( &uniSearchName,
1654                                         FALSE);
1655
1656                 AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1657                                   TRUE);
1658
1659                 AFSLocateCaseSensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
1660                                                 ulCRC,
1661                                                 &pDirEntry);
1662
1663                 if( pDirEntry == NULL)
1664                 {
1665
1666                     //
1667                     // Missed so perform a case insensitive lookup
1668                     //
1669
1670                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1671                                   AFS_TRACE_LEVEL_VERBOSE_2,
1672                                   "AFSLocateNameEntry (FO: %p) Searching for entry %wZ case insensitive\n",
1673                                   FileObject,
1674                                   &uniSearchName));
1675
1676                     ulCRC = AFSGenerateCRC( &uniSearchName,
1677                                             TRUE);
1678
1679                     AFSLocateCaseInsensitiveDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
1680                                                       ulCRC,
1681                                                       &pDirEntry);
1682
1683                     if( pDirEntry == NULL)
1684                     {
1685
1686                         //
1687                         // OK, if this component is a valid short name then try
1688                         // a lookup in the short name tree
1689                         //
1690
1691                         if( !BooleanFlagOn( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
1692                             RtlIsNameLegalDOS8Dot3( &uniSearchName,
1693                                                     NULL,
1694                                                     NULL))
1695                         {
1696
1697                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1698                                           AFS_TRACE_LEVEL_VERBOSE_2,
1699                                           "AFSLocateNameEntry (FO: %p) Searching for entry %wZ short name\n",
1700                                           FileObject,
1701                                           &uniSearchName));
1702
1703                             AFSLocateShortNameDirEntry( pParentDirEntry->ObjectInformation->Specific.Directory.ShortNameTree,
1704                                                         ulCRC,
1705                                                         &pDirEntry);
1706                         }
1707
1708                         if ( pDirEntry == NULL &&
1709                              pParentDirEntry->ObjectInformation->VolumeCB == AFSGlobalRoot)
1710                         {
1711
1712                             //
1713                             // Check with the service to see if this is a valid cell name
1714                             // that can be automatically resolved.  Drop the shared TreeLock
1715                             // since AFSCheckCellName must acquire it exclusively.
1716                             //
1717
1718                             AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1719
1720                             ntStatus = AFSCheckCellName( AuthGroup,
1721                                                          &uniSearchName,
1722                                                          &pDirEntry);
1723
1724                             AFSAcquireShared( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1725                                               TRUE);
1726                         }
1727
1728                         if( pDirEntry == NULL)
1729                         {
1730
1731                             //
1732                             // If we substituted a name then reset our search name and try again
1733                             //
1734
1735                             if( bSubstituteName)
1736                             {
1737
1738                                 AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
1739
1740                                 uniSearchName = uniComponentName;
1741
1742                                 bSubstituteName = FALSE;
1743
1744                                 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1745
1746                                 continue;       // while( pDirEntry == NULL)
1747                             }
1748
1749                             //
1750                             // Node name not found so get out
1751                             //
1752
1753                             AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1754
1755                             if( uniRemainingPath.Length > 0)
1756                             {
1757
1758                                 ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1759
1760                                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1761                                               AFS_TRACE_LEVEL_VERBOSE,
1762                                               "AFSLocateNameEntry (FO: %p) Returning path not found for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
1763                                               FileObject,
1764                                               &uniSearchName,
1765                                               pParentDirEntry->ObjectInformation->FileId.Cell,
1766                                               pParentDirEntry->ObjectInformation->FileId.Volume,
1767                                               pParentDirEntry->ObjectInformation->FileId.Vnode,
1768                                               pParentDirEntry->ObjectInformation->FileId.Unique));
1769                             }
1770                             else
1771                             {
1772
1773                                 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1774
1775                                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1776                                               AFS_TRACE_LEVEL_VERBOSE,
1777                                               "AFSLocateNameEntry (FO: %p) Returning name not found for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
1778                                               FileObject,
1779                                               &uniSearchName,
1780                                               pParentDirEntry->ObjectInformation->FileId.Cell,
1781                                               pParentDirEntry->ObjectInformation->FileId.Volume,
1782                                               pParentDirEntry->ObjectInformation->FileId.Vnode,
1783                                               pParentDirEntry->ObjectInformation->FileId.Unique));
1784
1785                                 //
1786                                 // Pass back the directory entries
1787                                 //
1788
1789                                 *OutParentDirectoryCB = pParentDirEntry;
1790
1791                                 pParentDirEntry = NULL;
1792
1793                                 *OutDirectoryCB = NULL;
1794
1795                                 *OutVolumeCB = pCurrentVolume;
1796
1797                                 *OutVolumeReferenceReason = VolumeReferenceReason;
1798
1799                                 bReleaseCurrentVolume = FALSE;
1800
1801                                 if( ComponentName != NULL)
1802                                 {
1803
1804                                     *ComponentName = uniComponentName;
1805                                 }
1806
1807                                 *RootPathName = uniFullPathName;
1808                             }
1809
1810                             try_return( ntStatus);
1811                         }
1812                     }
1813                     else
1814                     {
1815
1816                         //
1817                         // Here we have a match on the case insensitive lookup for the name. If there
1818                         // Is more than one link entry for this node then fail the lookup request
1819                         //
1820
1821                         pCurrentObject = pDirEntry->ObjectInformation;
1822
1823                         if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD) ||
1824                             pDirEntry->CaseInsensitiveList.fLink != NULL)
1825                         {
1826
1827                             //
1828                             // Increment our dir entry ref count since we will decrement it on exit
1829                             //
1830
1831                             lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1832
1833                             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1834                                           AFS_TRACE_LEVEL_VERBOSE,
1835                                           "AFSLocateNameEntry Increment5 count on %wZ DE %p Ccb %p Cnt %d\n",
1836                                           &pDirEntry->NameInformation.FileName,
1837                                           pDirEntry,
1838                                           NULL,
1839                                           lCount));
1840
1841                             AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1842
1843                             try_return(ntStatus = STATUS_OBJECT_NAME_COLLISION);
1844                         }
1845                     }
1846                 }
1847
1848                 if( pDirEntry != NULL)
1849                 {
1850
1851                     //
1852                     // If the verify flag is set on the parent and the current entry is deleted
1853                     // revalidate the parent and search again.
1854                     //
1855
1856                     pCurrentObject = pDirEntry->ObjectInformation;
1857
1858                     if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1859                         BooleanFlagOn( pParentDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
1860                     {
1861
1862                         AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1863
1864                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1865                                       AFS_TRACE_LEVEL_VERBOSE,
1866                                       "AFSLocateNameEntry (FO: %p) Verifying(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1867                                       FileObject,
1868                                       &pParentDirEntry->NameInformation.FileName,
1869                                       pParentDirEntry->ObjectInformation->FileId.Cell,
1870                                       pParentDirEntry->ObjectInformation->FileId.Volume,
1871                                       pParentDirEntry->ObjectInformation->FileId.Vnode,
1872                                       pParentDirEntry->ObjectInformation->FileId.Unique));
1873
1874                         //
1875                         // Directory TreeLock should be exclusively held
1876                         //
1877
1878                         AFSAcquireExcl( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
1879                                         TRUE);
1880
1881                         ntStatus = AFSVerifyEntry( AuthGroup,
1882                                                    pParentDirEntry);
1883
1884                         AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1885
1886                         if( !NT_SUCCESS( ntStatus))
1887                         {
1888
1889                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1890                                           AFS_TRACE_LEVEL_ERROR,
1891                                           "AFSLocateNameEntry (FO: %p) Failed to verify(2) parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1892                                           FileObject,
1893                                           &pParentDirEntry->NameInformation.FileName,
1894                                           pParentDirEntry->ObjectInformation->FileId.Cell,
1895                                           pParentDirEntry->ObjectInformation->FileId.Volume,
1896                                           pParentDirEntry->ObjectInformation->FileId.Vnode,
1897                                           pParentDirEntry->ObjectInformation->FileId.Unique,
1898                                           ntStatus));
1899
1900                             try_return( ntStatus);
1901                         }
1902
1903                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1904                                       AFS_TRACE_LEVEL_VERBOSE,
1905                                       "AFSLocateNameEntry (FO: %p) Reprocessing component %wZ in parent %wZ\n",
1906                                       FileObject,
1907                                       &uniSearchName,
1908                                       &pParentDirEntry->NameInformation.FileName));
1909
1910
1911                         pDirEntry = NULL;
1912
1913                         pCurrentObject = NULL;
1914
1915                         continue;
1916                     }
1917
1918                     //
1919                     // Increment our dir entry ref count
1920                     //
1921
1922                     lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
1923
1924                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1925                                   AFS_TRACE_LEVEL_VERBOSE,
1926                                   "AFSLocateNameEntry Increment6 count on %wZ DE %p Ccb %p Cnt %d\n",
1927                                   &pDirEntry->NameInformation.FileName,
1928                                   pDirEntry,
1929                                   NULL,
1930                                   lCount));
1931                 }
1932
1933                 AFSReleaseResource( pParentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
1934
1935             } // End while( pDirEntry == NULL)
1936
1937             //
1938             // If we have a dirEntry for this component, perform some basic validation on it
1939             //
1940
1941             if( pDirEntry != NULL)
1942             {
1943
1944                 pCurrentObject = pDirEntry->ObjectInformation;
1945
1946                 if (BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
1947                 {
1948
1949                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1950                                   AFS_TRACE_LEVEL_ERROR,
1951                                   "AFSLocateNameEntry (FO: %p) Deleted entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1952                                   FileObject,
1953                                   &pDirEntry->NameInformation.FileName,
1954                                   pCurrentObject->FileId.Cell,
1955                                   pCurrentObject->FileId.Volume,
1956                                   pCurrentObject->FileId.Vnode,
1957                                   pCurrentObject->FileId.Unique));
1958
1959                     //
1960                     // This entry was deleted through the invalidation call back so perform cleanup
1961                     // on the entry
1962                     //
1963
1964                     if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1965                     {
1966
1967                         pParentObjectInfo = AFSFindObjectInfo( pCurrentObject->VolumeCB,
1968                                                                &pCurrentObject->ParentFileId,
1969                                                                FALSE);
1970                     }
1971
1972                     ASSERT( pParentObjectInfo != NULL);
1973
1974                     AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1975                                     TRUE);
1976
1977                     AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1978                                     TRUE);
1979
1980                     lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1981
1982                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1983                                   AFS_TRACE_LEVEL_VERBOSE,
1984                                   "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1985                                   &pDirEntry->NameInformation.FileName,
1986                                   pDirEntry,
1987                                   NULL,
1988                                   lCount));
1989
1990                     ASSERT( lCount >= 0);
1991
1992                     if( lCount == 0 &&
1993                         pDirEntry->NameArrayReferenceCount <= 0)
1994                     {
1995
1996                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1997                                       AFS_TRACE_LEVEL_VERBOSE,
1998                                       "AFSLocateNameEntry Deleting dir entry %p (%p) for %wZ\n",
1999                                       pDirEntry,
2000                                       pCurrentObject,
2001                                       &pDirEntry->NameInformation.FileName));
2002
2003                         //
2004                         // Remove and delete the directory entry from the parent list
2005                         //
2006
2007                         AFSDeleteDirEntry( pParentObjectInfo,
2008                                            &pDirEntry);
2009
2010                         AFSAcquireShared( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
2011                                           TRUE);
2012
2013                         if( pCurrentObject->ObjectReferenceCount <= 0)
2014                         {
2015
2016                             if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
2017                             {
2018
2019                                 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2020                                               AFS_TRACE_LEVEL_VERBOSE,
2021                                               "AFSLocateNameEntry Removing object %p from volume tree\n",
2022                                               pCurrentObject));
2023
2024                                 AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
2025                                                     &pCurrentObject->TreeEntry);
2026
2027                                 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
2028                             }
2029                         }
2030
2031                         AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
2032                     }
2033                     else
2034                     {
2035
2036                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2037                                       AFS_TRACE_LEVEL_VERBOSE,
2038                                       "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
2039                                       pDirEntry,
2040                                       &pDirEntry->NameInformation.FileName));
2041
2042                         SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
2043
2044                         AFSRemoveNameEntry( pParentObjectInfo,
2045                                             pDirEntry);
2046                     }
2047
2048                     AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2049
2050                     AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
2051
2052                     //
2053                     // We deleted the dir entry so check if there is any remaining portion
2054                     // of the name to process.
2055                     //
2056
2057                     if( uniRemainingPath.Length > 0)
2058                     {
2059
2060                         ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
2061
2062                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2063                                       AFS_TRACE_LEVEL_VERBOSE,
2064                                       "AFSLocateNameEntry (FO: %p) Returning path not found(2) for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
2065                                       FileObject,
2066                                       &uniComponentName,
2067                                       pParentObjectInfo->FileId.Cell,
2068                                       pParentObjectInfo->FileId.Volume,
2069                                       pParentObjectInfo->FileId.Vnode,
2070                                       pParentObjectInfo->FileId.Unique));
2071
2072                         AFSReleaseObjectInfo( &pParentObjectInfo);
2073                     }
2074                     else
2075                     {
2076
2077                         ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
2078
2079                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2080                                       AFS_TRACE_LEVEL_VERBOSE,
2081                                       "AFSLocateNameEntry (FO: %p) Returning name not found(2) for %wZ in Parent FID %08lX-%08lX-%08lX-%08lX\n",
2082                                       FileObject,
2083                                       &uniComponentName,
2084                                       pParentObjectInfo->FileId.Cell,
2085                                       pParentObjectInfo->FileId.Volume,
2086                                       pParentObjectInfo->FileId.Vnode,
2087                                       pParentObjectInfo->FileId.Unique));
2088
2089                         AFSReleaseObjectInfo( &pParentObjectInfo);
2090
2091                         //
2092                         // Pass back the directory entries
2093                         //
2094
2095                         *OutParentDirectoryCB = pParentDirEntry;
2096
2097                         pParentDirEntry = NULL;
2098
2099                         *OutDirectoryCB = NULL;
2100
2101                         *OutVolumeCB = pCurrentVolume;
2102
2103                         *OutVolumeReferenceReason = VolumeReferenceReason;
2104
2105                         bReleaseCurrentVolume = FALSE;
2106
2107                         if( ComponentName != NULL)
2108                         {
2109
2110                             *ComponentName = uniComponentName;
2111                         }
2112
2113                         *RootPathName = uniFullPathName;
2114                     }
2115                 }
2116             }
2117
2118             if( ntStatus != STATUS_SUCCESS)
2119             {
2120
2121                 try_return( ntStatus);
2122             }
2123
2124             //
2125             // If we ended up substituting a name in the component then update
2126             // the full path and update the pointers
2127             //
2128
2129             if( bSubstituteName)
2130             {
2131
2132                 BOOLEAN bRelativeOpen = FALSE;
2133
2134                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2135                               AFS_TRACE_LEVEL_VERBOSE_2,
2136                               "AFSLocateNameEntry (FO: %p) Substituting %wZ into %wZ Index %08lX\n",
2137                               FileObject,
2138                               &uniSearchName,
2139                               &uniComponentName,
2140                               ulSubstituteIndex));
2141
2142                 if( FileObject != NULL &&
2143                     FileObject->RelatedFileObject != NULL)
2144                 {
2145
2146                     bRelativeOpen = TRUE;
2147                 }
2148
2149                 //
2150                 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
2151                 // and free the prior Buffer contents but only if the fourth
2152                 // parameter is TRUE.
2153                 //
2154
2155                 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
2156                                                     &uniComponentName,
2157                                                     &uniSearchName,
2158                                                     &uniRemainingPath,
2159                                                     bRelativeOpen ||
2160                                                     bAllocatedSymLinkBuffer ||
2161                                                     bSubstitutedName);
2162
2163                 if( !NT_SUCCESS( ntStatus))
2164                 {
2165
2166                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2167                                   AFS_TRACE_LEVEL_ERROR,
2168                                   "AFSLocateNameEntry (FO: %p) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
2169                                   FileObject,
2170                                   &uniSearchName,
2171                                   &uniComponentName,
2172                                   ulSubstituteIndex,
2173                                   ntStatus));
2174
2175                     try_return( ntStatus);
2176                 }
2177
2178                 //
2179                 // We have substituted a name into the buffer so if we do this again for this
2180                 // path, we need to free up the buffer we allocated.
2181                 //
2182
2183                 bSubstitutedName = TRUE;
2184             }
2185
2186             //
2187             // Update the search parameters
2188             //
2189
2190             uniPathName = uniRemainingPath;
2191
2192             //
2193             // Check if the is a SymLink entry but has no Target FileID or Name. In this
2194             // case it might be a DFS Link so let's go and evaluate it to be sure
2195             //
2196
2197             if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
2198                 ( pCurrentObject->TargetFileId.Vnode == 0 ||
2199                   pDirEntry->NameInformation.TargetName.Length == 0))
2200             {
2201
2202                 ntStatus = AFSValidateSymLink( AuthGroup,
2203                                                pDirEntry);
2204
2205                 if( !NT_SUCCESS( ntStatus))
2206                 {
2207
2208                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2209                                   AFS_TRACE_LEVEL_ERROR,
2210                                   "AFSLocateNameEntry (FO: %p) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2211                                   FileObject,
2212                                   &pDirEntry->NameInformation.FileName,
2213                                   pCurrentObject->FileId.Cell,
2214                                   pCurrentObject->FileId.Volume,
2215                                   pCurrentObject->FileId.Vnode,
2216                                   pCurrentObject->FileId.Unique,
2217                                   ntStatus));
2218
2219                     try_return( ntStatus);
2220                 }
2221             }
2222
2223             //
2224             // Update the name array
2225             //
2226
2227             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2228                           AFS_TRACE_LEVEL_VERBOSE,
2229                           "AFSLocateNameEntry (FO: %p) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2230                           FileObject,
2231                           &pDirEntry->NameInformation.FileName,
2232                           pCurrentObject->FileId.Cell,
2233                           pCurrentObject->FileId.Volume,
2234                           pCurrentObject->FileId.Vnode,
2235                           pCurrentObject->FileId.Unique));
2236
2237             ntStatus = AFSInsertNextElement( pNameArray,
2238                                              pDirEntry);
2239
2240             if( !NT_SUCCESS( ntStatus))
2241             {
2242
2243                 try_return( ntStatus);
2244             }
2245         }       // while (TRUE)
2246
2247 try_exit:
2248
2249         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2250                       AFS_TRACE_LEVEL_VERBOSE,
2251                       "AFSLocateNameEntry (FO: %p) Completed processing %wZ Status %08lX\n",
2252                       FileObject,
2253                       RootPathName,
2254                       ntStatus));
2255
2256         if( ( !NT_SUCCESS( ntStatus) &&
2257               ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
2258             ntStatus == STATUS_REPARSE)
2259         {
2260             if( RootPathName->Buffer != uniFullPathName.Buffer)
2261             {
2262
2263                 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
2264             }
2265         }
2266         else
2267         {
2268
2269             if( *OutParentDirectoryCB != NULL)
2270             {
2271
2272                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2273                               AFS_TRACE_LEVEL_VERBOSE,
2274                               "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
2275                               &(*OutParentDirectoryCB)->NameInformation.FileName,
2276                               *OutParentDirectoryCB,
2277                               NULL,
2278                               (*OutParentDirectoryCB)->DirOpenReferenceCount));
2279             }
2280
2281             if( *OutDirectoryCB != NULL)
2282             {
2283
2284                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2285                               AFS_TRACE_LEVEL_VERBOSE,
2286                               "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
2287                               &(*OutDirectoryCB)->NameInformation.FileName,
2288                               *OutDirectoryCB,
2289                               NULL,
2290                               (*OutDirectoryCB)->DirOpenReferenceCount));
2291             }
2292         }
2293
2294         if( pDirEntry != NULL)
2295         {
2296
2297             lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
2298
2299             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2300                           AFS_TRACE_LEVEL_VERBOSE,
2301                           "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
2302                           &pDirEntry->NameInformation.FileName,
2303                           pDirEntry,
2304                           NULL,
2305                           lCount));
2306
2307             ASSERT( lCount >= 0);
2308         }
2309
2310         if( pParentDirEntry != NULL)
2311         {
2312
2313             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
2314
2315             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2316                           AFS_TRACE_LEVEL_VERBOSE,
2317                           "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
2318                           &pParentDirEntry->NameInformation.FileName,
2319                           pParentDirEntry,
2320                           NULL,
2321                           lCount));
2322
2323             ASSERT( lCount >= 0);
2324         }
2325
2326         if( bReleaseCurrentVolume)
2327         {
2328
2329             ASSERT( pCurrentVolume->VolumeReferenceCount > 0);
2330
2331             lCount = AFSVolumeDecrement( pCurrentVolume,
2332                                          VolumeReferenceReason);
2333
2334             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2335                           AFS_TRACE_LEVEL_VERBOSE,
2336                           "AFSLocateNameEntry Decrement7 count on volume %p Reason %u Cnt %d\n",
2337                           pCurrentVolume,
2338                           VolumeReferenceReason,
2339                           lCount));
2340
2341             bReleaseCurrentVolume = FALSE;
2342         }
2343
2344         if( bSubstituteName &&
2345             uniSearchName.Buffer != NULL)
2346         {
2347
2348             AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
2349         }
2350     }
2351
2352     return ntStatus;
2353 }
2354
2355 NTSTATUS
2356 AFSCreateDirEntry( IN GUID            *AuthGroup,
2357                    IN AFSObjectInfoCB *ParentObjectInfo,
2358                    IN AFSDirectoryCB *ParentDirCB,
2359                    IN PUNICODE_STRING FileName,
2360                    IN PUNICODE_STRING ComponentName,
2361                    IN ULONG Attributes,
2362                    IN OUT AFSDirectoryCB **DirEntry)
2363 {
2364
2365     UNREFERENCED_PARAMETER(FileName);
2366     NTSTATUS ntStatus = STATUS_SUCCESS;
2367     AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
2368     LARGE_INTEGER liFileSize = {0,0};
2369     LONG lCount;
2370
2371     __Enter
2372     {
2373
2374         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2375                       AFS_TRACE_LEVEL_VERBOSE_2,
2376                       "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
2377                       &ParentDirCB->NameInformation.FileName,
2378                       ParentObjectInfo->FileId.Cell,
2379                       ParentObjectInfo->FileId.Volume,
2380                       ParentObjectInfo->FileId.Vnode,
2381                       ParentObjectInfo->FileId.Unique,
2382                       ComponentName,
2383                       Attributes));
2384
2385         //
2386         // OK, before inserting the node into the parent tree, issue
2387         // the request to the service for node creation
2388         // We will need to drop the lock on the parent node since the create
2389         // could cause a callback into the file system to invalidate it's cache
2390         //
2391
2392         ntStatus = AFSNotifyFileCreate( AuthGroup,
2393                                         ParentObjectInfo,
2394                                         &liFileSize,
2395                                         Attributes,
2396                                         ComponentName,
2397                                         &pDirNode);
2398
2399         //
2400         // If the returned status is STATUS_REPARSE then the entry exists
2401         // and we raced, get out.
2402
2403         if( ntStatus == STATUS_REPARSE)
2404         {
2405
2406             *DirEntry = pDirNode;
2407
2408             try_return( ntStatus = STATUS_SUCCESS);
2409         }
2410
2411         if( !NT_SUCCESS( ntStatus))
2412         {
2413
2414             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2415                           AFS_TRACE_LEVEL_ERROR,
2416                           "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
2417                           &ParentDirCB->NameInformation.FileName,
2418                           ParentObjectInfo->FileId.Cell,
2419                           ParentObjectInfo->FileId.Volume,
2420                           ParentObjectInfo->FileId.Vnode,
2421                           ParentObjectInfo->FileId.Unique,
2422                           ComponentName,
2423                           Attributes,
2424                           ntStatus));
2425
2426             try_return( ntStatus);
2427         }
2428
2429         //
2430         // If AFSNotifyFileCreate returns pDirNode != NULL, then its
2431         // DirOpenReferenceCount is held.
2432         //
2433
2434         AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2435                         TRUE);
2436
2437         //
2438         // Before attempting to insert the new entry, check if we need to validate the parent
2439         //
2440
2441         if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2442         {
2443
2444             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2445                           AFS_TRACE_LEVEL_VERBOSE,
2446                           "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2447                           &ParentDirCB->NameInformation.FileName,
2448                           ParentObjectInfo->FileId.Cell,
2449                           ParentObjectInfo->FileId.Volume,
2450                           ParentObjectInfo->FileId.Vnode,
2451                           ParentObjectInfo->FileId.Unique));
2452
2453             ntStatus = AFSVerifyEntry( AuthGroup,
2454                                        ParentDirCB);
2455
2456             if( !NT_SUCCESS( ntStatus))
2457             {
2458
2459                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2460                               AFS_TRACE_LEVEL_ERROR,
2461                               "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2462                               &ParentDirCB->NameInformation.FileName,
2463                               ParentObjectInfo->FileId.Cell,
2464                               ParentObjectInfo->FileId.Volume,
2465                               ParentObjectInfo->FileId.Vnode,
2466                               ParentObjectInfo->FileId.Unique,
2467                               ntStatus));
2468
2469                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2470
2471                 try_return( ntStatus);
2472             }
2473         }
2474
2475         //
2476         // Check for the entry in the event we raced with some other thread
2477         //
2478
2479         AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2480                                         (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2481                                         &pExistingDirNode);
2482
2483         if( pExistingDirNode != NULL)
2484         {
2485             if (AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2486                                &pExistingDirNode->ObjectInformation->FileId))
2487             {
2488
2489                 if ( pExistingDirNode != pDirNode)
2490                 {
2491
2492                     lCount = InterlockedDecrement( &pDirNode->DirOpenReferenceCount);
2493
2494                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2495                                   AFS_TRACE_LEVEL_VERBOSE,
2496                                   "AFSCreateDirEntry Decrement count on %wZ DE %p Cnt %d\n",
2497                                   &pDirNode->NameInformation.FileName,
2498                                   pDirNode,
2499                                   lCount));
2500
2501                     AFSDeleteDirEntry( ParentObjectInfo,
2502                                        &pDirNode);
2503
2504                     lCount = InterlockedIncrement( &pExistingDirNode->DirOpenReferenceCount);
2505
2506                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2507                                   AFS_TRACE_LEVEL_VERBOSE,
2508                                   "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2509                                   &pExistingDirNode->NameInformation.FileName,
2510                                   pExistingDirNode,
2511                                   lCount));
2512
2513                     *DirEntry = pExistingDirNode;
2514                 }
2515
2516                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2517
2518                 try_return( ntStatus = STATUS_SUCCESS);
2519             }
2520             else
2521             {
2522
2523                 //
2524                 // Need to tear down this entry and rebuild it below
2525                 //
2526
2527                 if( pExistingDirNode->DirOpenReferenceCount <= 0 &&
2528                     pExistingDirNode->NameArrayReferenceCount <= 0)
2529                 {
2530
2531                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2532                                   AFS_TRACE_LEVEL_VERBOSE,
2533                                   "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2534                                   pExistingDirNode,
2535                                   &pExistingDirNode->NameInformation.FileName,
2536                                   pExistingDirNode->ObjectInformation->FileId.Cell,
2537                                   pExistingDirNode->ObjectInformation->FileId.Volume,
2538                                   pExistingDirNode->ObjectInformation->FileId.Vnode,
2539                                   pExistingDirNode->ObjectInformation->FileId.Unique,
2540                                   pDirNode->ObjectInformation->FileId.Cell,
2541                                   pDirNode->ObjectInformation->FileId.Volume,
2542                                   pDirNode->ObjectInformation->FileId.Vnode,
2543                                   pDirNode->ObjectInformation->FileId.Unique));
2544
2545                     AFSDeleteDirEntry( ParentObjectInfo,
2546                                        &pExistingDirNode);
2547                 }
2548                 else
2549                 {
2550
2551                     SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2552
2553                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2554                                   AFS_TRACE_LEVEL_VERBOSE,
2555                                   "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2556                                   pExistingDirNode,
2557                                   &pExistingDirNode->NameInformation.FileName,
2558                                   pExistingDirNode->ObjectInformation->FileId.Cell,
2559                                   pExistingDirNode->ObjectInformation->FileId.Volume,
2560                                   pExistingDirNode->ObjectInformation->FileId.Vnode,
2561                                   pExistingDirNode->ObjectInformation->FileId.Unique,
2562                                   pDirNode->ObjectInformation->FileId.Cell,
2563                                   pDirNode->ObjectInformation->FileId.Volume,
2564                                   pDirNode->ObjectInformation->FileId.Vnode,
2565                                   pDirNode->ObjectInformation->FileId.Unique));
2566
2567                     AFSRemoveNameEntry( ParentObjectInfo,
2568                                         pExistingDirNode);
2569                 }
2570             }
2571         }
2572
2573         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2574                       AFS_TRACE_LEVEL_VERBOSE_2,
2575                       "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2576                       &ParentDirCB->NameInformation.FileName,
2577                       ParentObjectInfo->FileId.Cell,
2578                       ParentObjectInfo->FileId.Volume,
2579                       ParentObjectInfo->FileId.Vnode,
2580                       ParentObjectInfo->FileId.Unique,
2581                       ComponentName));
2582
2583         //
2584         // Insert the directory node
2585         //
2586
2587         AFSInsertDirectoryNode( ParentObjectInfo,
2588                                 pDirNode,
2589                                 TRUE);
2590
2591         //
2592         // Pass back the dir entry
2593         //
2594
2595         *DirEntry = pDirNode;
2596
2597         AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2598
2599 try_exit:
2600
2601         NOTHING;
2602     }
2603
2604     return ntStatus;
2605 }
2606
2607 void
2608 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2609                         IN AFSDirectoryCB *DirEntry,
2610                         IN BOOLEAN InsertInEnumList)
2611 {
2612
2613     LONG lCount;
2614
2615     __Enter
2616     {
2617
2618         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2619
2620         //
2621         // Insert the node into the directory node tree
2622         //
2623
2624         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2625                       AFS_TRACE_LEVEL_VERBOSE,
2626                       "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2627                       DirEntry,
2628                       &DirEntry->NameInformation.FileName));
2629
2630         ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2631
2632         if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2633         {
2634
2635             ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2636
2637             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2638                           AFS_TRACE_LEVEL_VERBOSE,
2639                           "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2640                           DirEntry,
2641                           &DirEntry->NameInformation.FileName));
2642         }
2643         else
2644         {
2645
2646             AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2647                                             DirEntry);
2648
2649             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2650                           AFS_TRACE_LEVEL_VERBOSE,
2651                           "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2652                           DirEntry,
2653                           &DirEntry->NameInformation.FileName));
2654         }
2655
2656         if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2657         {
2658
2659             ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2660
2661             SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2662
2663             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2664                           AFS_TRACE_LEVEL_VERBOSE,
2665                           "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2666                           DirEntry,
2667                           &DirEntry->NameInformation.FileName));
2668         }
2669         else
2670         {
2671
2672             AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2673                                               DirEntry);
2674
2675             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2676                           AFS_TRACE_LEVEL_VERBOSE,
2677                           "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2678                           DirEntry,
2679                           &DirEntry->NameInformation.FileName));
2680         }
2681
2682         //
2683         // Into the shortname tree
2684         //
2685
2686         if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2687         {
2688
2689             if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2690             {
2691
2692                 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2693
2694                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2695                               AFS_TRACE_LEVEL_VERBOSE,
2696                               "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2697                               DirEntry,
2698                               &DirEntry->NameInformation.FileName));
2699
2700                 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2701             }
2702             else
2703             {
2704
2705                 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2706                                                              DirEntry)))
2707                 {
2708                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2709                                   AFS_TRACE_LEVEL_VERBOSE,
2710                                   "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2711                                   DirEntry,
2712                                   &DirEntry->NameInformation.FileName));
2713                 }
2714                 else
2715                 {
2716                     SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2717
2718                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2719                                   AFS_TRACE_LEVEL_VERBOSE,
2720                                   "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2721                                   DirEntry,
2722                                   &DirEntry->NameInformation.FileName));
2723                 }
2724             }
2725         }
2726
2727         if( InsertInEnumList)
2728         {
2729
2730             //
2731             // And insert the node into the directory list
2732             //
2733
2734             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2735                           AFS_TRACE_LEVEL_VERBOSE,
2736                           "AFSInsertDirectoryNode Inserting entry %p %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2737                           DirEntry,
2738                           &DirEntry->NameInformation.FileName,
2739                           DirEntry->ObjectInformation->FileId.Cell,
2740                           DirEntry->ObjectInformation->FileId.Volume,
2741                           DirEntry->ObjectInformation->FileId.Vnode,
2742                           DirEntry->ObjectInformation->FileId.Unique));
2743
2744             if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2745             {
2746
2747                 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2748             }
2749             else
2750             {
2751
2752                 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2753
2754                 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2755             }
2756
2757             ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2758
2759             SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2760
2761             lCount = InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2762
2763             AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2764                           AFS_TRACE_LEVEL_VERBOSE,
2765                           "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2766                           &DirEntry->NameInformation.FileName,
2767                           lCount,
2768                           ParentObjectInfo->FileId.Cell,
2769                           ParentObjectInfo->FileId.Volume,
2770                           ParentObjectInfo->FileId.Vnode,
2771                           ParentObjectInfo->FileId.Unique));
2772         }
2773     }
2774
2775     return;
2776 }
2777
2778 void
2779 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2780                    IN AFSDirectoryCB **ppDirEntry)
2781 {
2782
2783     LONG lCount;
2784     AFSDirectoryCB *pDirEntry;
2785
2786     __Enter
2787     {
2788
2789         pDirEntry = (AFSDirectoryCB *) InterlockedCompareExchangePointer( (PVOID *)ppDirEntry,
2790                                                                           NULL,
2791                                                                           *ppDirEntry);
2792
2793         if ( pDirEntry == NULL)
2794         {
2795
2796             try_return( NOTHING);
2797         }
2798
2799         AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2800                       AFS_TRACE_LEVEL_VERBOSE,
2801                       "AFSDeleteDirEntry Deleting dir entry in parent %p Entry %p object %p %wZ RefCount %d\n",
2802                       ParentObjectInfo,
2803                       pDirEntry,
2804                       pDirEntry->ObjectInformation,
2805                       &pDirEntry->NameInformation.FileName,
2806                       pDirEntry->DirOpenReferenceCount));
2807
2808         ASSERT( pDirEntry->DirOpenReferenceCount == 0);
2809
2810         AFSRemoveDirNodeFromParent( ParentObjectInfo,
2811                                     pDirEntry,
2812                                     TRUE);
2813
2814         //
2815         // Free up the name buffer if it was reallocated
2816         //
2817
2818         if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2819         {
2820
2821             AFSExFreePoolWithTag( pDirEntry->NameInformation.FileName.Buffer, 0);
2822         }
2823
2824         if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2825         {
2826
2827             AFSExFreePoolWithTag( pDirEntry->NameInformation.TargetName.Buffer, 0);
2828         }
2829
2830         if ( pDirEntry->ObjectInformation != NULL)
2831         {
2832
2833             if( BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
2834                 pDirEntry->ObjectInformation->Links == 0)
2835             {
2836
2837                 SetFlag( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2838             }
2839
2840             //
2841             // Dereference the object for this dir entry
2842             //
2843
2844             AFSAcquireShared( pDirEntry->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock,
2845                               TRUE);
2846
2847             lCount = AFSObjectInfoDecrement( pDirEntry->ObjectInformation,
2848                                              AFS_OBJECT_REFERENCE_DIRENTRY);
2849
2850             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2851                           AFS_TRACE_LEVEL_VERBOSE,
2852                           "AFSDeleteDirEntry Decrement count on object %p Cnt %d\n",
2853                           pDirEntry->ObjectInformation,
2854                           lCount));
2855
2856             AFSReleaseResource( pDirEntry->ObjectInformation->VolumeCB->ObjectInfoTree.TreeLock);
2857         }
2858
2859         ExDeleteResourceLite( &pDirEntry->NonPaged->Lock);
2860
2861         AFSExFreePoolWithTag( pDirEntry->NonPaged, AFS_DIR_ENTRY_NP_TAG);
2862
2863         //
2864         // Free up the dir entry
2865         //
2866
2867         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
2868                       AFS_TRACE_LEVEL_VERBOSE,
2869                       "AFSDeleteDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
2870                       pDirEntry));
2871
2872         AFSExFreePoolWithTag( pDirEntry, AFS_DIR_ENTRY_TAG);
2873
2874 try_exit:
2875
2876         NOTHING;
2877     }
2878 }
2879
2880 NTSTATUS
2881 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2882                             IN AFSDirectoryCB *DirEntry,
2883                             IN BOOLEAN RemoveFromEnumList)
2884 {
2885
2886     NTSTATUS ntStatus = STATUS_SUCCESS;
2887     LONG lCount;
2888
2889     __Enter
2890     {
2891
2892
2893         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2894
2895         if ( DirEntry->ObjectInformation != NULL)
2896         {
2897
2898             AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2899                           AFS_TRACE_LEVEL_VERBOSE,
2900                           "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %p\n",
2901                           DirEntry,
2902                           &DirEntry->NameInformation.FileName,
2903                           DirEntry->ObjectInformation->FileId.Cell,
2904                           DirEntry->ObjectInformation->FileId.Volume,
2905                           DirEntry->ObjectInformation->FileId.Vnode,
2906                           DirEntry->ObjectInformation->FileId.Unique,
2907                           ParentObjectInfo));
2908         }
2909         else
2910         {
2911
2912             AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2913                           AFS_TRACE_LEVEL_VERBOSE,
2914                           "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ from Parent %p\n",
2915                           DirEntry,
2916                           &DirEntry->NameInformation.FileName,
2917                           ParentObjectInfo));
2918         }
2919
2920         if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2921         {
2922
2923             AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2924                           AFS_TRACE_LEVEL_VERBOSE,
2925                           "AFSRemoveDirNodeFromParent Removing DirEntry %p name %wZ\n",
2926                           DirEntry,
2927                           &DirEntry->NameInformation.FileName));
2928
2929             AFSRemoveNameEntry( ParentObjectInfo,
2930                                 DirEntry);
2931         }
2932         else
2933         {
2934
2935             AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
2936                           AFS_TRACE_LEVEL_VERBOSE,
2937                           "AFSRemoveDirNodeFromParent DE %p for %wZ NOT removing entry due to flag set\n",
2938                           DirEntry,
2939                           &DirEntry->NameInformation.FileName));
2940
2941         }
2942
2943         if( RemoveFromEnumList &&
2944             BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST))
2945         {
2946
2947             //
2948             // And remove the entry from the enumeration list
2949             //
2950
2951             if( DirEntry->ListEntry.fLink == NULL)
2952             {
2953
2954                 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = (AFSDirectoryCB *)DirEntry->ListEntry.bLink;
2955             }
2956             else
2957             {
2958
2959                 ((AFSDirectoryCB *)DirEntry->ListEntry.fLink)->ListEntry.bLink = DirEntry->ListEntry.bLink;
2960             }
2961
2962             if( DirEntry->ListEntry.bLink == NULL)
2963             {
2964
2965                 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = (AFSDirectoryCB *)DirEntry->ListEntry.fLink;
2966             }
2967             else
2968             {
2969
2970                 ((AFSDirectoryCB *)DirEntry->ListEntry.bLink)->ListEntry.fLink = DirEntry->ListEntry.fLink;
2971             }
2972
2973             ASSERT( ParentObjectInfo->Specific.Directory.DirectoryNodeCount > 0);
2974
2975             lCount = InterlockedDecrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2976
2977             ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2978
2979             AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2980                           AFS_TRACE_LEVEL_VERBOSE,
2981                           "AFSRemoveDirNodeFromParent Removing entry %wZ Dec Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2982                           &DirEntry->NameInformation.FileName,
2983                           lCount,
2984                           ParentObjectInfo->FileId.Cell,
2985                           ParentObjectInfo->FileId.Volume,
2986                           ParentObjectInfo->FileId.Vnode,
2987                           ParentObjectInfo->FileId.Unique));
2988
2989             DirEntry->ListEntry.fLink = NULL;
2990             DirEntry->ListEntry.bLink = NULL;
2991         }
2992     }
2993
2994     return ntStatus;
2995 }
2996
2997 NTSTATUS
2998 AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
2999                     IN OUT PUNICODE_STRING TargetFileName)
3000 {
3001
3002     NTSTATUS ntStatus = STATUS_SUCCESS;
3003     UNICODE_STRING uniFileName;
3004
3005     __Enter
3006     {
3007
3008         //
3009         // We will process backwards from the end of the name looking
3010         // for the first \ we encounter
3011         //
3012
3013         uniFileName.Length = FileName->Length;
3014         uniFileName.MaximumLength = FileName->MaximumLength;
3015
3016         uniFileName.Buffer = FileName->Buffer;
3017
3018         while( TRUE)
3019         {
3020
3021             if( uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
3022             {
3023
3024                 //
3025                 // Subtract one more character off of the filename if it is not the root
3026                 //
3027
3028                 if( uniFileName.Length > sizeof( WCHAR))
3029                 {
3030
3031                     uniFileName.Length -= sizeof( WCHAR);
3032                 }
3033
3034                 //
3035                 // Now build up the target name
3036                 //
3037
3038                 TargetFileName->Length = FileName->Length - uniFileName.Length;
3039
3040                 //
3041                 // If we are not on the root then fixup the name
3042                 //
3043
3044                 if( uniFileName.Length > sizeof( WCHAR))
3045                 {
3046
3047                     TargetFileName->Length -= sizeof( WCHAR);
3048
3049                     TargetFileName->Buffer = &uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) + 1];
3050                 }
3051                 else
3052                 {
3053
3054                     TargetFileName->Buffer = &uniFileName.Buffer[ uniFileName.Length/sizeof( WCHAR)];
3055                 }
3056
3057                 //
3058                 // Fixup the passed back filename length
3059                 //
3060
3061                 FileName->Length = uniFileName.Length;
3062
3063                 TargetFileName->MaximumLength = TargetFileName->Length;
3064
3065                 break;
3066             }
3067
3068             uniFileName.Length -= sizeof( WCHAR);
3069         }
3070     }
3071
3072     return ntStatus;
3073 }
3074
3075 NTSTATUS
3076 AFSParseName( IN PIRP Irp,
3077               IN GUID *AuthGroup,
3078               OUT PUNICODE_STRING FileName,
3079               OUT PUNICODE_STRING ParsedFileName,
3080               OUT PUNICODE_STRING RootFileName,
3081               OUT ULONG *ParseFlags,
3082               OUT AFSVolumeCB   **VolumeCB,
3083               OUT AFSDirectoryCB **ParentDirectoryCB,
3084               OUT AFSNameArrayHdr **NameArray)
3085 {
3086
3087     NTSTATUS            ntStatus = STATUS_SUCCESS;
3088     PIO_STACK_LOCATION  pIrpSp = IoGetCurrentIrpStackLocation( Irp);
3089     AFSDeviceExt       *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3090     UNICODE_STRING      uniFullName, uniComponentName, uniRemainingPath;
3091     ULONG               ulCRC = 0;
3092     AFSDirectoryCB     *pDirEntry = NULL;
3093     USHORT              usIndex = 0, usDriveIndex = 0;
3094     AFSCcb             *pRelatedCcb = NULL;
3095     AFSNameArrayHdr    *pNameArray = NULL, *pRelatedNameArray = NULL;
3096     USHORT              usComponentIndex = 0;
3097     USHORT              usComponentLength = 0;
3098     AFSVolumeCB        *pVolumeCB = NULL;
3099     AFSFcb             *pRelatedFcb = NULL;
3100     BOOLEAN             bReleaseTreeLock = FALSE;
3101     BOOLEAN             bIsAllShare = FALSE;
3102     LONG                lCount;
3103
3104     __Enter
3105     {
3106
3107         //
3108         // Indicate we are opening a root ...
3109         //
3110
3111         *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
3112
3113         *ParentDirectoryCB = NULL;
3114
3115         if( pIrpSp->FileObject->RelatedFileObject != NULL)
3116         {
3117
3118             pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
3119
3120             pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
3121
3122             pRelatedNameArray = pRelatedCcb->NameArray;
3123
3124             uniFullName = pIrpSp->FileObject->FileName;
3125
3126             ASSERT( pRelatedFcb != NULL);
3127
3128             //
3129             // No wild cards in the name
3130             //
3131
3132             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3133                           AFS_TRACE_LEVEL_VERBOSE_2,
3134                           "AFSParseName (%p) Relative open for %wZ FID %08lX-%08lX-%08lX-%08lX component %wZ\n",
3135                           Irp,
3136                           &pRelatedCcb->DirectoryCB->NameInformation.FileName,
3137                           pRelatedFcb->ObjectInformation->FileId.Cell,
3138                           pRelatedFcb->ObjectInformation->FileId.Volume,
3139                           pRelatedFcb->ObjectInformation->FileId.Vnode,
3140                           pRelatedFcb->ObjectInformation->FileId.Unique,
3141                           &uniFullName));
3142
3143             if( FsRtlDoesNameContainWildCards( &uniFullName))
3144             {
3145
3146                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3147                               AFS_TRACE_LEVEL_ERROR,
3148                               "AFSParseName (%p) Component %wZ contains wild cards\n",
3149                               Irp,
3150                               &uniFullName));
3151
3152                 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3153             }
3154
3155             pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
3156
3157             pDirEntry = pRelatedCcb->DirectoryCB;
3158
3159             *FileName = pIrpSp->FileObject->FileName;
3160
3161             //
3162             // Grab the root node while checking state
3163             //
3164
3165             AFSAcquireShared( pVolumeCB->VolumeLock,
3166                               TRUE);
3167
3168             if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3169                 BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3170             {
3171
3172                 //
3173                 // The volume has been taken off line so fail the access
3174                 //
3175
3176                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3177                               AFS_TRACE_LEVEL_ERROR,
3178                               "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3179                               Irp,
3180                               pVolumeCB->ObjectInformation.FileId.Cell,
3181                               pVolumeCB->ObjectInformation.FileId.Volume));
3182
3183                 AFSReleaseResource( pVolumeCB->VolumeLock);
3184
3185                 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3186             }
3187
3188             if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3189             {
3190
3191                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3192                               AFS_TRACE_LEVEL_VERBOSE,
3193                               "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
3194                               Irp,
3195                               pVolumeCB->ObjectInformation.FileId.Cell,
3196                               pVolumeCB->ObjectInformation.FileId.Volume));
3197
3198                 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3199                                             pVolumeCB);
3200
3201                 if( !NT_SUCCESS( ntStatus))
3202                 {
3203
3204                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3205                                   AFS_TRACE_LEVEL_ERROR,
3206                                   "AFSParseName (%p) Failed verification of root Status %08lX\n",
3207                                   Irp,
3208                                   ntStatus));
3209
3210                     AFSReleaseResource( pVolumeCB->VolumeLock);
3211
3212                     try_return( ntStatus);
3213                 }
3214             }
3215
3216             AFSReleaseResource( pVolumeCB->VolumeLock);
3217
3218             if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
3219             {
3220
3221                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3222                               AFS_TRACE_LEVEL_VERBOSE,
3223                               "AFSParseName (%p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3224                               Irp,
3225                               &pDirEntry->NameInformation.FileName,
3226                               pDirEntry->ObjectInformation->FileId.Cell,
3227                               pDirEntry->ObjectInformation->FileId.Volume,
3228                               pDirEntry->ObjectInformation->FileId.Vnode,
3229                               pDirEntry->ObjectInformation->FileId.Unique));
3230
3231                 //
3232                 // Directory TreeLock should be exclusively held
3233                 //
3234
3235                 AFSAcquireExcl( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
3236                                 TRUE);
3237
3238                 ntStatus = AFSVerifyEntry( AuthGroup,
3239                                            pDirEntry);
3240
3241                 AFSReleaseResource( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
3242
3243                 if( !NT_SUCCESS( ntStatus))
3244                 {
3245
3246                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3247                                   AFS_TRACE_LEVEL_VERBOSE,
3248                                   "AFSParseName (%p) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3249                                   Irp,
3250                                   &pDirEntry->NameInformation.FileName,
3251                                   pDirEntry->ObjectInformation->FileId.Cell,
3252                                   pDirEntry->ObjectInformation->FileId.Volume,
3253                                   pDirEntry->ObjectInformation->FileId.Vnode,
3254                                   pDirEntry->ObjectInformation->FileId.Unique,
3255                                   ntStatus));
3256
3257                     try_return( ntStatus);
3258                 }
3259             }
3260
3261             //
3262             // Create our full path name buffer
3263             //
3264
3265             uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length +
3266                                                     sizeof( WCHAR) +
3267                                                     pIrpSp->FileObject->FileName.Length +
3268                                                     sizeof( WCHAR);
3269
3270             uniFullName.Length = 0;
3271
3272             uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
3273                                                                     uniFullName.MaximumLength,
3274                                                                     AFS_NAME_BUFFER_THREE_TAG);
3275
3276             if( uniFullName.Buffer == NULL)
3277             {
3278
3279                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3280                               AFS_TRACE_LEVEL_ERROR,
3281                               "AFSParseName (%p) Failed to allocate full name buffer\n",
3282                               Irp));
3283
3284                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3285             }
3286
3287             RtlZeroMemory( uniFullName.Buffer,
3288                            uniFullName.MaximumLength);
3289
3290             RtlCopyMemory( uniFullName.Buffer,
3291                            pRelatedCcb->FullFileName.Buffer,
3292                            pRelatedCcb->FullFileName.Length);
3293
3294             uniFullName.Length = pRelatedCcb->FullFileName.Length;
3295
3296             usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
3297
3298             usComponentLength = pIrpSp->FileObject->FileName.Length;
3299
3300             if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
3301                 pIrpSp->FileObject->FileName.Length > 0 &&
3302                 pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
3303                 pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
3304             {
3305
3306                 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
3307
3308                 uniFullName.Length += sizeof( WCHAR);
3309
3310                 usComponentLength += sizeof( WCHAR);
3311             }
3312
3313             if( pIrpSp->FileObject->FileName.Length > 0)
3314             {
3315
3316                 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
3317                                pIrpSp->FileObject->FileName.Buffer,
3318                                pIrpSp->FileObject->FileName.Length);
3319
3320                 uniFullName.Length += pIrpSp->FileObject->FileName.Length;
3321             }
3322
3323             *RootFileName = uniFullName;
3324
3325             //
3326             // We populate up to the current parent
3327             //
3328
3329             if( pRelatedNameArray == NULL)
3330             {
3331
3332                 //
3333                 // Init and populate our name array
3334                 //
3335
3336                 pNameArray = AFSInitNameArray( NULL,
3337                                                0);
3338
3339                 if( pNameArray == NULL)
3340                 {
3341
3342                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3343                                   AFS_TRACE_LEVEL_VERBOSE,
3344                                   "AFSParseName (%p) Failed to initialize name array\n",
3345                                   Irp));
3346
3347                     AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3348
3349                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3350                 }
3351
3352                 ntStatus = AFSPopulateNameArray( pNameArray,
3353                                                  NULL,
3354                                                  pRelatedCcb->DirectoryCB);
3355             }
3356             else
3357             {
3358
3359                 //
3360                 // Init and populate our name array
3361                 //
3362
3363                 pNameArray = AFSInitNameArray( NULL,
3364                                                pRelatedNameArray->MaxElementCount);
3365
3366                 if( pNameArray == NULL)
3367                 {
3368
3369                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3370                                   AFS_TRACE_LEVEL_VERBOSE,
3371                                   "AFSParseName (%p) Failed to initialize name array\n",
3372                                   Irp));
3373
3374                     AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3375
3376                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3377                 }
3378
3379                 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
3380                                                                  pRelatedNameArray,
3381                                                                  pRelatedCcb->DirectoryCB);
3382             }
3383
3384             if( !NT_SUCCESS( ntStatus))
3385             {
3386
3387                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3388                               AFS_TRACE_LEVEL_VERBOSE,
3389                               "AFSParseName (%p) Failed to populate name array\n",
3390                               Irp));
3391
3392                 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3393
3394                 try_return( ntStatus);
3395             }
3396
3397             ParsedFileName->Length = usComponentLength;
3398             ParsedFileName->MaximumLength = uniFullName.MaximumLength;
3399
3400             ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
3401
3402             //
3403             // Indicate to caller that RootFileName must be freed
3404             //
3405
3406             SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
3407
3408             *NameArray = pNameArray;
3409
3410             //
3411             // Increment our volume reference count
3412             //
3413
3414             lCount = AFSVolumeIncrement( pVolumeCB,
3415                                          AFS_VOLUME_REFERENCE_PARSE_NAME);
3416
3417             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3418                           AFS_TRACE_LEVEL_VERBOSE,
3419                           "AFSParseName Increment count on volume %p Cnt %d\n",
3420                           pVolumeCB,
3421                           lCount));
3422
3423             *VolumeCB = pVolumeCB;
3424
3425             *ParentDirectoryCB = pDirEntry;
3426
3427             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3428                           AFS_TRACE_LEVEL_VERBOSE_2,
3429                           "AFSParseName (%p) Returning full name %wZ\n",
3430                           Irp,
3431                           &uniFullName));
3432
3433             try_return( ntStatus);
3434         }
3435
3436         //
3437         // No wild cards in the name
3438         //
3439
3440         uniFullName = pIrpSp->FileObject->FileName;
3441
3442         if( FsRtlDoesNameContainWildCards( &uniFullName) ||
3443             uniFullName.Length < AFSServerName.Length)
3444         {
3445
3446             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3447                           AFS_TRACE_LEVEL_ERROR,
3448                           "AFSParseName (%p) Name %wZ contains wild cards or too short\n",
3449                           Irp,
3450                           &uniFullName));
3451
3452             try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3453         }
3454
3455         //
3456         // The name is a fully qualified name. Parse out the server/share names and
3457         // point to the root qualified name
3458         // First thing is to locate the server name
3459         //
3460
3461         FsRtlDissectName( uniFullName,
3462                           &uniComponentName,
3463                           &uniRemainingPath);
3464
3465         uniFullName = uniRemainingPath;
3466
3467         //
3468         // This component is the server name we are serving
3469         //
3470
3471         if( RtlCompareUnicodeString( &uniComponentName,
3472                                      &AFSServerName,
3473                                      TRUE) != 0)
3474         {
3475
3476             //
3477             // Drive letter based name?
3478             //
3479
3480             uniFullName = pIrpSp->FileObject->FileName;
3481
3482             while( usIndex < uniFullName.Length/sizeof( WCHAR))
3483             {
3484
3485                 if( uniFullName.Buffer[ usIndex] == L':')
3486                 {
3487
3488                     uniFullName.Buffer = &uniFullName.Buffer[ usIndex + 2];
3489
3490                     uniFullName.Length -= (usIndex + 2) * sizeof( WCHAR);
3491
3492                     usDriveIndex = usIndex - 1;
3493
3494                     break;
3495                 }
3496
3497                 usIndex++;
3498             }
3499
3500             //
3501             // Do we have the right server name now?
3502             //
3503
3504             FsRtlDissectName( uniFullName,
3505                               &uniComponentName,
3506                               &uniRemainingPath);
3507
3508             uniFullName = uniRemainingPath;
3509
3510             //
3511             // This component is the server name we are serving
3512             //
3513
3514             if( RtlCompareUnicodeString( &uniComponentName,
3515                                          &AFSServerName,
3516                                          TRUE) != 0)
3517             {
3518
3519                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3520                               AFS_TRACE_LEVEL_ERROR,
3521                               "AFSParseName (%p) Name %wZ does not have server name\n",
3522                               Irp,
3523                               &pIrpSp->FileObject->FileName));
3524
3525                 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3526             }
3527
3528             //
3529             // Validate this drive letter is actively mapped
3530             //
3531
3532             if( usDriveIndex > 0 &&
3533                 !AFSIsDriveMapped( pIrpSp->FileObject->FileName.Buffer[ usDriveIndex]))
3534             {
3535
3536                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3537                               AFS_TRACE_LEVEL_ERROR,
3538                               "AFSParseName (%p) Name %wZ contains invalid drive mapping\n",
3539                               Irp,
3540                               &pIrpSp->FileObject->FileName));
3541
3542                 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3543             }
3544         }
3545
3546         if( FsRtlDoesNameContainWildCards( &uniFullName))
3547         {
3548
3549             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3550                           AFS_TRACE_LEVEL_ERROR,
3551                           "AFSParseName (%p) Component %wZ contains wild cards\n",
3552                           Irp,
3553                           &uniFullName));
3554
3555             try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3556         }
3557
3558         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3559                       AFS_TRACE_LEVEL_VERBOSE_2,
3560                       "AFSParseName (%p) Processing full name %wZ\n",
3561                       Irp,
3562                       &uniFullName));
3563
3564         if( uniFullName.Length > 0 &&
3565             uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] == L'\\')
3566         {
3567
3568             uniFullName.Length -= sizeof( WCHAR);
3569         }
3570
3571         //
3572         // Be sure we are online and ready to go
3573         //
3574
3575         AFSAcquireShared( AFSGlobalRoot->VolumeLock,
3576                           TRUE);
3577
3578         if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3579             BooleanFlagOn( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3580         {
3581
3582             //
3583             // The volume has been taken off line so fail the access
3584             //
3585
3586             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3587                           AFS_TRACE_LEVEL_ERROR,
3588                           "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3589                           Irp,
3590                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3591                           AFSGlobalRoot->ObjectInformation.FileId.Volume));
3592
3593             AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3594
3595             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3596         }
3597
3598         if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3599         {
3600
3601             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3602                           AFS_TRACE_LEVEL_VERBOSE,
3603                           "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
3604                           Irp,
3605                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3606                           AFSGlobalRoot->ObjectInformation.FileId.Volume));
3607
3608             ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3609                                         AFSGlobalRoot);
3610
3611             if( !NT_SUCCESS( ntStatus))
3612             {
3613
3614                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3615                               AFS_TRACE_LEVEL_ERROR,
3616                               "AFSParseName (%p) Failed verification of root Status %08lX\n",
3617                               Irp,
3618                               ntStatus));
3619
3620                 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3621
3622                 try_return( ntStatus);
3623             }
3624         }
3625
3626         AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3627
3628         if( !BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3629         {
3630
3631             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3632                           AFS_TRACE_LEVEL_VERBOSE,
3633                           "AFSParseName (%p) Enumerating global root of volume %08lX:%08lX\n",
3634                           Irp,
3635                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3636                           AFSGlobalRoot->ObjectInformation.FileId.Volume));
3637
3638             ntStatus = AFSEnumerateGlobalRoot( AuthGroup);
3639
3640             if( !NT_SUCCESS( ntStatus))
3641             {
3642
3643                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3644                               AFS_TRACE_LEVEL_ERROR,
3645                               "AFSParseName (%p) Failed enumeraiton of root Status %08lX\n",
3646                               Irp,
3647                               ntStatus));
3648
3649                 try_return( ntStatus);
3650             }
3651         }
3652
3653         //
3654         // Check for the \\Server access and return it as though it were \\Server\Globalroot
3655         //
3656
3657         if( uniRemainingPath.Buffer == NULL ||
3658             ( uniRemainingPath.Length == sizeof( WCHAR) &&
3659               uniRemainingPath.Buffer[ 0] == L'\\'))
3660         {
3661
3662             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3663                           AFS_TRACE_LEVEL_VERBOSE_2,
3664                           "AFSParseName (%p) Returning global root access\n",
3665                           Irp));
3666
3667             lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3668
3669             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3670                           AFS_TRACE_LEVEL_VERBOSE,
3671                           "AFSParseName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3672                           &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3673                           AFSGlobalRoot->DirectoryCB,
3674                           NULL,
3675                           lCount));
3676
3677             *VolumeCB = NULL;
3678
3679             FileName->Length = 0;
3680             FileName->MaximumLength = 0;
3681             FileName->Buffer = NULL;
3682
3683             try_return( ntStatus = STATUS_SUCCESS);
3684         }
3685
3686         *RootFileName = uniFullName;
3687
3688         //
3689         // Include the starting \ in the root name
3690         //
3691
3692         if( RootFileName->Buffer[ 0] != L'\\')
3693         {
3694             RootFileName->Buffer--;
3695             RootFileName->Length += sizeof( WCHAR);
3696             RootFileName->MaximumLength += sizeof( WCHAR);
3697         }
3698
3699         //
3700         // Get the 'share' name
3701         //
3702
3703         FsRtlDissectName( uniFullName,
3704                           &uniComponentName,
3705                           &uniRemainingPath);
3706
3707         if( FsRtlDoesNameContainWildCards( &uniFullName))
3708         {
3709
3710             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3711                           AFS_TRACE_LEVEL_ERROR,
3712                           "AFSParseName (%p) Component %wZ contains wild cards\n",
3713                           Irp,
3714                           &uniComponentName));
3715
3716             try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3717         }
3718
3719         //
3720         // If this is the ALL access then perform some additional processing
3721         //
3722
3723         if( uniComponentName.Length == 0 ||
3724             RtlCompareUnicodeString( &uniComponentName,
3725                                      &AFSGlobalRootName,
3726                                      TRUE) == 0)
3727         {
3728
3729             bIsAllShare = TRUE;
3730
3731             //
3732             // If there is nothing else then get out
3733             //
3734
3735             if( uniRemainingPath.Buffer == NULL ||
3736                 uniRemainingPath.Length == 0 ||
3737                 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3738                   uniRemainingPath.Buffer[ 0] == L'\\'))
3739             {
3740
3741                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3742                               AFS_TRACE_LEVEL_VERBOSE_2,
3743                               "AFSParseName (%p) Returning global root access\n",
3744                               Irp));
3745
3746                 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3747
3748                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3749                               AFS_TRACE_LEVEL_VERBOSE,
3750                               "AFSParseName Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
3751                               &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3752                               AFSGlobalRoot->DirectoryCB,
3753                               NULL,
3754                               lCount));
3755
3756                 *VolumeCB = NULL;
3757
3758                 FileName->Length = 0;
3759                 FileName->MaximumLength = 0;
3760                 FileName->Buffer = NULL;
3761
3762                 try_return( ntStatus = STATUS_SUCCESS);
3763             }
3764
3765             //
3766             // Process the name again to strip off the ALL portion
3767             //
3768
3769             uniFullName = uniRemainingPath;
3770
3771             FsRtlDissectName( uniFullName,
3772                               &uniComponentName,
3773                               &uniRemainingPath);
3774
3775             //
3776             // Check for the PIOCtl name
3777             //
3778
3779             if( RtlCompareUnicodeString( &uniComponentName,
3780                                          &AFSPIOCtlName,
3781                                          TRUE) == 0)
3782             {
3783
3784                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3785                               AFS_TRACE_LEVEL_VERBOSE_2,
3786                               "AFSParseName (%p) Returning root PIOCtl access\n",
3787                               Irp));
3788
3789                 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3790
3791                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3792                               AFS_TRACE_LEVEL_VERBOSE,
3793                               "AFSParseName Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
3794                               &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3795                               AFSGlobalRoot->DirectoryCB,
3796                               NULL,
3797                               lCount));
3798
3799                 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3800
3801                 *VolumeCB = NULL;
3802
3803                 *FileName = AFSPIOCtlName;
3804
3805                 try_return( ntStatus = STATUS_SUCCESS);
3806             }
3807         }
3808         else if( (pDirEntry = AFSGetSpecialShareNameEntry( &uniComponentName,
3809                                                            &uniRemainingPath)) != NULL)
3810         {
3811
3812             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3813                           AFS_TRACE_LEVEL_VERBOSE_2,
3814                           "AFSParseName (%p) Returning root share name %wZ access\n",
3815                           Irp,
3816                           &uniComponentName));
3817
3818             //
3819             // Add in the full share name to pass back
3820             //
3821
3822             if( uniRemainingPath.Buffer != NULL)
3823             {
3824
3825                 //
3826                 // This routine strips off the leading slash so add it back in
3827                 //
3828
3829                 uniRemainingPath.Buffer--;
3830                 uniRemainingPath.Length += sizeof( WCHAR);
3831                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3832
3833                 //
3834                 // And the cell name
3835                 //
3836
3837                 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3838                 uniRemainingPath.Length += uniComponentName.Length;
3839                 uniRemainingPath.MaximumLength += uniComponentName.Length;
3840
3841                 uniComponentName = uniRemainingPath;
3842             }
3843
3844             *VolumeCB = NULL;
3845
3846             *FileName = uniComponentName;
3847
3848             ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3849
3850             *ParentDirectoryCB = pDirEntry;
3851
3852             try_return( ntStatus = STATUS_SUCCESS);
3853         }
3854
3855         //
3856         // Determine the 'share' we are accessing
3857         //
3858
3859         ulCRC = AFSGenerateCRC( &uniComponentName,
3860                                 FALSE);
3861
3862         AFSAcquireShared( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3863                           TRUE);
3864
3865         bReleaseTreeLock = TRUE;
3866
3867         AFSLocateCaseSensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
3868                                         ulCRC,
3869                                         &pDirEntry);
3870
3871         if( pDirEntry == NULL)
3872         {
3873
3874             ulCRC = AFSGenerateCRC( &uniComponentName,
3875                                     TRUE);
3876
3877             AFSLocateCaseInsensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
3878                                               ulCRC,
3879                                               &pDirEntry);
3880
3881             if( pDirEntry == NULL)
3882             {
3883
3884                 //
3885                 // OK, if this component is a valid short name then try
3886                 // a lookup in the short name tree
3887                 //
3888
3889                 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3890                     RtlIsNameLegalDOS8Dot3( &uniComponentName,
3891                                             NULL,
3892                                             NULL))
3893                 {
3894
3895                     AFSLocateShortNameDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.ShortNameTree,
3896                                                 ulCRC,
3897                                                 &pDirEntry);
3898                 }
3899
3900                 if( pDirEntry == NULL)
3901                 {
3902
3903                     //
3904                     // Check with the service whether it is a valid cell name
3905                     //
3906
3907                     AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3908
3909                     bReleaseTreeLock = FALSE;
3910
3911                     ntStatus = AFSCheckCellName( AuthGroup,
3912                                                  &uniComponentName,
3913                                                  &pDirEntry);
3914
3915                     if( !NT_SUCCESS( ntStatus))
3916                     {
3917
3918                         if ( bIsAllShare &&
3919                              uniRemainingPath.Length == 0 &&
3920                              ntStatus == STATUS_OBJECT_PATH_NOT_FOUND)
3921                         {
3922
3923                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3924                                           AFS_TRACE_LEVEL_VERBOSE,
3925                                           "AFSParseName (%p) AFSCheckCellName %wZ returned path not found; ntStatus %08X\n",
3926                                           Irp,
3927                                           &uniComponentName,
3928                                           STATUS_OBJECT_NAME_NOT_FOUND));
3929
3930                             ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
3931                         }
3932
3933                         try_return( ntStatus);
3934                     }
3935                 }
3936             }
3937         }
3938
3939         if( bReleaseTreeLock)
3940         {
3941             AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3942         }
3943
3944
3945         //
3946         // Be sure we are starting from the correct volume
3947         //
3948
3949         if( pDirEntry->ObjectInformation->VolumeCB != AFSGlobalRoot)
3950         {
3951
3952             //
3953             // We dropped the global root in the CheckCellName routine which is the
3954             // only way we can be here
3955             //
3956
3957             pVolumeCB = pDirEntry->ObjectInformation->VolumeCB;
3958
3959             //
3960             // Init our name array
3961             //
3962
3963             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
3964                                            0);
3965
3966             if( pNameArray == NULL)
3967             {
3968
3969                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3970                               AFS_TRACE_LEVEL_VERBOSE,
3971                               "AFSParseName (%p) Failed to initialize name array\n",
3972                               Irp));
3973
3974                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3975             }
3976
3977             ntStatus = AFSInsertNextElement( pNameArray,
3978                                              pVolumeCB->DirectoryCB);
3979
3980             if ( ntStatus)
3981             {
3982
3983                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3984                               AFS_TRACE_LEVEL_VERBOSE,
3985                               "AFSParseName (%p) Failed to insert name array element\n",
3986                               Irp));
3987
3988                 try_return( ntStatus);
3989             }
3990
3991             //
3992             // In this case don't add back in the 'share' name since that is where we are
3993             // starting. Just put the leading slash back in
3994             //
3995
3996             if( uniRemainingPath.Buffer != NULL)
3997             {
3998
3999                 uniRemainingPath.Buffer--;
4000                 uniRemainingPath.Length += sizeof( WCHAR);
4001                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
4002
4003                 if( uniRemainingPath.Length > sizeof( WCHAR))
4004                 {
4005
4006                     ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
4007                 }
4008
4009                 //
4010                 // Pass back the parent being the root of the volume
4011                 //
4012
4013                 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
4014             }
4015             else
4016             {
4017
4018                 //
4019                 // Pass back a root slash
4020                 //
4021
4022                 uniRemainingPath = uniComponentName;
4023
4024                 uniRemainingPath.Buffer--;
4025                 uniRemainingPath.Length = sizeof( WCHAR);
4026                 uniRemainingPath.MaximumLength = sizeof( WCHAR);
4027
4028                 //
4029                 // This is a root open so pass back no parent
4030                 //
4031             }
4032         }
4033         else
4034         {
4035
4036             pVolumeCB = AFSGlobalRoot;
4037
4038             //
4039             // Init our name array
4040             //
4041
4042             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
4043                                            0);
4044             if( pNameArray == NULL)
4045             {
4046
4047                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4048                               AFS_TRACE_LEVEL_VERBOSE,
4049                               "AFSParseName (%p) Failed to initialize name array\n",
4050                               Irp));
4051
4052                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4053             }
4054
4055             //
4056             // Add back in the 'share' portion of the name since we will parse it out on return
4057             //
4058
4059             if( uniRemainingPath.Buffer != NULL)
4060             {
4061
4062                 //
4063                 // This routine strips off the leading slash so add it back in
4064                 //
4065
4066                 uniRemainingPath.Buffer--;
4067                 uniRemainingPath.Length += sizeof( WCHAR);
4068                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
4069
4070                 if( uniRemainingPath.Length > sizeof( WCHAR))
4071                 {
4072
4073                     ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
4074                 }
4075
4076                 //
4077                 // And the cell name
4078                 //
4079
4080                 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
4081                 uniRemainingPath.Length += uniComponentName.Length;
4082                 uniRemainingPath.MaximumLength += uniComponentName.Length;
4083             }
4084             else
4085             {
4086
4087                 uniRemainingPath = uniComponentName;
4088             }
4089
4090             //
4091             // And the leading slash again ...
4092             //
4093
4094             uniRemainingPath.Buffer--;
4095             uniRemainingPath.Length += sizeof( WCHAR);
4096             uniRemainingPath.MaximumLength += sizeof( WCHAR);
4097
4098             //
4099             // Pass back the parent being the volume root
4100             //
4101
4102             *ParentDirectoryCB = pVolumeCB->DirectoryCB;
4103         }
4104
4105         //
4106         // Return the remaining portion as the file name
4107         //
4108
4109         *FileName = uniRemainingPath;
4110
4111         *ParsedFileName = uniRemainingPath;
4112
4113         *NameArray = pNameArray;
4114
4115         *VolumeCB = pVolumeCB;
4116
4117         //
4118         // Increment our reference on the volume
4119         //
4120
4121         lCount = AFSVolumeIncrement( pVolumeCB,
4122                                      AFS_VOLUME_REFERENCE_PARSE_NAME);
4123
4124         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4125                       AFS_TRACE_LEVEL_VERBOSE,
4126                       "AFSParseName Increment2 count on global volume %p Cnt %d\n",
4127                       pVolumeCB,
4128                       lCount));
4129
4130 try_exit:
4131
4132         if( NT_SUCCESS( ntStatus))
4133         {
4134
4135             if( *ParentDirectoryCB != NULL)
4136             {
4137
4138                 lCount = InterlockedIncrement( &(*ParentDirectoryCB)->DirOpenReferenceCount);
4139
4140                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4141                               AFS_TRACE_LEVEL_VERBOSE,
4142                               "AFSParseName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4143                               &(*ParentDirectoryCB)->NameInformation.FileName,
4144                               (*ParentDirectoryCB),
4145                               NULL,
4146                               lCount));
4147             }
4148         }
4149
4150         if( *VolumeCB != NULL)
4151         {
4152             ASSERT( (*VolumeCB)->VolumeReferenceCount > 0);
4153         }
4154
4155         if( ntStatus != STATUS_SUCCESS)
4156         {
4157
4158             if( pNameArray != NULL)
4159             {
4160
4161                 AFSFreeNameArray( pNameArray);
4162             }
4163         }
4164     }
4165
4166     return ntStatus;
4167 }
4168
4169 NTSTATUS
4170 AFSCheckCellName( IN GUID *AuthGroup,
4171                   IN UNICODE_STRING *CellName,
4172                   OUT AFSDirectoryCB **ShareDirEntry)
4173 {
4174
4175     NTSTATUS ntStatus = STATUS_SUCCESS;
4176     UNICODE_STRING uniName;
4177     AFSDirEnumEntry *pDirEnumEntry = NULL;
4178     AFSDirHdr *pDirHdr = &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr;
4179     AFSDirectoryCB *pDirNode = NULL;
4180     UNICODE_STRING uniDirName, uniTargetName;
4181     AFSVolumeCB *pVolumeCB = NULL;
4182     LONG lCount;
4183
4184     __Enter
4185     {
4186
4187         //
4188         // Look for some default names we will not handle
4189         //
4190
4191         RtlInitUnicodeString( &uniName,
4192                               L"IPC$");
4193
4194         if( RtlCompareUnicodeString( &uniName,
4195                                      CellName,
4196                                      TRUE) == 0)
4197         {
4198
4199             try_return( ntStatus = STATUS_NO_SUCH_FILE);
4200         }
4201
4202         RtlInitUnicodeString( &uniName,
4203                               L"wkssvc");
4204
4205         if( RtlCompareUnicodeString( &uniName,
4206                                      CellName,
4207                                      TRUE) == 0)
4208         {
4209
4210             try_return( ntStatus = STATUS_NO_SUCH_FILE);
4211         }
4212
4213         RtlInitUnicodeString( &uniName,
4214                               L"srvsvc");
4215
4216         if( RtlCompareUnicodeString( &uniName,
4217                                      CellName,
4218                                      TRUE) == 0)
4219         {
4220
4221             try_return( ntStatus = STATUS_NO_SUCH_FILE);
4222         }
4223
4224         RtlInitUnicodeString( &uniName,
4225                               L"PIPE");
4226
4227         if( RtlCompareUnicodeString( &uniName,
4228                                      CellName,
4229                                      TRUE) == 0)
4230         {
4231
4232             try_return( ntStatus = STATUS_NO_SUCH_FILE);
4233         }
4234
4235         //
4236         // OK, ask the CM about this component name
4237         //
4238
4239         ntStatus = AFSEvaluateTargetByName( AuthGroup,
4240                                             &AFSGlobalRoot->ObjectInformation,
4241                                             CellName,
4242                                             0,
4243                                             &pDirEnumEntry);
4244
4245         if( !NT_SUCCESS( ntStatus))
4246         {
4247
4248             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4249                           AFS_TRACE_LEVEL_WARNING,
4250                           "AFSCheckCellName entry %wZ does not exist parent FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4251                           CellName,
4252                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
4253                           AFSGlobalRoot->ObjectInformation.FileId.Volume,
4254                           AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4255                           AFSGlobalRoot->ObjectInformation.FileId.Unique,
4256                           ntStatus));
4257
4258             try_return( ntStatus);
4259         }
4260
4261         //
4262         // OK, we have a dir enum entry back so add it to the root node
4263         //
4264
4265         uniDirName = *CellName;
4266
4267         uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
4268         uniTargetName.MaximumLength = uniTargetName.Length;
4269         uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
4270
4271         //
4272         // Is this entry a root volume entry?
4273         //
4274
4275         if( pDirEnumEntry->FileId.Cell != AFSGlobalRoot->ObjectInformation.FileId.Cell ||
4276             pDirEnumEntry->FileId.Volume != AFSGlobalRoot->ObjectInformation.FileId.Volume)
4277         {
4278
4279             //
4280             // Build the root volume entry
4281             //
4282
4283             ntStatus = AFSBuildRootVolume( AuthGroup,
4284                                            &pDirEnumEntry->FileId,
4285                                            &pVolumeCB);
4286
4287             //
4288             // On success returns with a volume reference count held
4289             //
4290
4291             if( !NT_SUCCESS( ntStatus))
4292             {
4293                 try_return( ntStatus);
4294             }
4295
4296             *ShareDirEntry = pVolumeCB->DirectoryCB;
4297
4298             lCount = InterlockedIncrement( &pVolumeCB->DirectoryCB->DirOpenReferenceCount);
4299
4300             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4301                           AFS_TRACE_LEVEL_VERBOSE,
4302                           "AFSCheckCellName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4303                           &pVolumeCB->DirectoryCB->NameInformation.FileName,
4304                           pVolumeCB->DirectoryCB,
4305                           NULL,
4306                           lCount));
4307
4308             lCount = AFSVolumeDecrement( pVolumeCB,
4309                                          AFS_VOLUME_REFERENCE_BUILD_ROOT);
4310
4311             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4312                           AFS_TRACE_LEVEL_VERBOSE,
4313                           "AFSCheckCellName Decrement count on volume %p Cnt %d\n",
4314                           pVolumeCB,
4315                           lCount));
4316         }
4317         else
4318         {
4319
4320             lCount = InterlockedIncrement( &pDirHdr->ContentIndex);
4321
4322             pDirNode = AFSInitDirEntry( &AFSGlobalRoot->ObjectInformation,
4323                                         &uniDirName,
4324                                         &uniTargetName,
4325                                         pDirEnumEntry,
4326                                         (ULONG)lCount);
4327
4328             if( pDirNode == NULL)
4329             {
4330
4331                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4332             }
4333
4334             //
4335             // Init the short name if we have one
4336             //
4337
4338             if( pDirEnumEntry->ShortNameLength > 0)
4339             {
4340
4341                 pDirNode->NameInformation.ShortNameLength = pDirEnumEntry->ShortNameLength;
4342
4343                 RtlCopyMemory( pDirNode->NameInformation.ShortName,
4344                                pDirEnumEntry->ShortName,
4345                                pDirNode->NameInformation.ShortNameLength);
4346             }
4347
4348             AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4349                             TRUE);
4350
4351             //
4352             // Insert the node into the name tree
4353             //
4354
4355             ASSERT( ExIsResourceAcquiredExclusiveLite( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock));
4356
4357             if( pDirHdr->CaseSensitiveTreeHead == NULL)
4358             {
4359
4360                 pDirHdr->CaseSensitiveTreeHead = pDirNode;
4361             }
4362             else
4363             {
4364
4365                 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( pDirHdr->CaseSensitiveTreeHead,
4366                                                                  pDirNode)))
4367                 {
4368
4369                     AFSDeleteDirEntry( &AFSGlobalRoot->ObjectInformation,
4370                                        &pDirNode);
4371
4372                     AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4373
4374                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4375                 }
4376             }
4377
4378             ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
4379
4380             if( pDirHdr->CaseInsensitiveTreeHead == NULL)
4381             {
4382
4383                 pDirHdr->CaseInsensitiveTreeHead = pDirNode;
4384
4385                 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
4386             }
4387             else
4388             {
4389
4390                 AFSInsertCaseInsensitiveDirEntry( pDirHdr->CaseInsensitiveTreeHead,
4391                                                   pDirNode);
4392             }
4393
4394             if( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead == NULL)
4395             {
4396
4397                 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead = pDirNode;
4398             }
4399             else
4400             {
4401
4402                 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
4403
4404                 pDirNode->ListEntry.bLink = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail;
4405             }
4406
4407             AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail = pDirNode;
4408
4409             SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
4410
4411             lCount = InterlockedIncrement( &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeCount);
4412
4413             AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
4414                           AFS_TRACE_LEVEL_VERBOSE,
4415                           "AFSCheckCellName Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
4416                           &pDirNode->NameInformation.FileName,
4417                           lCount,
4418                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
4419                           AFSGlobalRoot->ObjectInformation.FileId.Volume,
4420                           AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4421                           AFSGlobalRoot->ObjectInformation.FileId.Unique));
4422
4423             lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
4424
4425             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4426                           AFS_TRACE_LEVEL_VERBOSE,
4427                           "AFSCheckCellName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
4428                           &pDirNode->NameInformation.FileName,
4429                           pDirNode,
4430                           NULL,
4431                           lCount));
4432
4433             AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4434
4435             //
4436             // Pass back the dir node
4437             //
4438
4439             *ShareDirEntry = pDirNode;
4440         }
4441
4442 try_exit:
4443
4444         if( pDirEnumEntry != NULL)
4445         {
4446
4447             AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_31_TAG);
4448         }
4449     }
4450
4451     return ntStatus;
4452 }
4453
4454 NTSTATUS
4455 AFSBuildMountPointTarget( IN GUID *AuthGroup,
4456                           IN AFSDirectoryCB  *DirectoryCB,
4457                           OUT AFSVolumeCB **TargetVolumeCB)
4458 {
4459
4460     NTSTATUS ntStatus = STATUS_SUCCESS;
4461     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4462     AFSDirEnumEntry *pDirEntry = NULL;
4463     ULONGLONG       ullIndex = 0;
4464     AFSVolumeCB *pVolumeCB = NULL;
4465     AFSFileID stTargetFileID;
4466     LONG lCount;
4467     BOOLEAN bReleaseVolumeLock = FALSE;
4468
4469     __Enter
4470     {
4471
4472         //
4473         // Loop on each entry, building the chain until we encounter the final target
4474         //
4475
4476         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4477                       AFS_TRACE_LEVEL_VERBOSE_2,
4478                       "AFSBuildMountPointTarget Building target directory for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4479                       &DirectoryCB->NameInformation.FileName,
4480                       DirectoryCB->ObjectInformation->FileId.Cell,
4481                       DirectoryCB->ObjectInformation->FileId.Volume,
4482                       DirectoryCB->ObjectInformation->FileId.Vnode,
4483                       DirectoryCB->ObjectInformation->FileId.Unique));
4484
4485         //
4486         // Do we need to evaluate the node?
4487         //
4488
4489         //if( DirectoryCB->ObjectInformation->TargetFileId.Vnode == 0 &&
4490         //    DirectoryCB->ObjectInformation->TargetFileId.Unique == 0)
4491         {
4492
4493             //
4494             // Go evaluate the current target to get the target fid
4495             //
4496
4497             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4498                           AFS_TRACE_LEVEL_VERBOSE_2,
4499                           "AFSBuildMountPointTarget Evaluating target %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4500                               &DirectoryCB->NameInformation.FileName,
4501                               DirectoryCB->ObjectInformation->FileId.Cell,
4502                               DirectoryCB->ObjectInformation->FileId.Volume,
4503                               DirectoryCB->ObjectInformation->FileId.Vnode,
4504                               DirectoryCB->ObjectInformation->FileId.Unique));
4505
4506             ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
4507                                               AuthGroup,
4508                                               FALSE,
4509                                               &pDirEntry);
4510
4511             if( !NT_SUCCESS( ntStatus))
4512             {
4513
4514                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4515                               AFS_TRACE_LEVEL_ERROR,
4516                               "AFSBuildMountPointTarget Failed to evaluate target %wZ Status %08lX\n",
4517                               &DirectoryCB->NameInformation.FileName,
4518                               ntStatus));
4519
4520                 try_return( ntStatus);
4521             }
4522
4523             if( pDirEntry->TargetFileId.Vnode == 0 &&
4524                 pDirEntry->TargetFileId.Unique == 0)
4525             {
4526
4527                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4528                               AFS_TRACE_LEVEL_ERROR,
4529                               "AFSBuildMountPointTarget Target %wZ FID %08lX-%08lX-%08lX-%08lX service returned zero FID\n",
4530                               &DirectoryCB->NameInformation.FileName,
4531                               DirectoryCB->ObjectInformation->FileId.Cell,
4532                               DirectoryCB->ObjectInformation->FileId.Volume,
4533                               DirectoryCB->ObjectInformation->FileId.Vnode,
4534                               DirectoryCB->ObjectInformation->FileId.Unique));
4535
4536                 try_return( ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED);
4537             }
4538
4539             AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
4540                             TRUE);
4541
4542             ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
4543                                             &DirectoryCB->Flags,
4544                                             (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4545                                             (USHORT)pDirEntry->TargetNameLength);
4546
4547             if( !NT_SUCCESS( ntStatus))
4548             {
4549
4550                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4551
4552                 try_return( ntStatus);
4553             }
4554
4555             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4556
4557             DirectoryCB->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
4558         }
4559
4560         stTargetFileID = DirectoryCB->ObjectInformation->TargetFileId;
4561
4562         //
4563         // Try to locate this FID. First the volume then the
4564         // entry itself
4565         //
4566
4567         ullIndex = AFSCreateHighIndex( &stTargetFileID);
4568
4569         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4570                       AFS_TRACE_LEVEL_VERBOSE,
4571                       "AFSBuildMountPointTarget Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4572                       &pDevExt->Specific.RDR.VolumeTreeLock,
4573                       PsGetCurrentThread()));
4574
4575         AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4576                           TRUE);
4577
4578         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4579                       AFS_TRACE_LEVEL_VERBOSE_2,
4580                       "AFSBuildMountPointTarget Locating volume for target %I64X\n",
4581                       ullIndex));
4582
4583         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4584                                        ullIndex,
4585                                        (AFSBTreeEntry **)&pVolumeCB);
4586
4587         //
4588         // We can be processing a request for a target that is on a volume
4589         // we have never seen before.
4590         //
4591
4592         if( pVolumeCB == NULL)
4593         {
4594
4595             //
4596             // Locking is held correctly in init routine
4597             //
4598
4599             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4600
4601             //
4602             // Go init the root of the volume
4603             //
4604
4605             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4606                           AFS_TRACE_LEVEL_VERBOSE_2,
4607                           "AFSBuildMountPointTarget Initializing root for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4608                           &DirectoryCB->NameInformation.FileName,
4609                           DirectoryCB->ObjectInformation->FileId.Cell,
4610                           DirectoryCB->ObjectInformation->FileId.Volume,
4611                           DirectoryCB->ObjectInformation->FileId.Vnode,
4612                           DirectoryCB->ObjectInformation->FileId.Unique));
4613
4614             ntStatus = AFSInitVolume( AuthGroup,
4615                                       &stTargetFileID,
4616                                       AFS_VOLUME_REFERENCE_MOUNTPT,
4617                                       &pVolumeCB);
4618
4619             if( !NT_SUCCESS( ntStatus))
4620             {
4621
4622                 try_return( ntStatus);
4623             }
4624
4625             //
4626             // pVolumeCB->VolumeLock held exclusive and
4627             // pVolumeCB->VolumeReferenceCount has been incremented
4628             // pVolumeCB->RootFcb == NULL
4629             //
4630
4631             bReleaseVolumeLock = TRUE;
4632         }
4633         else
4634         {
4635
4636             //
4637             // AFSInitVolume returns with a VolumeReferenceCount
4638             // obtain one to match
4639             //
4640
4641             lCount = AFSVolumeIncrement( pVolumeCB,
4642                                          AFS_VOLUME_REFERENCE_MOUNTPT);
4643
4644             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4645                           AFS_TRACE_LEVEL_VERBOSE,
4646                           "AFSBuildMountPointTarget Increment count on volume %p Cnt %d\n",
4647                           pVolumeCB,
4648                           lCount));
4649
4650             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4651         }
4652
4653         if( pVolumeCB->RootFcb == NULL)
4654         {
4655
4656             if ( bReleaseVolumeLock == FALSE)
4657             {
4658
4659                 AFSAcquireExcl( pVolumeCB->VolumeLock,
4660                                 TRUE);
4661
4662                 bReleaseVolumeLock = TRUE;
4663             }
4664
4665             //
4666             // Initialize the root fcb for this volume
4667             //
4668
4669             ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4670                                        pVolumeCB);
4671
4672             if( !NT_SUCCESS( ntStatus))
4673             {
4674
4675                 lCount = AFSVolumeDecrement( pVolumeCB,
4676                                              AFS_VOLUME_REFERENCE_MOUNTPT);
4677
4678                 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4679                               AFS_TRACE_LEVEL_VERBOSE,
4680                               "AFSBuildMountPoint Decrement count on volume %p Cnt %d\n",
4681                               pVolumeCB,
4682                               lCount));
4683
4684                 AFSReleaseResource( pVolumeCB->VolumeLock);
4685
4686                 try_return( ntStatus);
4687             }
4688
4689             //
4690             // Drop the lock acquired above
4691             //
4692
4693             AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4694         }
4695
4696         if ( bReleaseVolumeLock == TRUE)
4697         {
4698
4699             AFSReleaseResource( pVolumeCB->VolumeLock);
4700         }
4701
4702         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4703                       AFS_TRACE_LEVEL_VERBOSE_2,
4704                       "AFSBuildMountPointTarget Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4705                       &pVolumeCB->DirectoryCB->NameInformation.FileName,
4706                       pVolumeCB->ObjectInformation.FileId.Cell,
4707                       pVolumeCB->ObjectInformation.FileId.Volume,
4708                       pVolumeCB->ObjectInformation.FileId.Vnode,
4709                       pVolumeCB->ObjectInformation.FileId.Unique));
4710
4711         *TargetVolumeCB = pVolumeCB;
4712
4713 try_exit:
4714
4715         if( pDirEntry)
4716         {
4717
4718             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
4719         }
4720     }
4721
4722     return ntStatus;
4723 }
4724
4725 NTSTATUS
4726 AFSBuildRootVolume( IN GUID *AuthGroup,
4727                     IN AFSFileID *FileId,
4728                     OUT AFSVolumeCB **TargetVolumeCB)
4729 {
4730
4731     NTSTATUS ntStatus = STATUS_SUCCESS;
4732     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4733     ULONGLONG       ullIndex = 0;
4734     AFSVolumeCB *pVolumeCB = NULL;
4735     LONG lCount;
4736     BOOLEAN bReleaseVolumeLock = FALSE;
4737
4738     __Enter
4739     {
4740
4741         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4742                       AFS_TRACE_LEVEL_VERBOSE_2,
4743                       "AFSBuildRootVolume Building target volume for FID %08lX-%08lX-%08lX-%08lX\n",
4744                       FileId->Cell,
4745                       FileId->Volume,
4746                       FileId->Vnode,
4747                       FileId->Unique));
4748
4749         ullIndex = AFSCreateHighIndex( FileId);
4750
4751         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4752                       AFS_TRACE_LEVEL_VERBOSE,
4753                       "AFSBuildRootVolume Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4754                       &pDevExt->Specific.RDR.VolumeTreeLock,
4755                       PsGetCurrentThread()));
4756
4757         AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4758                           TRUE);
4759
4760         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4761                       AFS_TRACE_LEVEL_VERBOSE_2,
4762                       "AFSBuildRootVolume Locating volume for target %I64X\n",
4763                       ullIndex));
4764
4765         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4766                                        ullIndex,
4767                                        (AFSBTreeEntry **)&pVolumeCB);
4768
4769         //
4770         // We can be processing a request for a target that is on a volume
4771         // we have never seen before.
4772         //
4773
4774         if( pVolumeCB == NULL)
4775         {
4776
4777             //
4778             // Locking is held correctly in init routine
4779             //
4780
4781             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4782
4783             //
4784             // Go init the root of the volume
4785             //
4786
4787             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4788                          AFS_TRACE_LEVEL_VERBOSE_2,
4789                           "AFSBuildRootVolume Initializing root for FID %08lX-%08lX-%08lX-%08lX\n",
4790                           FileId->Cell,
4791                           FileId->Volume,
4792                           FileId->Vnode,
4793                           FileId->Unique));
4794
4795             ntStatus = AFSInitVolume( AuthGroup,
4796                                       FileId,
4797                                       AFS_VOLUME_REFERENCE_BUILD_ROOT,
4798                                       &pVolumeCB);
4799
4800             if( !NT_SUCCESS( ntStatus))
4801             {
4802
4803                 try_return( ntStatus);
4804             }
4805
4806             //
4807             // pVolumeCB->VolumeLock is held exclusive
4808             // pVolumeCB->VolumeReferenceCount has been incremented
4809             // pVolumeCB->RootFcb == NULL
4810             //
4811
4812             bReleaseVolumeLock = TRUE;
4813         }
4814         else
4815         {
4816
4817             //
4818             // AFSInitVolume returns with a VolumeReferenceCount
4819             // obtain one to match
4820             //
4821
4822             lCount = AFSVolumeIncrement( pVolumeCB,
4823                                          AFS_VOLUME_REFERENCE_BUILD_ROOT);
4824
4825             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4826                           AFS_TRACE_LEVEL_VERBOSE,
4827                           "AFSBuildRootVolume Increment count on volume %p Cnt %d\n",
4828                           pVolumeCB,
4829                           lCount));
4830
4831             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4832         }
4833
4834
4835         if( pVolumeCB->RootFcb == NULL)
4836         {
4837
4838             if ( bReleaseVolumeLock == FALSE)
4839             {
4840
4841                 AFSAcquireExcl( pVolumeCB->VolumeLock,
4842                                 TRUE);
4843
4844                 bReleaseVolumeLock = TRUE;
4845             }
4846
4847             //
4848             // Initialize the root fcb for this volume
4849             //
4850
4851             ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4852                                        pVolumeCB);
4853
4854             if( !NT_SUCCESS( ntStatus))
4855             {
4856
4857                 lCount = AFSVolumeDecrement( pVolumeCB,
4858                                              AFS_VOLUME_REFERENCE_BUILD_ROOT);
4859
4860                 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4861                               AFS_TRACE_LEVEL_VERBOSE,
4862                               "AFSBuildRootVolume Decrement count on volume %p Cnt %d\n",
4863                               pVolumeCB,
4864                               lCount));
4865
4866                 AFSReleaseResource( pVolumeCB->VolumeLock);
4867
4868                 try_return( ntStatus);
4869             }
4870
4871             //
4872             // Drop the lock acquired above
4873             //
4874
4875             AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4876         }
4877
4878         if ( bReleaseVolumeLock == TRUE)
4879         {
4880
4881             AFSReleaseResource( pVolumeCB->VolumeLock);
4882         }
4883
4884         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4885                       AFS_TRACE_LEVEL_VERBOSE_2,
4886                       "AFSBuildRootVolume Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4887                       &pVolumeCB->DirectoryCB->NameInformation.FileName,
4888                       pVolumeCB->ObjectInformation.FileId.Cell,
4889                       pVolumeCB->ObjectInformation.FileId.Volume,
4890                       pVolumeCB->ObjectInformation.FileId.Vnode,
4891                       pVolumeCB->ObjectInformation.FileId.Unique));
4892
4893         *TargetVolumeCB = pVolumeCB;
4894
4895 try_exit:
4896
4897         NOTHING;
4898     }
4899
4900     return ntStatus;
4901 }
4902
4903 NTSTATUS
4904 AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
4905                    IN PFILE_OBJECT FileObject,
4906                    IN UNICODE_STRING *RemainingPath,
4907                    IN GUID *AuthGroup)
4908 {
4909
4910     NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
4911     UNICODE_STRING uniReparseName;
4912     UNICODE_STRING uniMUPDeviceName;
4913     UNICODE_STRING uniIOMgrDeviceName;
4914     AFSDirEnumEntry *pDirEntry = NULL;
4915
4916     __Enter
4917     {
4918
4919         //
4920         // Build up the name to reparse
4921         //
4922
4923         RtlInitUnicodeString( &uniMUPDeviceName,
4924                               L"\\Device\\MUP");
4925
4926         RtlInitUnicodeString( &uniIOMgrDeviceName,
4927                               L"\\??\\");
4928
4929         uniReparseName.Length = 0;
4930         uniReparseName.Buffer = NULL;
4931
4932         //
4933         // Be sure we have a target name
4934         //
4935
4936         if( DirEntry->NameInformation.TargetName.Length == 0)
4937         {
4938
4939             ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
4940                                               AuthGroup,
4941                                               FALSE,
4942                                               &pDirEntry);
4943
4944             if( !NT_SUCCESS( ntStatus) ||
4945                 pDirEntry->TargetNameLength == 0)
4946             {
4947
4948                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4949                               AFS_TRACE_LEVEL_ERROR,
4950                               "AFSProcessDFSLink EvaluateTargetByID failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4951                               &DirEntry->NameInformation.FileName,
4952                               DirEntry->ObjectInformation->FileId.Cell,
4953                               DirEntry->ObjectInformation->FileId.Volume,
4954                               DirEntry->ObjectInformation->FileId.Vnode,
4955                               DirEntry->ObjectInformation->FileId.Unique,
4956                               ntStatus));
4957
4958                 if( NT_SUCCESS( ntStatus))
4959                 {
4960
4961                     ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
4962                 }
4963
4964                 try_return( ntStatus);
4965             }
4966
4967             //
4968             // Update the target name
4969             //
4970
4971             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
4972                             TRUE);
4973
4974             ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
4975                                             &DirEntry->Flags,
4976                                             (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4977                                             (USHORT)pDirEntry->TargetNameLength);
4978
4979             if( !NT_SUCCESS( ntStatus))
4980             {
4981
4982                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4983                               AFS_TRACE_LEVEL_ERROR,
4984                               "AFSProcessDFSLink UpdateTargetName failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4985                               &DirEntry->NameInformation.FileName,
4986                               DirEntry->ObjectInformation->FileId.Cell,
4987                               DirEntry->ObjectInformation->FileId.Volume,
4988                               DirEntry->ObjectInformation->FileId.Vnode,
4989                               DirEntry->ObjectInformation->FileId.Unique,
4990                               ntStatus));
4991
4992                 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4993
4994                 try_return( ntStatus);
4995             }
4996
4997             AFSConvertToShared( &DirEntry->NonPaged->Lock);
4998         }
4999         else
5000         {
5001             AFSAcquireShared( &DirEntry->NonPaged->Lock,
5002                               TRUE);
5003         }
5004
5005         uniReparseName.MaximumLength = uniMUPDeviceName.Length +
5006                                                    sizeof( WCHAR) +
5007                                                    DirEntry->NameInformation.TargetName.Length +
5008                                                    sizeof( WCHAR);
5009
5010         if( RemainingPath != NULL &&
5011             RemainingPath->Length > 0)
5012         {
5013
5014             uniReparseName.MaximumLength += RemainingPath->Length;
5015         }
5016
5017         //
5018         // Allocate the reparse buffer
5019         //
5020
5021         uniReparseName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5022                                                                    uniReparseName.MaximumLength,
5023                                                                    AFS_REPARSE_NAME_TAG);
5024
5025         if( uniReparseName.Buffer == NULL)
5026         {
5027
5028             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5029                           AFS_TRACE_LEVEL_ERROR,
5030                           "AFSProcessDFSLink uniReparseName.Buffer == NULL Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
5031                           &DirEntry->NameInformation.FileName,
5032                           DirEntry->ObjectInformation->FileId.Cell,
5033                           DirEntry->ObjectInformation->FileId.Volume,
5034                           DirEntry->ObjectInformation->FileId.Vnode,
5035                           DirEntry->ObjectInformation->FileId.Unique,
5036                           STATUS_INSUFFICIENT_RESOURCES));
5037
5038             AFSReleaseResource( &DirEntry->NonPaged->Lock);
5039
5040             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5041         }
5042
5043         //
5044         // Start building the name
5045         //
5046
5047         if ( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\' &&
5048              DirEntry->NameInformation.TargetName.Buffer[ 1] == L':')
5049         {
5050
5051             RtlCopyMemory( uniReparseName.Buffer,
5052                            uniIOMgrDeviceName.Buffer,
5053                            uniIOMgrDeviceName.Length);
5054
5055             uniReparseName.Length = uniIOMgrDeviceName.Length;
5056         }
5057         else
5058         {
5059
5060             RtlCopyMemory( uniReparseName.Buffer,
5061                            uniMUPDeviceName.Buffer,
5062                            uniMUPDeviceName.Length);
5063
5064             uniReparseName.Length = uniMUPDeviceName.Length;
5065
5066             if( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\')
5067             {
5068
5069                 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
5070
5071                 uniReparseName.Length += sizeof( WCHAR);
5072             }
5073         }
5074
5075         RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
5076                        DirEntry->NameInformation.TargetName.Buffer,
5077                        DirEntry->NameInformation.TargetName.Length);
5078
5079         uniReparseName.Length += DirEntry->NameInformation.TargetName.Length;
5080
5081         AFSReleaseResource( &DirEntry->NonPaged->Lock);
5082
5083         if( RemainingPath != NULL &&
5084             RemainingPath->Length > 0)
5085         {
5086
5087             if( uniReparseName.Buffer[ (uniReparseName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
5088                 RemainingPath->Buffer[ 0] != L'\\')
5089             {
5090
5091                 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
5092
5093                 uniReparseName.Length += sizeof( WCHAR);
5094             }
5095
5096             RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
5097                            RemainingPath->Buffer,
5098                            RemainingPath->Length);
5099
5100             uniReparseName.Length += RemainingPath->Length;
5101         }
5102
5103         //
5104         // Update the name in the file object
5105         //
5106
5107         if( FileObject->FileName.Buffer != NULL)
5108         {
5109
5110             AFSExFreePoolWithTag( FileObject->FileName.Buffer, 0);
5111         }
5112
5113         FileObject->FileName = uniReparseName;
5114
5115         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5116                       AFS_TRACE_LEVEL_VERBOSE,
5117                       "AFSProcessDFSLink Reparsing access to Fcb %wZ FID %08lX-%08lX-%08lX-%08lX to %wZ\n",
5118                       &DirEntry->NameInformation.FileName,
5119                       DirEntry->ObjectInformation->FileId.Cell,
5120                       DirEntry->ObjectInformation->FileId.Volume,
5121                       DirEntry->ObjectInformation->FileId.Vnode,
5122                       DirEntry->ObjectInformation->FileId.Unique,
5123                       &uniReparseName));
5124
5125         //
5126         // Return status reparse ...
5127         //
5128
5129         ntStatus = STATUS_REPARSE;
5130
5131 try_exit:
5132
5133         if ( pDirEntry)
5134         {
5135
5136             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
5137         }
5138     }
5139
5140     return ntStatus;
5141 }