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