4642a8f8555d4a1b054ecf1b9daaa7a76d86f672
[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 ( !BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
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->ParentFileId.Cell,
297                                           pCurrentObject->ParentFileId.Volume,
298                                           pCurrentObject->ParentFileId.Vnode,
299                                           pCurrentObject->ParentFileId.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                 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1704                 {
1705
1706                     pParentObjectInfo = AFSFindObjectInfo( pCurrentObject->VolumeCB,
1707                                                            &pCurrentObject->ParentFileId);
1708                 }
1709
1710                 ASSERT( pParentObjectInfo != NULL);
1711
1712                 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
1713                                 TRUE);
1714
1715                 AFSAcquireExcl( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock,
1716                                 TRUE);
1717
1718                 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
1719
1720                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1721                               AFS_TRACE_LEVEL_VERBOSE,
1722                               "AFSLocateNameEntry Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1723                               &pDirEntry->NameInformation.FileName,
1724                               pDirEntry,
1725                               NULL,
1726                               lCount);
1727
1728                 ASSERT( lCount >= 0);
1729
1730                 if( lCount <= 0)
1731                 {
1732
1733                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING|AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1734                                   AFS_TRACE_LEVEL_VERBOSE,
1735                                   "AFSLocateNameEntry Deleting dir entry %p (%p) for %wZ\n",
1736                                   pDirEntry,
1737                                   pCurrentObject,
1738                                   &pDirEntry->NameInformation.FileName);
1739
1740                     //
1741                     // Remove and delete the directory entry from the parent list
1742                     //
1743
1744                     AFSDeleteDirEntry( pParentObjectInfo,
1745                                        pDirEntry);
1746
1747                     AFSAcquireShared( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1748                                       TRUE);
1749
1750                     if( pCurrentObject->ObjectReferenceCount <= 0)
1751                     {
1752
1753                         if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
1754                         {
1755
1756                             AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1757                                           AFS_TRACE_LEVEL_VERBOSE,
1758                                           "AFSLocateNameEntry Removing object %p from volume tree\n",
1759                                           pCurrentObject);
1760
1761                             AFSRemoveHashEntry( &pCurrentObject->VolumeCB->ObjectInfoTree.TreeHead,
1762                                                 &pCurrentObject->TreeEntry);
1763
1764                             ClearFlag( pCurrentObject->Flags, AFS_OBJECT_INSERTED_HASH_TREE);
1765                         }
1766                     }
1767
1768                     AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1769                 }
1770                 else
1771                 {
1772
1773                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1774                                   AFS_TRACE_LEVEL_VERBOSE,
1775                                   "AFSLocateNameEntry Setting DELETE flag in dir entry %p for %wZ\n",
1776                                   pDirEntry,
1777                                   &pDirEntry->NameInformation.FileName);
1778
1779                     SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
1780
1781                     AFSRemoveNameEntry( pParentObjectInfo,
1782                                         pDirEntry);
1783                 }
1784
1785                 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
1786
1787                 AFSReleaseResource( pCurrentObject->VolumeCB->ObjectInfoTree.TreeLock);
1788
1789                 AFSReleaseObjectInfo( &pParentObjectInfo);
1790
1791                 //
1792                 // We deleted the dir entry so check if there is any remaining portion
1793                 // of the name to process.
1794                 //
1795
1796                 if( uniRemainingPath.Length > 0)
1797                 {
1798
1799                     ntStatus = STATUS_OBJECT_PATH_NOT_FOUND;
1800
1801                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1802                                   AFS_TRACE_LEVEL_VERBOSE,
1803                                   "AFSLocateNameEntry (FO: %p) Returning path not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1804                                   FileObject,
1805                                   &uniComponentName,
1806                                   pCurrentObject->FileId.Cell,
1807                                   pCurrentObject->FileId.Volume,
1808                                   pCurrentObject->FileId.Vnode,
1809                                   pCurrentObject->FileId.Unique);
1810                 }
1811                 else
1812                 {
1813
1814                     ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1815
1816                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1817                                   AFS_TRACE_LEVEL_VERBOSE,
1818                                   "AFSLocateNameEntry (FO: %p) Returning name not found(2) for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1819                                   FileObject,
1820                                   &uniComponentName,
1821                                   pCurrentObject->FileId.Cell,
1822                                   pCurrentObject->FileId.Volume,
1823                                   pCurrentObject->FileId.Vnode,
1824                                   pCurrentObject->FileId.Unique);
1825
1826                     //
1827                     // Pass back the directory entries
1828                     //
1829
1830                     *ParentDirectoryCB = pParentDirEntry;
1831
1832                     *DirectoryCB = NULL;
1833
1834                     *VolumeCB = pCurrentVolume;
1835
1836                     if( ComponentName != NULL)
1837                     {
1838
1839                         *ComponentName = uniComponentName;
1840                     }
1841
1842                     *RootPathName = uniFullPathName;
1843                 }
1844             }
1845
1846             if( ntStatus != STATUS_SUCCESS)
1847             {
1848
1849                 try_return( ntStatus);
1850             }
1851
1852             //
1853             // Decrement the previous parent
1854             //
1855
1856             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
1857
1858             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1859                           AFS_TRACE_LEVEL_VERBOSE,
1860                           "AFSLocateNameEntry Decrement5 count on Parent %wZ DE %p Ccb %p Cnt %d\n",
1861                           &pParentDirEntry->NameInformation.FileName,
1862                           pParentDirEntry,
1863                           NULL,
1864                           lCount);
1865
1866             ASSERT( lCount >= 0);
1867
1868             //
1869             // If we ended up substituting a name in the component then update
1870             // the full path and update the pointers
1871             //
1872
1873             if( bSubstituteName)
1874             {
1875
1876                 BOOLEAN bRelativeOpen = FALSE;
1877
1878                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1879                               AFS_TRACE_LEVEL_VERBOSE_2,
1880                               "AFSLocateNameEntry (FO: %p) Substituting %wZ into %wZ Index %08lX\n",
1881                               FileObject,
1882                               &uniSearchName,
1883                               &uniComponentName,
1884                               ulSubstituteIndex);
1885
1886                 if( FileObject != NULL &&
1887                     FileObject->RelatedFileObject != NULL)
1888                 {
1889
1890                     bRelativeOpen = TRUE;
1891                 }
1892
1893                 //
1894                 // AFSSubstituteNameInPath will replace the uniFullPathName.Buffer
1895                 // and free the prior Buffer contents but only if the fourth
1896                 // parameter is TRUE.
1897                 //
1898
1899                 ntStatus = AFSSubstituteNameInPath( &uniFullPathName,
1900                                                     &uniComponentName,
1901                                                     &uniSearchName,
1902                                                     &uniRemainingPath,
1903                                                     bRelativeOpen ||
1904                                                             bAllocatedSymLinkBuffer ||
1905                                                             bSubstitutedName);
1906
1907                 if( !NT_SUCCESS( ntStatus))
1908                 {
1909
1910                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1911                                   AFS_TRACE_LEVEL_ERROR,
1912                                   "AFSLocateNameEntry (FO: %p) Failure to substitute %wZ into %wZ Index %08lX Status %08lX\n",
1913                                   FileObject,
1914                                   &uniSearchName,
1915                                   &uniComponentName,
1916                                   ulSubstituteIndex,
1917                                   ntStatus);
1918
1919                     try_return( ntStatus);
1920                 }
1921
1922                 //
1923                 // We have substituted a name into the buffer so if we do this again for this
1924                 // path, we need to free up the buffer we allocated.
1925                 //
1926
1927                 bSubstitutedName = TRUE;
1928             }
1929
1930             //
1931             // Update the search parameters
1932             //
1933
1934             uniPathName = uniRemainingPath;
1935
1936             //
1937             // Check if the is a SymLink entry but has no Target FileID or Name. In this
1938             // case it might be a DFS Link so let's go and evaluate it to be sure
1939             //
1940
1941             if( pCurrentObject->FileType == AFS_FILE_TYPE_SYMLINK &&
1942                 ( pCurrentObject->TargetFileId.Vnode == 0 ||
1943                   pDirEntry->NameInformation.TargetName.Length == 0))
1944             {
1945
1946                 ntStatus = AFSValidateSymLink( AuthGroup,
1947                                                pDirEntry);
1948
1949                 if( !NT_SUCCESS( ntStatus))
1950                 {
1951
1952                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1953                                   AFS_TRACE_LEVEL_ERROR,
1954                                   "AFSLocateNameEntry (FO: %p) Failed to evaluate possible DFS Link %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1955                                   FileObject,
1956                                   &pDirEntry->NameInformation.FileName,
1957                                   pCurrentObject->FileId.Cell,
1958                                   pCurrentObject->FileId.Volume,
1959                                   pCurrentObject->FileId.Vnode,
1960                                   pCurrentObject->FileId.Unique,
1961                                   ntStatus);
1962
1963                     try_return( ntStatus);
1964                 }
1965             }
1966
1967             //
1968             // Update the name array
1969             //
1970
1971             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1972                           AFS_TRACE_LEVEL_VERBOSE,
1973                           "AFSLocateNameEntry (FO: %p) Inserting name array entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
1974                           FileObject,
1975                           &pDirEntry->NameInformation.FileName,
1976                           pCurrentObject->FileId.Cell,
1977                           pCurrentObject->FileId.Volume,
1978                           pCurrentObject->FileId.Vnode,
1979                           pCurrentObject->FileId.Unique);
1980
1981             ntStatus = AFSInsertNextElement( pNameArray,
1982                                              pDirEntry);
1983
1984             if( !NT_SUCCESS( ntStatus))
1985             {
1986
1987                 try_return( ntStatus);
1988             }
1989         }       // while (TRUE)
1990
1991 try_exit:
1992
1993         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1994                       AFS_TRACE_LEVEL_VERBOSE,
1995                       "AFSLocateNameEntry (FO: %p) Completed processing %wZ Status %08lX\n",
1996                       FileObject,
1997                       RootPathName,
1998                       ntStatus);
1999
2000         if( ( !NT_SUCCESS( ntStatus) &&
2001               ntStatus != STATUS_OBJECT_NAME_NOT_FOUND) ||
2002             ntStatus == STATUS_REPARSE)
2003         {
2004
2005             if( pDirEntry != NULL)
2006             {
2007
2008                 lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
2009
2010                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2011                               AFS_TRACE_LEVEL_VERBOSE,
2012                               "AFSLocateNameEntry Decrement6 count on %wZ DE %p Ccb %p Cnt %d\n",
2013                               &pDirEntry->NameInformation.FileName,
2014                               pDirEntry,
2015                               NULL,
2016                               lCount);
2017
2018                 ASSERT( lCount >= 0);
2019             }
2020             else if( pParentDirEntry != NULL)
2021             {
2022
2023                 lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
2024
2025                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2026                               AFS_TRACE_LEVEL_VERBOSE,
2027                               "AFSLocateNameEntry Decrement7 count on %wZ DE %p Ccb %p Cnt %d\n",
2028                               &pParentDirEntry->NameInformation.FileName,
2029                               pParentDirEntry,
2030                               NULL,
2031                               lCount);
2032
2033                 ASSERT( lCount >= 0);
2034             }
2035
2036             if( bReleaseCurrentVolume)
2037             {
2038
2039                 ASSERT( pCurrentVolume->VolumeReferenceCount > 1);
2040
2041                 lCount = InterlockedDecrement( &pCurrentVolume->VolumeReferenceCount);
2042
2043                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2044                               AFS_TRACE_LEVEL_VERBOSE,
2045                               "AFSLocateNameEntry Decrement3 count on volume %p Cnt %d\n",
2046                               pCurrentVolume,
2047                               lCount);
2048             }
2049
2050             if( RootPathName->Buffer != uniFullPathName.Buffer)
2051             {
2052
2053                 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
2054             }
2055         }
2056         else
2057         {
2058
2059             if( *ParentDirectoryCB != NULL)
2060             {
2061
2062                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2063                               AFS_TRACE_LEVEL_VERBOSE,
2064                               "AFSLocateNameEntry Count on Parent %wZ DE %p Ccb %p Cnt %d\n",
2065                               &(*ParentDirectoryCB)->NameInformation.FileName,
2066                               *ParentDirectoryCB,
2067                               NULL,
2068                               (*ParentDirectoryCB)->DirOpenReferenceCount);
2069             }
2070
2071             if( *DirectoryCB != NULL)
2072             {
2073
2074                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2075                               AFS_TRACE_LEVEL_VERBOSE,
2076                               "AFSLocateNameEntry Count on %wZ DE %p Ccb %p Cnt %d\n",
2077                               &(*DirectoryCB)->NameInformation.FileName,
2078                               *DirectoryCB,
2079                               NULL,
2080                               (*DirectoryCB)->DirOpenReferenceCount);
2081             }
2082         }
2083
2084         if( bSubstituteName &&
2085             uniSearchName.Buffer != NULL)
2086         {
2087
2088             AFSExFreePoolWithTag( uniSearchName.Buffer, 0);
2089         }
2090     }
2091
2092     return ntStatus;
2093 }
2094
2095 NTSTATUS
2096 AFSCreateDirEntry( IN GUID            *AuthGroup,
2097                    IN AFSObjectInfoCB *ParentObjectInfo,
2098                    IN AFSDirectoryCB *ParentDirCB,
2099                    IN PUNICODE_STRING FileName,
2100                    IN PUNICODE_STRING ComponentName,
2101                    IN ULONG Attributes,
2102                    IN OUT AFSDirectoryCB **DirEntry)
2103 {
2104
2105     UNREFERENCED_PARAMETER(FileName);
2106     NTSTATUS ntStatus = STATUS_SUCCESS;
2107     AFSDirectoryCB *pDirNode = NULL, *pExistingDirNode = NULL;
2108     LARGE_INTEGER liFileSize = {0,0};
2109     LONG lCount;
2110
2111     __Enter
2112     {
2113
2114         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2115                       AFS_TRACE_LEVEL_VERBOSE_2,
2116                       "AFSCreateDirEntry Creating dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX\n",
2117                       &ParentDirCB->NameInformation.FileName,
2118                       ParentObjectInfo->FileId.Cell,
2119                       ParentObjectInfo->FileId.Volume,
2120                       ParentObjectInfo->FileId.Vnode,
2121                       ParentObjectInfo->FileId.Unique,
2122                       ComponentName,
2123                       Attributes);
2124
2125         //
2126         // OK, before inserting the node into the parent tree, issue
2127         // the request to the service for node creation
2128         // We will need to drop the lock on the parent node since the create
2129         // could cause a callback into the file system to invalidate it's cache
2130         //
2131
2132         ntStatus = AFSNotifyFileCreate( AuthGroup,
2133                                         ParentObjectInfo,
2134                                         &liFileSize,
2135                                         Attributes,
2136                                         ComponentName,
2137                                         &pDirNode);
2138
2139         //
2140         // If the returned status is STATUS_REPARSE then the entry exists
2141         // and we raced, get out.
2142
2143         if( ntStatus == STATUS_REPARSE)
2144         {
2145
2146             *DirEntry = pDirNode;
2147
2148             try_return( ntStatus = STATUS_SUCCESS);
2149         }
2150
2151         if( !NT_SUCCESS( ntStatus))
2152         {
2153
2154             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2155                           AFS_TRACE_LEVEL_ERROR,
2156                           "AFSCreateDirEntry Failed to create dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ Attribs %08lX Status %08lX\n",
2157                           &ParentDirCB->NameInformation.FileName,
2158                           ParentObjectInfo->FileId.Cell,
2159                           ParentObjectInfo->FileId.Volume,
2160                           ParentObjectInfo->FileId.Vnode,
2161                           ParentObjectInfo->FileId.Unique,
2162                           ComponentName,
2163                           Attributes,
2164                           ntStatus);
2165
2166             try_return( ntStatus);
2167         }
2168
2169         //
2170         // If AFSNotifyFileCreate returns pDirNode != NULL, then its
2171         // DirOpenReferenceCount is held.
2172         //
2173
2174         AFSAcquireExcl( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2175                         TRUE);
2176
2177         //
2178         // Before attempting to insert the new entry, check if we need to validate the parent
2179         //
2180
2181         if( BooleanFlagOn( ParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY))
2182         {
2183
2184             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2185                           AFS_TRACE_LEVEL_VERBOSE,
2186                           "AFSCreateDirEntry Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2187                           &ParentDirCB->NameInformation.FileName,
2188                           ParentObjectInfo->FileId.Cell,
2189                           ParentObjectInfo->FileId.Volume,
2190                           ParentObjectInfo->FileId.Vnode,
2191                           ParentObjectInfo->FileId.Unique);
2192
2193             ntStatus = AFSVerifyEntry( AuthGroup,
2194                                        ParentDirCB);
2195
2196             if( !NT_SUCCESS( ntStatus))
2197             {
2198
2199                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2200                               AFS_TRACE_LEVEL_ERROR,
2201                               "AFSCreateDirEntry Failed to verify parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2202                               &ParentDirCB->NameInformation.FileName,
2203                               ParentObjectInfo->FileId.Cell,
2204                               ParentObjectInfo->FileId.Volume,
2205                               ParentObjectInfo->FileId.Vnode,
2206                               ParentObjectInfo->FileId.Unique,
2207                               ntStatus);
2208
2209                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2210
2211                 try_return( ntStatus);
2212             }
2213         }
2214
2215         //
2216         // Check for the entry in the event we raced with some other thread
2217         //
2218
2219         AFSLocateCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2220                                         (ULONG)pDirNode->CaseSensitiveTreeEntry.HashIndex,
2221                                         &pExistingDirNode);
2222
2223         if( pExistingDirNode != NULL)
2224         {
2225             if (AFSIsEqualFID( &pDirNode->ObjectInformation->FileId,
2226                                &pExistingDirNode->ObjectInformation->FileId))
2227             {
2228
2229                 if ( pExistingDirNode != pDirNode)
2230                 {
2231
2232                     lCount = InterlockedDecrement( &pDirNode->DirOpenReferenceCount);
2233
2234                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2235                                   AFS_TRACE_LEVEL_VERBOSE,
2236                                   "AFSCreateDirEntry Decrement count on %wZ DE %p Cnt %d\n",
2237                                   &pDirNode->NameInformation.FileName,
2238                                   pDirNode,
2239                                   lCount);
2240
2241                     AFSDeleteDirEntry( ParentObjectInfo,
2242                                        pDirNode);
2243
2244                     lCount = InterlockedIncrement( &pExistingDirNode->DirOpenReferenceCount);
2245
2246                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2247                                   AFS_TRACE_LEVEL_VERBOSE,
2248                                   "AFSCreateDirEntry Increment count on %wZ DE %p Cnt %d\n",
2249                                   &pExistingDirNode->NameInformation.FileName,
2250                                   pExistingDirNode,
2251                                   lCount);
2252
2253                     *DirEntry = pExistingDirNode;
2254                 }
2255
2256                 AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2257
2258                 try_return( ntStatus = STATUS_SUCCESS);
2259             }
2260             else
2261             {
2262
2263                 //
2264                 // Need to tear down this entry and rebuild it below
2265                 //
2266
2267                 if( pExistingDirNode->DirOpenReferenceCount <= 0)
2268                 {
2269
2270                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2271                                   AFS_TRACE_LEVEL_VERBOSE,
2272                                   "AFSCreateDirEntry Different FIDs - Deleting DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2273                                   pExistingDirNode,
2274                                   &pExistingDirNode->NameInformation.FileName,
2275                                   pExistingDirNode->ObjectInformation->FileId.Cell,
2276                                   pExistingDirNode->ObjectInformation->FileId.Volume,
2277                                   pExistingDirNode->ObjectInformation->FileId.Vnode,
2278                                   pExistingDirNode->ObjectInformation->FileId.Unique,
2279                                   pDirNode->ObjectInformation->FileId.Cell,
2280                                   pDirNode->ObjectInformation->FileId.Volume,
2281                                   pDirNode->ObjectInformation->FileId.Vnode,
2282                                   pDirNode->ObjectInformation->FileId.Unique);
2283
2284                     AFSDeleteDirEntry( ParentObjectInfo,
2285                                        pExistingDirNode);
2286                 }
2287                 else
2288                 {
2289
2290                     SetFlag( pExistingDirNode->Flags, AFS_DIR_ENTRY_DELETED);
2291
2292                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2293                                   AFS_TRACE_LEVEL_VERBOSE,
2294                                   "AFSCreateDirEntry Different FIDs - Removing DE %p for %wZ Old FID %08lX-%08lX-%08lX-%08lX New FID %08lX-%08lX-%08lX-%08lX\n",
2295                                   pExistingDirNode,
2296                                   &pExistingDirNode->NameInformation.FileName,
2297                                   pExistingDirNode->ObjectInformation->FileId.Cell,
2298                                   pExistingDirNode->ObjectInformation->FileId.Volume,
2299                                   pExistingDirNode->ObjectInformation->FileId.Vnode,
2300                                   pExistingDirNode->ObjectInformation->FileId.Unique,
2301                                   pDirNode->ObjectInformation->FileId.Cell,
2302                                   pDirNode->ObjectInformation->FileId.Volume,
2303                                   pDirNode->ObjectInformation->FileId.Vnode,
2304                                   pDirNode->ObjectInformation->FileId.Unique);
2305
2306                     AFSRemoveNameEntry( ParentObjectInfo,
2307                                         pExistingDirNode);
2308                 }
2309             }
2310         }
2311
2312         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2313                       AFS_TRACE_LEVEL_VERBOSE_2,
2314                       "AFSCreateDirEntry Inserting dir entry in parent %wZ FID %08lX-%08lX-%08lX-%08lX Component %wZ\n",
2315                       &ParentDirCB->NameInformation.FileName,
2316                       ParentObjectInfo->FileId.Cell,
2317                       ParentObjectInfo->FileId.Volume,
2318                       ParentObjectInfo->FileId.Vnode,
2319                       ParentObjectInfo->FileId.Unique,
2320                       ComponentName);
2321
2322         //
2323         // Insert the directory node
2324         //
2325
2326         AFSInsertDirectoryNode( ParentObjectInfo,
2327                                 pDirNode,
2328                                 TRUE);
2329
2330         //
2331         // Pass back the dir entry
2332         //
2333
2334         *DirEntry = pDirNode;
2335
2336         AFSReleaseResource( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2337
2338 try_exit:
2339
2340         NOTHING;
2341     }
2342
2343     return ntStatus;
2344 }
2345
2346 void
2347 AFSInsertDirectoryNode( IN AFSObjectInfoCB *ParentObjectInfo,
2348                         IN AFSDirectoryCB *DirEntry,
2349                         IN BOOLEAN InsertInEnumList)
2350 {
2351
2352     LONG lCount;
2353
2354     __Enter
2355     {
2356
2357         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2358
2359         //
2360         // Insert the node into the directory node tree
2361         //
2362
2363         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2364                       AFS_TRACE_LEVEL_VERBOSE,
2365                       "AFSInsertDirectoryNode Insert DE %p for %wZ Clearing NOT_IN flag\n",
2366                       DirEntry,
2367                       &DirEntry->NameInformation.FileName);
2368
2369         ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
2370
2371         if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead == NULL)
2372         {
2373
2374             ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = DirEntry;
2375
2376             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2377                           AFS_TRACE_LEVEL_VERBOSE,
2378                           "AFSInsertDirectoryNode Insert DE %p to head of case sensitive tree for %wZ\n",
2379                           DirEntry,
2380                           &DirEntry->NameInformation.FileName);
2381         }
2382         else
2383         {
2384
2385             AFSInsertCaseSensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
2386                                             DirEntry);
2387
2388             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2389                           AFS_TRACE_LEVEL_VERBOSE,
2390                           "AFSInsertDirectoryNode Insert DE %p to case sensitive tree for %wZ\n",
2391                           DirEntry,
2392                           &DirEntry->NameInformation.FileName);
2393         }
2394
2395         if( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead == NULL)
2396         {
2397
2398             ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = DirEntry;
2399
2400             SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
2401
2402             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2403                           AFS_TRACE_LEVEL_VERBOSE,
2404                           "AFSInsertDirectoryNode Insert DE %p to head of case insensitive tree for %wZ\n",
2405                           DirEntry,
2406                           &DirEntry->NameInformation.FileName);
2407         }
2408         else
2409         {
2410
2411             AFSInsertCaseInsensitiveDirEntry( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
2412                                               DirEntry);
2413
2414             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2415                           AFS_TRACE_LEVEL_VERBOSE,
2416                           "AFSInsertDirectoryNode Insert DE %p to case insensitive tree for %wZ\n",
2417                           DirEntry,
2418                           &DirEntry->NameInformation.FileName);
2419         }
2420
2421         //
2422         // Into the shortname tree
2423         //
2424
2425         if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex != 0)
2426         {
2427
2428             if( ParentObjectInfo->Specific.Directory.ShortNameTree == NULL)
2429             {
2430
2431                 ParentObjectInfo->Specific.Directory.ShortNameTree = DirEntry;
2432
2433                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2434                               AFS_TRACE_LEVEL_VERBOSE,
2435                               "AFSInsertDirectoryNode Insert DE %p to head of shortname tree for %wZ\n",
2436                               DirEntry,
2437                               &DirEntry->NameInformation.FileName);
2438
2439                 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2440             }
2441             else
2442             {
2443
2444                 if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ParentObjectInfo->Specific.Directory.ShortNameTree,
2445                                                              DirEntry)))
2446                 {
2447                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2448                                   AFS_TRACE_LEVEL_VERBOSE,
2449                                   "AFSInsertDirectoryNode Failed to insert DE %p to shortname tree for %wZ\n",
2450                                   DirEntry,
2451                                   &DirEntry->NameInformation.FileName);
2452                 }
2453                 else
2454                 {
2455                     SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
2456
2457                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2458                                   AFS_TRACE_LEVEL_VERBOSE,
2459                                   "AFSInsertDirectoryNode Insert DE %p to shortname tree for %wZ\n",
2460                                   DirEntry,
2461                                   &DirEntry->NameInformation.FileName);
2462                 }
2463             }
2464         }
2465
2466         if( InsertInEnumList)
2467         {
2468
2469             //
2470             // And insert the node into the directory list
2471             //
2472
2473             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2474                           AFS_TRACE_LEVEL_VERBOSE,
2475                           "AFSInsertDirectoryNode Inserting entry %p %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2476                           DirEntry,
2477                           &DirEntry->NameInformation.FileName,
2478                           DirEntry->ObjectInformation->FileId.Cell,
2479                           DirEntry->ObjectInformation->FileId.Volume,
2480                           DirEntry->ObjectInformation->FileId.Vnode,
2481                           DirEntry->ObjectInformation->FileId.Unique);
2482
2483             if( ParentObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL)
2484             {
2485
2486                 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = DirEntry;
2487             }
2488             else
2489             {
2490
2491                 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = (void *)DirEntry;
2492
2493                 DirEntry->ListEntry.bLink = (void *)ParentObjectInfo->Specific.Directory.DirectoryNodeListTail;
2494             }
2495
2496             ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = DirEntry;
2497
2498             SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2499
2500             lCount = InterlockedIncrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2501
2502             AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2503                           AFS_TRACE_LEVEL_VERBOSE,
2504                           "AFSInsertDirectoryNode Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2505                           &DirEntry->NameInformation.FileName,
2506                           lCount,
2507                           ParentObjectInfo->FileId.Cell,
2508                           ParentObjectInfo->FileId.Volume,
2509                           ParentObjectInfo->FileId.Vnode,
2510                           ParentObjectInfo->FileId.Unique);
2511         }
2512     }
2513
2514     return;
2515 }
2516
2517 void
2518 AFSDeleteDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
2519                    IN AFSDirectoryCB *DirEntry)
2520 {
2521
2522     LONG lCount;
2523
2524     __Enter
2525     {
2526
2527         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2528                       AFS_TRACE_LEVEL_VERBOSE,
2529                       "AFSDeleteDirEntry Deleting dir entry in parent %p Entry %p %wZ FID %08lX-%08lX-%08lX-%08lX RefCount %d\n",
2530                       ParentObjectInfo,
2531                       DirEntry,
2532                       &DirEntry->NameInformation.FileName,
2533                       DirEntry->ObjectInformation->FileId.Cell,
2534                       DirEntry->ObjectInformation->FileId.Volume,
2535                       DirEntry->ObjectInformation->FileId.Vnode,
2536                       DirEntry->ObjectInformation->FileId.Unique,
2537                       DirEntry->DirOpenReferenceCount);
2538
2539         ASSERT( DirEntry->DirOpenReferenceCount == 0);
2540
2541         AFSRemoveDirNodeFromParent( ParentObjectInfo,
2542                                     DirEntry,
2543                                     TRUE);
2544
2545         //
2546         // Free up the name buffer if it was reallocated
2547         //
2548
2549         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
2550         {
2551
2552             AFSExFreePoolWithTag( DirEntry->NameInformation.FileName.Buffer, 0);
2553         }
2554
2555         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
2556         {
2557
2558             AFSExFreePoolWithTag( DirEntry->NameInformation.TargetName.Buffer, 0);
2559         }
2560
2561         //
2562         // Dereference the object for this dir entry
2563         //
2564
2565         lCount = AFSObjectInfoDecrement( DirEntry->ObjectInformation,
2566                                          AFS_OBJECT_REFERENCE_DIRENTRY);
2567
2568         AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2569                       AFS_TRACE_LEVEL_VERBOSE,
2570                       "AFSDeleteDirEntry Decrement count on object %p Cnt %d\n",
2571                       DirEntry->ObjectInformation,
2572                       lCount);
2573
2574         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
2575             DirEntry->ObjectInformation->Links == 0)
2576         {
2577
2578             SetFlag( DirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED);
2579         }
2580
2581         ExDeleteResourceLite( &DirEntry->NonPaged->Lock);
2582
2583         AFSExFreePoolWithTag( DirEntry->NonPaged, AFS_DIR_ENTRY_NP_TAG);
2584
2585         //
2586         // Free up the dir entry
2587         //
2588
2589         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
2590                       AFS_TRACE_LEVEL_VERBOSE,
2591                       "AFSDeleteDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
2592                       DirEntry);
2593
2594         AFSExFreePoolWithTag( DirEntry, AFS_DIR_ENTRY_TAG);
2595     }
2596 }
2597
2598 NTSTATUS
2599 AFSRemoveDirNodeFromParent( IN AFSObjectInfoCB *ParentObjectInfo,
2600                             IN AFSDirectoryCB *DirEntry,
2601                             IN BOOLEAN RemoveFromEnumList)
2602 {
2603
2604     NTSTATUS ntStatus = STATUS_SUCCESS;
2605     LONG lCount;
2606
2607     __Enter
2608     {
2609
2610
2611         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
2612
2613         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2614                       AFS_TRACE_LEVEL_VERBOSE,
2615                       "AFSRemoveDirNodeFromParent Removing DirEntry %p %wZ FID %08lX-%08lX-%08lX-%08lX from Parent %p\n",
2616                       DirEntry,
2617                       &DirEntry->NameInformation.FileName,
2618                       DirEntry->ObjectInformation->FileId.Cell,
2619                       DirEntry->ObjectInformation->FileId.Volume,
2620                       DirEntry->ObjectInformation->FileId.Vnode,
2621                       DirEntry->ObjectInformation->FileId.Unique,
2622                       ParentObjectInfo);
2623
2624         if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
2625         {
2626
2627             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2628                           AFS_TRACE_LEVEL_VERBOSE,
2629                           "AFSRemoveDirNodeFromParent Removing DirEntry %p name %wZ\n",
2630                           DirEntry,
2631                           &DirEntry->NameInformation.FileName);
2632
2633             AFSRemoveNameEntry( ParentObjectInfo,
2634                                 DirEntry);
2635         }
2636         else
2637         {
2638
2639             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2640                           AFS_TRACE_LEVEL_VERBOSE,
2641                           "AFSRemoveDirNodeFromParent DE %p for %wZ NOT removing entry due to flag set\n",
2642                           DirEntry,
2643                           &DirEntry->NameInformation.FileName);
2644
2645         }
2646
2647         if( RemoveFromEnumList &&
2648             BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST))
2649         {
2650
2651             //
2652             // And remove the entry from the enumeration list
2653             //
2654
2655             if( DirEntry->ListEntry.fLink == NULL)
2656             {
2657
2658                 ParentObjectInfo->Specific.Directory.DirectoryNodeListTail = (AFSDirectoryCB *)DirEntry->ListEntry.bLink;
2659             }
2660             else
2661             {
2662
2663                 ((AFSDirectoryCB *)DirEntry->ListEntry.fLink)->ListEntry.bLink = DirEntry->ListEntry.bLink;
2664             }
2665
2666             if( DirEntry->ListEntry.bLink == NULL)
2667             {
2668
2669                 ParentObjectInfo->Specific.Directory.DirectoryNodeListHead = (AFSDirectoryCB *)DirEntry->ListEntry.fLink;
2670             }
2671             else
2672             {
2673
2674                 ((AFSDirectoryCB *)DirEntry->ListEntry.bLink)->ListEntry.fLink = DirEntry->ListEntry.fLink;
2675             }
2676
2677             ASSERT( ParentObjectInfo->Specific.Directory.DirectoryNodeCount > 0);
2678
2679             lCount = InterlockedDecrement( &ParentObjectInfo->Specific.Directory.DirectoryNodeCount);
2680
2681             ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
2682
2683             AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
2684                           AFS_TRACE_LEVEL_VERBOSE,
2685                           "AFSRemoveDirNodeFromParent Removing entry %wZ Dec Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
2686                           &DirEntry->NameInformation.FileName,
2687                           lCount,
2688                           ParentObjectInfo->FileId.Cell,
2689                           ParentObjectInfo->FileId.Volume,
2690                           ParentObjectInfo->FileId.Vnode,
2691                           ParentObjectInfo->FileId.Unique);
2692
2693             DirEntry->ListEntry.fLink = NULL;
2694             DirEntry->ListEntry.bLink = NULL;
2695         }
2696     }
2697
2698     return ntStatus;
2699 }
2700
2701 NTSTATUS
2702 AFSFixupTargetName( IN OUT PUNICODE_STRING FileName,
2703                     IN OUT PUNICODE_STRING TargetFileName)
2704 {
2705
2706     NTSTATUS ntStatus = STATUS_SUCCESS;
2707     UNICODE_STRING uniFileName;
2708
2709     __Enter
2710     {
2711
2712         //
2713         // We will process backwards from the end of the name looking
2714         // for the first \ we encounter
2715         //
2716
2717         uniFileName.Length = FileName->Length;
2718         uniFileName.MaximumLength = FileName->MaximumLength;
2719
2720         uniFileName.Buffer = FileName->Buffer;
2721
2722         while( TRUE)
2723         {
2724
2725             if( uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
2726             {
2727
2728                 //
2729                 // Subtract one more character off of the filename if it is not the root
2730                 //
2731
2732                 if( uniFileName.Length > sizeof( WCHAR))
2733                 {
2734
2735                     uniFileName.Length -= sizeof( WCHAR);
2736                 }
2737
2738                 //
2739                 // Now build up the target name
2740                 //
2741
2742                 TargetFileName->Length = FileName->Length - uniFileName.Length;
2743
2744                 //
2745                 // If we are not on the root then fixup the name
2746                 //
2747
2748                 if( uniFileName.Length > sizeof( WCHAR))
2749                 {
2750
2751                     TargetFileName->Length -= sizeof( WCHAR);
2752
2753                     TargetFileName->Buffer = &uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) + 1];
2754                 }
2755                 else
2756                 {
2757
2758                     TargetFileName->Buffer = &uniFileName.Buffer[ uniFileName.Length/sizeof( WCHAR)];
2759                 }
2760
2761                 //
2762                 // Fixup the passed back filename length
2763                 //
2764
2765                 FileName->Length = uniFileName.Length;
2766
2767                 TargetFileName->MaximumLength = TargetFileName->Length;
2768
2769                 break;
2770             }
2771
2772             uniFileName.Length -= sizeof( WCHAR);
2773         }
2774     }
2775
2776     return ntStatus;
2777 }
2778
2779 NTSTATUS
2780 AFSParseName( IN PIRP Irp,
2781               IN GUID *AuthGroup,
2782               OUT PUNICODE_STRING FileName,
2783               OUT PUNICODE_STRING ParsedFileName,
2784               OUT PUNICODE_STRING RootFileName,
2785               OUT ULONG *ParseFlags,
2786               OUT AFSVolumeCB   **VolumeCB,
2787               OUT AFSDirectoryCB **ParentDirectoryCB,
2788               OUT AFSNameArrayHdr **NameArray)
2789 {
2790
2791     NTSTATUS            ntStatus = STATUS_SUCCESS;
2792     PIO_STACK_LOCATION  pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2793     AFSDeviceExt       *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2794     UNICODE_STRING      uniFullName, uniComponentName, uniRemainingPath;
2795     ULONG               ulCRC = 0;
2796     AFSDirectoryCB     *pDirEntry = NULL;
2797     USHORT              usIndex = 0, usDriveIndex = 0;
2798     AFSCcb             *pRelatedCcb = NULL;
2799     AFSNameArrayHdr    *pNameArray = NULL, *pRelatedNameArray = NULL;
2800     USHORT              usComponentIndex = 0;
2801     USHORT              usComponentLength = 0;
2802     AFSVolumeCB        *pVolumeCB = NULL;
2803     AFSFcb             *pRelatedFcb = NULL;
2804     BOOLEAN             bReleaseTreeLock = FALSE;
2805     BOOLEAN             bIsAllShare = FALSE;
2806     LONG                lCount;
2807
2808     __Enter
2809     {
2810
2811         //
2812         // Indicate we are opening a root ...
2813         //
2814
2815         *ParseFlags = AFS_PARSE_FLAG_ROOT_ACCESS;
2816
2817         *ParentDirectoryCB = NULL;
2818
2819         if( pIrpSp->FileObject->RelatedFileObject != NULL)
2820         {
2821
2822             pRelatedFcb = (AFSFcb *)pIrpSp->FileObject->RelatedFileObject->FsContext;
2823
2824             pRelatedCcb = (AFSCcb *)pIrpSp->FileObject->RelatedFileObject->FsContext2;
2825
2826             pRelatedNameArray = pRelatedCcb->NameArray;
2827
2828             uniFullName = pIrpSp->FileObject->FileName;
2829
2830             ASSERT( pRelatedFcb != NULL);
2831
2832             //
2833             // No wild cards in the name
2834             //
2835
2836             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2837                           AFS_TRACE_LEVEL_VERBOSE_2,
2838                           "AFSParseName (%p) Relative open for %wZ FID %08lX-%08lX-%08lX-%08lX component %wZ\n",
2839                           Irp,
2840                           &pRelatedCcb->DirectoryCB->NameInformation.FileName,
2841                           pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Cell,
2842                           pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Volume,
2843                           pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Vnode,
2844                           pRelatedCcb->DirectoryCB->ObjectInformation->FileId.Unique,
2845                           &uniFullName);
2846
2847             if( FsRtlDoesNameContainWildCards( &uniFullName))
2848             {
2849
2850                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2851                               AFS_TRACE_LEVEL_ERROR,
2852                               "AFSParseName (%p) Component %wZ contains wild cards\n",
2853                               Irp,
2854                               &uniFullName);
2855
2856                 try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
2857             }
2858
2859             pVolumeCB = pRelatedFcb->ObjectInformation->VolumeCB;
2860
2861             pDirEntry = pRelatedCcb->DirectoryCB;
2862
2863             *FileName = pIrpSp->FileObject->FileName;
2864
2865             //
2866             // Grab the root node while checking state
2867             //
2868
2869             AFSAcquireShared( pVolumeCB->VolumeLock,
2870                               TRUE);
2871
2872             if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
2873                 BooleanFlagOn( pVolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE))
2874             {
2875
2876                 //
2877                 // The volume has been taken off line so fail the access
2878                 //
2879
2880                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2881                               AFS_TRACE_LEVEL_ERROR,
2882                               "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
2883                               Irp,
2884                               pVolumeCB->ObjectInformation.FileId.Cell,
2885                               pVolumeCB->ObjectInformation.FileId.Volume);
2886
2887                 AFSReleaseResource( pVolumeCB->VolumeLock);
2888
2889                 try_return( ntStatus = STATUS_DEVICE_NOT_READY);
2890             }
2891
2892             if( BooleanFlagOn( pVolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
2893             {
2894
2895                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2896                               AFS_TRACE_LEVEL_VERBOSE,
2897                               "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
2898                               Irp,
2899                               pVolumeCB->ObjectInformation.FileId.Cell,
2900                               pVolumeCB->ObjectInformation.FileId.Volume);
2901
2902                 ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
2903                                             pVolumeCB);
2904
2905                 if( !NT_SUCCESS( ntStatus))
2906                 {
2907
2908                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2909                                   AFS_TRACE_LEVEL_ERROR,
2910                                   "AFSParseName (%p) Failed verification of root Status %08lX\n",
2911                                   Irp,
2912                                   ntStatus);
2913
2914                     AFSReleaseResource( pVolumeCB->VolumeLock);
2915
2916                     try_return( ntStatus);
2917                 }
2918             }
2919
2920             AFSReleaseResource( pVolumeCB->VolumeLock);
2921
2922             if( BooleanFlagOn( pDirEntry->ObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY))
2923             {
2924
2925                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2926                               AFS_TRACE_LEVEL_VERBOSE,
2927                               "AFSParseName (%p) Verifying parent %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2928                               Irp,
2929                               &pDirEntry->NameInformation.FileName,
2930                               pDirEntry->ObjectInformation->FileId.Cell,
2931                               pDirEntry->ObjectInformation->FileId.Volume,
2932                               pDirEntry->ObjectInformation->FileId.Vnode,
2933                               pDirEntry->ObjectInformation->FileId.Unique);
2934
2935                 //
2936                 // Directory TreeLock should be exclusively held
2937                 //
2938
2939                 AFSAcquireExcl( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
2940                                 TRUE);
2941
2942                 ntStatus = AFSVerifyEntry( AuthGroup,
2943                                            pDirEntry);
2944
2945                 AFSReleaseResource( pDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
2946
2947                 if( !NT_SUCCESS( ntStatus))
2948                 {
2949
2950                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2951                                   AFS_TRACE_LEVEL_VERBOSE,
2952                                   "AFSParseName (%p) Failed verification of parent %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2953                                   Irp,
2954                                   &pDirEntry->NameInformation.FileName,
2955                                   pDirEntry->ObjectInformation->FileId.Cell,
2956                                   pDirEntry->ObjectInformation->FileId.Volume,
2957                                   pDirEntry->ObjectInformation->FileId.Vnode,
2958                                   pDirEntry->ObjectInformation->FileId.Unique,
2959                                   ntStatus);
2960
2961                     try_return( ntStatus);
2962                 }
2963             }
2964
2965             //
2966             // Create our full path name buffer
2967             //
2968
2969             uniFullName.MaximumLength = pRelatedCcb->FullFileName.Length +
2970                                                     sizeof( WCHAR) +
2971                                                     pIrpSp->FileObject->FileName.Length +
2972                                                     sizeof( WCHAR);
2973
2974             uniFullName.Length = 0;
2975
2976             uniFullName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2977                                                                     uniFullName.MaximumLength,
2978                                                                     AFS_NAME_BUFFER_THREE_TAG);
2979
2980             if( uniFullName.Buffer == NULL)
2981             {
2982
2983                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2984                               AFS_TRACE_LEVEL_ERROR,
2985                               "AFSParseName (%p) Failed to allocate full name buffer\n",
2986                               Irp);
2987
2988                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2989             }
2990
2991             RtlZeroMemory( uniFullName.Buffer,
2992                            uniFullName.MaximumLength);
2993
2994             RtlCopyMemory( uniFullName.Buffer,
2995                            pRelatedCcb->FullFileName.Buffer,
2996                            pRelatedCcb->FullFileName.Length);
2997
2998             uniFullName.Length = pRelatedCcb->FullFileName.Length;
2999
3000             usComponentIndex = (USHORT)(uniFullName.Length/sizeof( WCHAR));
3001
3002             usComponentLength = pIrpSp->FileObject->FileName.Length;
3003
3004             if( uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
3005                 pIrpSp->FileObject->FileName.Length > 0 &&
3006                 pIrpSp->FileObject->FileName.Buffer[ 0] != L'\\' &&
3007                 pIrpSp->FileObject->FileName.Buffer[ 0] != L':')
3008             {
3009
3010                 uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR))] = L'\\';
3011
3012                 uniFullName.Length += sizeof( WCHAR);
3013
3014                 usComponentLength += sizeof( WCHAR);
3015             }
3016
3017             if( pIrpSp->FileObject->FileName.Length > 0)
3018             {
3019
3020                 RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
3021                                pIrpSp->FileObject->FileName.Buffer,
3022                                pIrpSp->FileObject->FileName.Length);
3023
3024                 uniFullName.Length += pIrpSp->FileObject->FileName.Length;
3025             }
3026
3027             *RootFileName = uniFullName;
3028
3029             //
3030             // We populate up to the current parent
3031             //
3032
3033             if( pRelatedNameArray == NULL)
3034             {
3035
3036                 //
3037                 // Init and populate our name array
3038                 //
3039
3040                 pNameArray = AFSInitNameArray( NULL,
3041                                                0);
3042
3043                 if( pNameArray == NULL)
3044                 {
3045
3046                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3047                                   AFS_TRACE_LEVEL_VERBOSE,
3048                                   "AFSParseName (%p) Failed to initialize name array\n",
3049                                   Irp);
3050
3051                     AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3052
3053                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3054                 }
3055
3056                 ntStatus = AFSPopulateNameArray( pNameArray,
3057                                                  NULL,
3058                                                  pRelatedCcb->DirectoryCB);
3059             }
3060             else
3061             {
3062
3063                 //
3064                 // Init and populate our name array
3065                 //
3066
3067                 pNameArray = AFSInitNameArray( NULL,
3068                                                pRelatedNameArray->MaxElementCount);
3069
3070                 if( pNameArray == NULL)
3071                 {
3072
3073                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3074                                   AFS_TRACE_LEVEL_VERBOSE,
3075                                   "AFSParseName (%p) Failed to initialize name array\n",
3076                                   Irp);
3077
3078                     AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3079
3080                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3081                 }
3082
3083                 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
3084                                                                  pRelatedNameArray,
3085                                                                  pRelatedCcb->DirectoryCB);
3086             }
3087
3088             if( !NT_SUCCESS( ntStatus))
3089             {
3090
3091                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3092                               AFS_TRACE_LEVEL_VERBOSE,
3093                               "AFSParseName (%p) Failed to populate name array\n",
3094                               Irp);
3095
3096                 AFSExFreePoolWithTag( uniFullName.Buffer, 0);
3097
3098                 try_return( ntStatus);
3099             }
3100
3101             ParsedFileName->Length = usComponentLength;
3102             ParsedFileName->MaximumLength = uniFullName.MaximumLength;
3103
3104             ParsedFileName->Buffer = &uniFullName.Buffer[ usComponentIndex];
3105
3106             //
3107             // Indicate to caller that RootFileName must be freed
3108             //
3109
3110             SetFlag( *ParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
3111
3112             *NameArray = pNameArray;
3113
3114             //
3115             // Increment our volume reference count
3116             //
3117
3118             lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
3119
3120             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3121                           AFS_TRACE_LEVEL_VERBOSE,
3122                           "AFSParseName Increment count on volume %p Cnt %d\n",
3123                           pVolumeCB,
3124                           lCount);
3125
3126             *VolumeCB = pVolumeCB;
3127
3128             *ParentDirectoryCB = pDirEntry;
3129
3130             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3131                           AFS_TRACE_LEVEL_VERBOSE_2,
3132                           "AFSParseName (%p) Returning full name %wZ\n",
3133                           Irp,
3134                           &uniFullName);
3135
3136             try_return( ntStatus);
3137         }
3138
3139         //
3140         // No wild cards in the name
3141         //
3142
3143         uniFullName = pIrpSp->FileObject->FileName;
3144
3145         if( FsRtlDoesNameContainWildCards( &uniFullName) ||
3146             uniFullName.Length < AFSServerName.Length)
3147         {
3148
3149             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3150                           AFS_TRACE_LEVEL_ERROR,
3151                           "AFSParseName (%p) Name %wZ contains wild cards or too short\n",
3152                           Irp,
3153                           &uniFullName);
3154
3155             try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3156         }
3157
3158         //
3159         // The name is a fully qualified name. Parse out the server/share names and
3160         // point to the root qualified name
3161         // First thing is to locate the server name
3162         //
3163
3164         FsRtlDissectName( uniFullName,
3165                           &uniComponentName,
3166                           &uniRemainingPath);
3167
3168         uniFullName = uniRemainingPath;
3169
3170         //
3171         // This component is the server name we are serving
3172         //
3173
3174         if( RtlCompareUnicodeString( &uniComponentName,
3175                                      &AFSServerName,
3176                                      TRUE) != 0)
3177         {
3178
3179             //
3180             // Drive letter based name?
3181             //
3182
3183             uniFullName = pIrpSp->FileObject->FileName;
3184
3185             while( usIndex < uniFullName.Length/sizeof( WCHAR))
3186             {
3187
3188                 if( uniFullName.Buffer[ usIndex] == L':')
3189                 {
3190
3191                     uniFullName.Buffer = &uniFullName.Buffer[ usIndex + 2];
3192
3193                     uniFullName.Length -= (usIndex + 2) * sizeof( WCHAR);
3194
3195                     usDriveIndex = usIndex - 1;
3196
3197                     break;
3198                 }
3199
3200                 usIndex++;
3201             }
3202
3203             //
3204             // Do we have the right server name now?
3205             //
3206
3207             FsRtlDissectName( uniFullName,
3208                               &uniComponentName,
3209                               &uniRemainingPath);
3210
3211             uniFullName = uniRemainingPath;
3212
3213             //
3214             // This component is the server name we are serving
3215             //
3216
3217             if( RtlCompareUnicodeString( &uniComponentName,
3218                                          &AFSServerName,
3219                                          TRUE) != 0)
3220             {
3221
3222                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3223                               AFS_TRACE_LEVEL_ERROR,
3224                               "AFSParseName (%p) Name %wZ does not have server name\n",
3225                               Irp,
3226                               &pIrpSp->FileObject->FileName);
3227
3228                 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3229             }
3230
3231             //
3232             // Validate this drive letter is actively mapped
3233             //
3234
3235             if( usDriveIndex > 0 &&
3236                 !AFSIsDriveMapped( pIrpSp->FileObject->FileName.Buffer[ usDriveIndex]))
3237             {
3238
3239                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3240                               AFS_TRACE_LEVEL_ERROR,
3241                               "AFSParseName (%p) Name %wZ contains invalid drive mapping\n",
3242                               Irp,
3243                               &pIrpSp->FileObject->FileName);
3244
3245                 try_return( ntStatus = STATUS_BAD_NETWORK_NAME);
3246             }
3247         }
3248
3249         if( FsRtlDoesNameContainWildCards( &uniFullName))
3250         {
3251
3252             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3253                           AFS_TRACE_LEVEL_ERROR,
3254                           "AFSParseName (%p) Component %wZ contains wild cards\n",
3255                           Irp,
3256                           &uniFullName);
3257
3258             try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3259         }
3260
3261         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3262                       AFS_TRACE_LEVEL_VERBOSE_2,
3263                       "AFSParseName (%p) Processing full name %wZ\n",
3264                       Irp,
3265                       &uniFullName);
3266
3267         if( uniFullName.Length > 0 &&
3268             uniFullName.Buffer[ (uniFullName.Length/sizeof( WCHAR)) - 1] == L'\\')
3269         {
3270
3271             uniFullName.Length -= sizeof( WCHAR);
3272         }
3273
3274         //
3275         // Be sure we are online and ready to go
3276         //
3277
3278         AFSAcquireShared( AFSGlobalRoot->VolumeLock,
3279                           TRUE);
3280
3281         if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
3282             BooleanFlagOn( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE))
3283         {
3284
3285             //
3286             // The volume has been taken off line so fail the access
3287             //
3288
3289             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3290                           AFS_TRACE_LEVEL_ERROR,
3291                           "AFSParseName (%p) Volume %08lX:%08lX OFFLINE/INVALID\n",
3292                           Irp,
3293                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3294                           AFSGlobalRoot->ObjectInformation.FileId.Volume);
3295
3296             AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3297
3298             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
3299         }
3300
3301         if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY))
3302         {
3303
3304             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3305                           AFS_TRACE_LEVEL_VERBOSE,
3306                           "AFSParseName (%p) Verifying root of volume %08lX:%08lX\n",
3307                           Irp,
3308                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3309                           AFSGlobalRoot->ObjectInformation.FileId.Volume);
3310
3311             ntStatus = AFSVerifyVolume( (ULONGLONG)PsGetCurrentProcessId(),
3312                                         AFSGlobalRoot);
3313
3314             if( !NT_SUCCESS( ntStatus))
3315             {
3316
3317                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3318                               AFS_TRACE_LEVEL_ERROR,
3319                               "AFSParseName (%p) Failed verification of root Status %08lX\n",
3320                               Irp,
3321                               ntStatus);
3322
3323                 AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3324
3325                 try_return( ntStatus);
3326             }
3327         }
3328
3329         AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3330
3331         if( !BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3332         {
3333
3334             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3335                           AFS_TRACE_LEVEL_VERBOSE,
3336                           "AFSParseName (%p) Enumerating global root of volume %08lX:%08lX\n",
3337                           Irp,
3338                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3339                           AFSGlobalRoot->ObjectInformation.FileId.Volume);
3340
3341             ntStatus = AFSEnumerateGlobalRoot( AuthGroup);
3342
3343             if( !NT_SUCCESS( ntStatus))
3344             {
3345
3346                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3347                               AFS_TRACE_LEVEL_ERROR,
3348                               "AFSParseName (%p) Failed enumeraiton of root Status %08lX\n",
3349                               Irp,
3350                               ntStatus);
3351
3352                 try_return( ntStatus);
3353             }
3354         }
3355
3356         //
3357         // Check for the \\Server access and return it as though it were \\Server\Globalroot
3358         //
3359
3360         if( uniRemainingPath.Buffer == NULL ||
3361             ( uniRemainingPath.Length == sizeof( WCHAR) &&
3362               uniRemainingPath.Buffer[ 0] == L'\\'))
3363         {
3364
3365             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3366                           AFS_TRACE_LEVEL_VERBOSE_2,
3367                           "AFSParseName (%p) Returning global root access\n",
3368                           Irp);
3369
3370             lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3371
3372             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3373                           AFS_TRACE_LEVEL_VERBOSE,
3374                           "AFSParseName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
3375                           &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3376                           AFSGlobalRoot->DirectoryCB,
3377                           NULL,
3378                           lCount);
3379
3380             *VolumeCB = NULL;
3381
3382             FileName->Length = 0;
3383             FileName->MaximumLength = 0;
3384             FileName->Buffer = NULL;
3385
3386             try_return( ntStatus = STATUS_SUCCESS);
3387         }
3388
3389         *RootFileName = uniFullName;
3390
3391         //
3392         // Include the starting \ in the root name
3393         //
3394
3395         if( RootFileName->Buffer[ 0] != L'\\')
3396         {
3397             RootFileName->Buffer--;
3398             RootFileName->Length += sizeof( WCHAR);
3399             RootFileName->MaximumLength += sizeof( WCHAR);
3400         }
3401
3402         //
3403         // Get the 'share' name
3404         //
3405
3406         FsRtlDissectName( uniFullName,
3407                           &uniComponentName,
3408                           &uniRemainingPath);
3409
3410         if( FsRtlDoesNameContainWildCards( &uniFullName))
3411         {
3412
3413             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3414                           AFS_TRACE_LEVEL_ERROR,
3415                           "AFSParseName (%p) Component %wZ contains wild cards\n",
3416                           Irp,
3417                           &uniComponentName);
3418
3419             try_return( ntStatus = STATUS_OBJECT_NAME_INVALID);
3420         }
3421
3422         //
3423         // If this is the ALL access then perform some additional processing
3424         //
3425
3426         if( uniComponentName.Length == 0 ||
3427             RtlCompareUnicodeString( &uniComponentName,
3428                                      &AFSGlobalRootName,
3429                                      TRUE) == 0)
3430         {
3431
3432             bIsAllShare = TRUE;
3433
3434             //
3435             // If there is nothing else then get out
3436             //
3437
3438             if( uniRemainingPath.Buffer == NULL ||
3439                 uniRemainingPath.Length == 0 ||
3440                 ( uniRemainingPath.Length == sizeof( WCHAR) &&
3441                   uniRemainingPath.Buffer[ 0] == L'\\'))
3442             {
3443
3444                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3445                               AFS_TRACE_LEVEL_VERBOSE_2,
3446                               "AFSParseName (%p) Returning global root access\n",
3447                               Irp);
3448
3449                 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3450
3451                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3452                               AFS_TRACE_LEVEL_VERBOSE,
3453                               "AFSParseName Increment3 count on %wZ DE %p Ccb %p Cnt %d\n",
3454                               &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3455                               AFSGlobalRoot->DirectoryCB,
3456                               NULL,
3457                               lCount);
3458
3459                 *VolumeCB = NULL;
3460
3461                 FileName->Length = 0;
3462                 FileName->MaximumLength = 0;
3463                 FileName->Buffer = NULL;
3464
3465                 try_return( ntStatus = STATUS_SUCCESS);
3466             }
3467
3468             //
3469             // Process the name again to strip off the ALL portion
3470             //
3471
3472             uniFullName = uniRemainingPath;
3473
3474             FsRtlDissectName( uniFullName,
3475                               &uniComponentName,
3476                               &uniRemainingPath);
3477
3478             //
3479             // Check for the PIOCtl name
3480             //
3481
3482             if( RtlCompareUnicodeString( &uniComponentName,
3483                                          &AFSPIOCtlName,
3484                                          TRUE) == 0)
3485             {
3486
3487                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3488                               AFS_TRACE_LEVEL_VERBOSE_2,
3489                               "AFSParseName (%p) Returning root PIOCtl access\n",
3490                               Irp);
3491
3492                 lCount = InterlockedIncrement( &AFSGlobalRoot->DirectoryCB->DirOpenReferenceCount);
3493
3494                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3495                               AFS_TRACE_LEVEL_VERBOSE,
3496                               "AFSParseName Increment4 count on %wZ DE %p Ccb %p Cnt %d\n",
3497                               &AFSGlobalRoot->DirectoryCB->NameInformation.FileName,
3498                               AFSGlobalRoot->DirectoryCB,
3499                               NULL,
3500                               lCount);
3501
3502                 ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3503
3504                 *VolumeCB = NULL;
3505
3506                 *FileName = AFSPIOCtlName;
3507
3508                 try_return( ntStatus = STATUS_SUCCESS);
3509             }
3510         }
3511         else if( (pDirEntry = AFSGetSpecialShareNameEntry( &uniComponentName,
3512                                                            &uniRemainingPath)) != NULL)
3513         {
3514
3515             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3516                           AFS_TRACE_LEVEL_VERBOSE_2,
3517                           "AFSParseName (%p) Returning root share name %wZ access\n",
3518                           Irp,
3519                           &uniComponentName);
3520
3521             //
3522             // Add in the full share name to pass back
3523             //
3524
3525             if( uniRemainingPath.Buffer != NULL)
3526             {
3527
3528                 //
3529                 // This routine strips off the leading slash so add it back in
3530                 //
3531
3532                 uniRemainingPath.Buffer--;
3533                 uniRemainingPath.Length += sizeof( WCHAR);
3534                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3535
3536                 //
3537                 // And the cell name
3538                 //
3539
3540                 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3541                 uniRemainingPath.Length += uniComponentName.Length;
3542                 uniRemainingPath.MaximumLength += uniComponentName.Length;
3543
3544                 uniComponentName = uniRemainingPath;
3545             }
3546
3547             *VolumeCB = NULL;
3548
3549             *FileName = uniComponentName;
3550
3551             ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3552
3553             *ParentDirectoryCB = pDirEntry;
3554
3555             try_return( ntStatus = STATUS_SUCCESS);
3556         }
3557
3558         //
3559         // Determine the 'share' we are accessing
3560         //
3561
3562         ulCRC = AFSGenerateCRC( &uniComponentName,
3563                                 FALSE);
3564
3565         AFSAcquireShared( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
3566                           TRUE);
3567
3568         bReleaseTreeLock = TRUE;
3569
3570         AFSLocateCaseSensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
3571                                         ulCRC,
3572                                         &pDirEntry);
3573
3574         if( pDirEntry == NULL)
3575         {
3576
3577             ulCRC = AFSGenerateCRC( &uniComponentName,
3578                                     TRUE);
3579
3580             AFSLocateCaseInsensitiveDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
3581                                               ulCRC,
3582                                               &pDirEntry);
3583
3584             if( pDirEntry == NULL)
3585             {
3586
3587                 //
3588                 // OK, if this component is a valid short name then try
3589                 // a lookup in the short name tree
3590                 //
3591
3592                 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3593                     RtlIsNameLegalDOS8Dot3( &uniComponentName,
3594                                             NULL,
3595                                             NULL))
3596                 {
3597
3598                     AFSLocateShortNameDirEntry( AFSGlobalRoot->ObjectInformation.Specific.Directory.ShortNameTree,
3599                                                 ulCRC,
3600                                                 &pDirEntry);
3601                 }
3602
3603                 if( pDirEntry == NULL)
3604                 {
3605
3606                     //
3607                     // Check with the service whether it is a valid cell name
3608                     //
3609
3610                     AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3611
3612                     bReleaseTreeLock = FALSE;
3613
3614                     ntStatus = AFSCheckCellName( AuthGroup,
3615                                                  &uniComponentName,
3616                                                  &pDirEntry);
3617
3618                     if( !NT_SUCCESS( ntStatus))
3619                     {
3620
3621                         if ( bIsAllShare &&
3622                              uniRemainingPath.Length == 0 &&
3623                              ntStatus == STATUS_OBJECT_PATH_NOT_FOUND)
3624                         {
3625
3626                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3627                                           AFS_TRACE_LEVEL_VERBOSE,
3628                                           "AFSParseName (%p) AFSCheckCellName %wZ returned path not found; ntStatus %08X\n",
3629                                           Irp,
3630                                           &uniComponentName,
3631                                           STATUS_OBJECT_NAME_NOT_FOUND);
3632
3633                             ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
3634                         }
3635
3636                         try_return( ntStatus);
3637                     }
3638                 }
3639             }
3640         }
3641
3642         if( bReleaseTreeLock)
3643         {
3644             AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
3645         }
3646
3647
3648         //
3649         // Be sure we are starting from the correct volume
3650         //
3651
3652         if( pDirEntry->ObjectInformation->VolumeCB != AFSGlobalRoot)
3653         {
3654
3655             //
3656             // We dropped the global root in the CheckCellName routine which is the
3657             // only way we can be here
3658             //
3659
3660             pVolumeCB = pDirEntry->ObjectInformation->VolumeCB;
3661
3662             //
3663             // Init our name array
3664             //
3665
3666             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
3667                                            0);
3668
3669             if( pNameArray == NULL)
3670             {
3671
3672                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3673                               AFS_TRACE_LEVEL_VERBOSE,
3674                               "AFSParseName (%p) Failed to initialize name array\n",
3675                               Irp);
3676
3677                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3678             }
3679
3680             ntStatus = AFSInsertNextElement( pNameArray,
3681                                              pVolumeCB->DirectoryCB);
3682
3683             if ( ntStatus)
3684             {
3685
3686                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3687                               AFS_TRACE_LEVEL_VERBOSE,
3688                               "AFSParseName (%p) Failed to insert name array element\n",
3689                               Irp);
3690
3691                 try_return( ntStatus);
3692             }
3693
3694             //
3695             // In this case don't add back in the 'share' name since that is where we are
3696             // starting. Just put the leading slash back in
3697             //
3698
3699             if( uniRemainingPath.Buffer != NULL)
3700             {
3701
3702                 uniRemainingPath.Buffer--;
3703                 uniRemainingPath.Length += sizeof( WCHAR);
3704                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3705
3706                 if( uniRemainingPath.Length > sizeof( WCHAR))
3707                 {
3708
3709                     ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3710                 }
3711
3712                 //
3713                 // Pass back the parent being the root of the volume
3714                 //
3715
3716                 *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3717             }
3718             else
3719             {
3720
3721                 //
3722                 // Pass back a root slash
3723                 //
3724
3725                 uniRemainingPath = uniComponentName;
3726
3727                 uniRemainingPath.Buffer--;
3728                 uniRemainingPath.Length = sizeof( WCHAR);
3729                 uniRemainingPath.MaximumLength = sizeof( WCHAR);
3730
3731                 //
3732                 // This is a root open so pass back no parent
3733                 //
3734             }
3735         }
3736         else
3737         {
3738
3739             pVolumeCB = AFSGlobalRoot;
3740
3741             //
3742             // Init our name array
3743             //
3744
3745             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
3746                                            0);
3747             if( pNameArray == NULL)
3748             {
3749
3750                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3751                               AFS_TRACE_LEVEL_VERBOSE,
3752                               "AFSParseName (%p) Failed to initialize name array\n",
3753                               Irp);
3754
3755                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
3756             }
3757
3758             //
3759             // Add back in the 'share' portion of the name since we will parse it out on return
3760             //
3761
3762             if( uniRemainingPath.Buffer != NULL)
3763             {
3764
3765                 //
3766                 // This routine strips off the leading slash so add it back in
3767                 //
3768
3769                 uniRemainingPath.Buffer--;
3770                 uniRemainingPath.Length += sizeof( WCHAR);
3771                 uniRemainingPath.MaximumLength += sizeof( WCHAR);
3772
3773                 if( uniRemainingPath.Length > sizeof( WCHAR))
3774                 {
3775
3776                     ClearFlag( *ParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS);
3777                 }
3778
3779                 //
3780                 // And the cell name
3781                 //
3782
3783                 uniRemainingPath.Buffer -= (uniComponentName.Length/sizeof( WCHAR));
3784                 uniRemainingPath.Length += uniComponentName.Length;
3785                 uniRemainingPath.MaximumLength += uniComponentName.Length;
3786             }
3787             else
3788             {
3789
3790                 uniRemainingPath = uniComponentName;
3791             }
3792
3793             //
3794             // And the leading slash again ...
3795             //
3796
3797             uniRemainingPath.Buffer--;
3798             uniRemainingPath.Length += sizeof( WCHAR);
3799             uniRemainingPath.MaximumLength += sizeof( WCHAR);
3800
3801             //
3802             // Pass back the parent being the volume root
3803             //
3804
3805             *ParentDirectoryCB = pVolumeCB->DirectoryCB;
3806         }
3807
3808         //
3809         // Return the remaining portion as the file name
3810         //
3811
3812         *FileName = uniRemainingPath;
3813
3814         *ParsedFileName = uniRemainingPath;
3815
3816         *NameArray = pNameArray;
3817
3818         *VolumeCB = pVolumeCB;
3819
3820         //
3821         // Increment our reference on the volume
3822         //
3823
3824         lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
3825
3826         AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3827                       AFS_TRACE_LEVEL_VERBOSE,
3828                       "AFSParseName Increment2 count on global volume %p Cnt %d\n",
3829                       pVolumeCB,
3830                       lCount);
3831
3832 try_exit:
3833
3834         if( NT_SUCCESS( ntStatus))
3835         {
3836
3837             if( *ParentDirectoryCB != NULL)
3838             {
3839
3840                 lCount = InterlockedIncrement( &(*ParentDirectoryCB)->DirOpenReferenceCount);
3841
3842                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3843                               AFS_TRACE_LEVEL_VERBOSE,
3844                               "AFSParseName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
3845                               &(*ParentDirectoryCB)->NameInformation.FileName,
3846                               (*ParentDirectoryCB),
3847                               NULL,
3848                               lCount);
3849             }
3850         }
3851
3852         if( *VolumeCB != NULL)
3853         {
3854             ASSERT( (*VolumeCB)->VolumeReferenceCount > 1);
3855         }
3856
3857         if( ntStatus != STATUS_SUCCESS)
3858         {
3859
3860             if( pNameArray != NULL)
3861             {
3862
3863                 AFSFreeNameArray( pNameArray);
3864             }
3865         }
3866     }
3867
3868     return ntStatus;
3869 }
3870
3871 NTSTATUS
3872 AFSCheckCellName( IN GUID *AuthGroup,
3873                   IN UNICODE_STRING *CellName,
3874                   OUT AFSDirectoryCB **ShareDirEntry)
3875 {
3876
3877     NTSTATUS ntStatus = STATUS_SUCCESS;
3878     UNICODE_STRING uniName;
3879     AFSDirEnumEntry *pDirEnumEntry = NULL;
3880     AFSDirHdr *pDirHdr = &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr;
3881     AFSDirectoryCB *pDirNode = NULL;
3882     UNICODE_STRING uniDirName, uniTargetName;
3883     AFSVolumeCB *pVolumeCB = NULL;
3884     LONG lCount;
3885
3886     __Enter
3887     {
3888
3889         //
3890         // Look for some default names we will not handle
3891         //
3892
3893         RtlInitUnicodeString( &uniName,
3894                               L"IPC$");
3895
3896         if( RtlCompareUnicodeString( &uniName,
3897                                      CellName,
3898                                      TRUE) == 0)
3899         {
3900
3901             try_return( ntStatus = STATUS_NO_SUCH_FILE);
3902         }
3903
3904         RtlInitUnicodeString( &uniName,
3905                               L"wkssvc");
3906
3907         if( RtlCompareUnicodeString( &uniName,
3908                                      CellName,
3909                                      TRUE) == 0)
3910         {
3911
3912             try_return( ntStatus = STATUS_NO_SUCH_FILE);
3913         }
3914
3915         RtlInitUnicodeString( &uniName,
3916                               L"srvsvc");
3917
3918         if( RtlCompareUnicodeString( &uniName,
3919                                      CellName,
3920                                      TRUE) == 0)
3921         {
3922
3923             try_return( ntStatus = STATUS_NO_SUCH_FILE);
3924         }
3925
3926         RtlInitUnicodeString( &uniName,
3927                               L"PIPE");
3928
3929         if( RtlCompareUnicodeString( &uniName,
3930                                      CellName,
3931                                      TRUE) == 0)
3932         {
3933
3934             try_return( ntStatus = STATUS_NO_SUCH_FILE);
3935         }
3936
3937         //
3938         // OK, ask the CM about this component name
3939         //
3940
3941         ntStatus = AFSEvaluateTargetByName( AuthGroup,
3942                                             &AFSGlobalRoot->ObjectInformation,
3943                                             CellName,
3944                                             &pDirEnumEntry);
3945
3946         if( !NT_SUCCESS( ntStatus))
3947         {
3948
3949             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3950                           AFS_TRACE_LEVEL_WARNING,
3951                           "AFSCheckCellName entry %wZ does not exist parent FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3952                           CellName,
3953                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
3954                           AFSGlobalRoot->ObjectInformation.FileId.Volume,
3955                           AFSGlobalRoot->ObjectInformation.FileId.Vnode,
3956                           AFSGlobalRoot->ObjectInformation.FileId.Unique,
3957                           ntStatus);
3958
3959             try_return( ntStatus);
3960         }
3961
3962         //
3963         // OK, we have a dir enum entry back so add it to the root node
3964         //
3965
3966         uniDirName = *CellName;
3967
3968         uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
3969         uniTargetName.MaximumLength = uniTargetName.Length;
3970         uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
3971
3972         //
3973         // Is this entry a root volume entry?
3974         //
3975
3976         if( pDirEnumEntry->FileId.Cell != AFSGlobalRoot->ObjectInformation.FileId.Cell ||
3977             pDirEnumEntry->FileId.Volume != AFSGlobalRoot->ObjectInformation.FileId.Volume)
3978         {
3979
3980             //
3981             // Build the root volume entry
3982             //
3983
3984             ntStatus = AFSBuildRootVolume( AuthGroup,
3985                                            &pDirEnumEntry->FileId,
3986                                            &pVolumeCB);
3987
3988             if( !NT_SUCCESS( ntStatus))
3989             {
3990                 try_return( ntStatus);
3991             }
3992
3993             *ShareDirEntry = pVolumeCB->DirectoryCB;
3994
3995             lCount = InterlockedIncrement( &pVolumeCB->DirectoryCB->DirOpenReferenceCount);
3996
3997             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
3998                           AFS_TRACE_LEVEL_VERBOSE,
3999                           "AFSCheckCellName Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
4000                           &pVolumeCB->DirectoryCB->NameInformation.FileName,
4001                           pVolumeCB->DirectoryCB,
4002                           NULL,
4003                           lCount);
4004
4005             lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
4006
4007             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4008                           AFS_TRACE_LEVEL_VERBOSE,
4009                           "AFSCheckCellName Increment count on volume %p Cnt %d\n",
4010                           pVolumeCB,
4011                           lCount);
4012         }
4013         else
4014         {
4015
4016             lCount = InterlockedIncrement( &pDirHdr->ContentIndex);
4017
4018             pDirNode = AFSInitDirEntry( &AFSGlobalRoot->ObjectInformation,
4019                                         &uniDirName,
4020                                         &uniTargetName,
4021                                         pDirEnumEntry,
4022                                         (ULONG)lCount);
4023
4024             if( pDirNode == NULL)
4025             {
4026
4027                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4028             }
4029
4030             //
4031             // Init the short name if we have one
4032             //
4033
4034             if( pDirEnumEntry->ShortNameLength > 0)
4035             {
4036
4037                 pDirNode->NameInformation.ShortNameLength = pDirEnumEntry->ShortNameLength;
4038
4039                 RtlCopyMemory( pDirNode->NameInformation.ShortName,
4040                                pDirEnumEntry->ShortName,
4041                                pDirNode->NameInformation.ShortNameLength);
4042             }
4043
4044             AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4045                             TRUE);
4046
4047             //
4048             // Insert the node into the name tree
4049             //
4050
4051             ASSERT( ExIsResourceAcquiredExclusiveLite( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock));
4052
4053             if( pDirHdr->CaseSensitiveTreeHead == NULL)
4054             {
4055
4056                 pDirHdr->CaseSensitiveTreeHead = pDirNode;
4057             }
4058             else
4059             {
4060
4061                 if( !NT_SUCCESS( AFSInsertCaseSensitiveDirEntry( pDirHdr->CaseSensitiveTreeHead,
4062                                                                  pDirNode)))
4063                 {
4064
4065                     AFSDeleteDirEntry( &AFSGlobalRoot->ObjectInformation,
4066                                        pDirNode);
4067
4068                     AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4069
4070                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4071                 }
4072             }
4073
4074             ClearFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
4075
4076             if( pDirHdr->CaseInsensitiveTreeHead == NULL)
4077             {
4078
4079                 pDirHdr->CaseInsensitiveTreeHead = pDirNode;
4080
4081                 SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
4082             }
4083             else
4084             {
4085
4086                 AFSInsertCaseInsensitiveDirEntry( pDirHdr->CaseInsensitiveTreeHead,
4087                                                   pDirNode);
4088             }
4089
4090             if( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead == NULL)
4091             {
4092
4093                 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead = pDirNode;
4094             }
4095             else
4096             {
4097
4098                 AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail->ListEntry.fLink = pDirNode;
4099
4100                 pDirNode->ListEntry.bLink = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail;
4101             }
4102
4103             AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListTail = pDirNode;
4104
4105             SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_INSERTED_ENUM_LIST);
4106
4107             lCount = InterlockedIncrement( &AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeCount);
4108
4109             AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
4110                           AFS_TRACE_LEVEL_VERBOSE,
4111                           "AFSCheckCellName Adding entry %wZ Inc Count %d to parent FID %08lX-%08lX-%08lX-%08lX\n",
4112                           &pDirNode->NameInformation.FileName,
4113                           lCount,
4114                           AFSGlobalRoot->ObjectInformation.FileId.Cell,
4115                           AFSGlobalRoot->ObjectInformation.FileId.Volume,
4116                           AFSGlobalRoot->ObjectInformation.FileId.Vnode,
4117                           AFSGlobalRoot->ObjectInformation.FileId.Unique);
4118
4119             lCount = InterlockedIncrement( &pDirNode->DirOpenReferenceCount);
4120
4121             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
4122                           AFS_TRACE_LEVEL_VERBOSE,
4123                           "AFSCheckCellName Increment2 count on %wZ DE %p Ccb %p Cnt %d\n",
4124                           &pDirNode->NameInformation.FileName,
4125                           pDirNode,
4126                           NULL,
4127                           lCount);
4128
4129             AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4130
4131             //
4132             // Pass back the dir node
4133             //
4134
4135             *ShareDirEntry = pDirNode;
4136         }
4137
4138 try_exit:
4139
4140         if( pDirEnumEntry != NULL)
4141         {
4142
4143             AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_31_TAG);
4144         }
4145     }
4146
4147     return ntStatus;
4148 }
4149
4150 NTSTATUS
4151 AFSBuildMountPointTarget( IN GUID *AuthGroup,
4152                           IN AFSDirectoryCB  *DirectoryCB,
4153                           OUT AFSVolumeCB **TargetVolumeCB)
4154 {
4155
4156     NTSTATUS ntStatus = STATUS_SUCCESS;
4157     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4158     AFSDirEnumEntry *pDirEntry = NULL;
4159     ULONGLONG       ullIndex = 0;
4160     AFSVolumeCB *pVolumeCB = NULL;
4161     AFSFileID stTargetFileID;
4162     LONG lCount;
4163     BOOLEAN bReleaseVolumeLock = FALSE;
4164
4165     __Enter
4166     {
4167
4168         //
4169         // Loop on each entry, building the chain until we encounter the final target
4170         //
4171
4172         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4173                       AFS_TRACE_LEVEL_VERBOSE_2,
4174                       "AFSBuildMountPointTarget Building target directory for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4175                       &DirectoryCB->NameInformation.FileName,
4176                       DirectoryCB->ObjectInformation->FileId.Cell,
4177                       DirectoryCB->ObjectInformation->FileId.Volume,
4178                       DirectoryCB->ObjectInformation->FileId.Vnode,
4179                       DirectoryCB->ObjectInformation->FileId.Unique);
4180
4181         //
4182         // Do we need to evaluate the node?
4183         //
4184
4185         //if( DirectoryCB->ObjectInformation->TargetFileId.Vnode == 0 &&
4186         //    DirectoryCB->ObjectInformation->TargetFileId.Unique == 0)
4187         {
4188
4189             //
4190             // Go evaluate the current target to get the target fid
4191             //
4192
4193             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4194                           AFS_TRACE_LEVEL_VERBOSE_2,
4195                           "AFSBuildMountPointTarget Evaluating target %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4196                               &DirectoryCB->NameInformation.FileName,
4197                               DirectoryCB->ObjectInformation->FileId.Cell,
4198                               DirectoryCB->ObjectInformation->FileId.Volume,
4199                               DirectoryCB->ObjectInformation->FileId.Vnode,
4200                               DirectoryCB->ObjectInformation->FileId.Unique);
4201
4202             ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
4203                                               AuthGroup,
4204                                               FALSE,
4205                                               &pDirEntry);
4206
4207             if( !NT_SUCCESS( ntStatus))
4208             {
4209
4210                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4211                               AFS_TRACE_LEVEL_ERROR,
4212                               "AFSBuildMountPointTarget Failed to evaluate target %wZ Status %08lX\n",
4213                               &DirectoryCB->NameInformation.FileName,
4214                               ntStatus);
4215                 try_return( ntStatus);
4216             }
4217
4218             if( pDirEntry->TargetFileId.Vnode == 0 &&
4219                 pDirEntry->TargetFileId.Unique == 0)
4220             {
4221
4222                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4223                               AFS_TRACE_LEVEL_ERROR,
4224                               "AFSBuildMountPointTarget Target %wZ FID %08lX-%08lX-%08lX-%08lX service returned zero FID\n",
4225                               &DirectoryCB->NameInformation.FileName,
4226                               DirectoryCB->ObjectInformation->FileId.Cell,
4227                               DirectoryCB->ObjectInformation->FileId.Volume,
4228                               DirectoryCB->ObjectInformation->FileId.Vnode,
4229                               DirectoryCB->ObjectInformation->FileId.Unique);
4230
4231                 try_return( ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED);
4232             }
4233
4234             AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
4235                             TRUE);
4236
4237             ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
4238                                             &DirectoryCB->Flags,
4239                                             (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4240                                             (USHORT)pDirEntry->TargetNameLength);
4241
4242             if( !NT_SUCCESS( ntStatus))
4243             {
4244
4245                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4246
4247                 try_return( ntStatus);
4248             }
4249
4250             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
4251
4252             DirectoryCB->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
4253         }
4254
4255         stTargetFileID = DirectoryCB->ObjectInformation->TargetFileId;
4256
4257         //
4258         // Try to locate this FID. First the volume then the
4259         // entry itself
4260         //
4261
4262         ullIndex = AFSCreateHighIndex( &stTargetFileID);
4263
4264         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4265                       AFS_TRACE_LEVEL_VERBOSE,
4266                       "AFSBuildMountPointTarget Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4267                       &pDevExt->Specific.RDR.VolumeTreeLock,
4268                       PsGetCurrentThread());
4269
4270         AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4271                           TRUE);
4272
4273         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4274                       AFS_TRACE_LEVEL_VERBOSE_2,
4275                       "AFSBuildMountPointTarget Locating volume for target %I64X\n",
4276                       ullIndex);
4277
4278         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4279                                        ullIndex,
4280                                        (AFSBTreeEntry **)&pVolumeCB);
4281
4282         //
4283         // We can be processing a request for a target that is on a volume
4284         // we have never seen before.
4285         //
4286
4287         if( pVolumeCB == NULL)
4288         {
4289
4290             //
4291             // Locking is held correctly in init routine
4292             //
4293
4294             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4295
4296             //
4297             // Go init the root of the volume
4298             //
4299
4300             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4301                           AFS_TRACE_LEVEL_VERBOSE_2,
4302                           "AFSBuildMountPointTarget Initializing root for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4303                           &DirectoryCB->NameInformation.FileName,
4304                           DirectoryCB->ObjectInformation->FileId.Cell,
4305                           DirectoryCB->ObjectInformation->FileId.Volume,
4306                           DirectoryCB->ObjectInformation->FileId.Vnode,
4307                           DirectoryCB->ObjectInformation->FileId.Unique);
4308
4309             ntStatus = AFSInitVolume( AuthGroup,
4310                                       &stTargetFileID,
4311                                       &pVolumeCB);
4312
4313             if( !NT_SUCCESS( ntStatus))
4314             {
4315
4316                 try_return( ntStatus);
4317             }
4318
4319             //
4320             // pVolumeCB->VolumeLock held exclusive and
4321             // pVolumeCB->VolumeReferenceCount has been incremented
4322             // pVolumeCB->RootFcb == NULL
4323             //
4324
4325             bReleaseVolumeLock = TRUE;
4326         }
4327         else
4328         {
4329
4330             //
4331             // AFSInitVolume returns with a VolumeReferenceCount
4332             // obtain one to match
4333             //
4334
4335             lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
4336
4337             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4338                           AFS_TRACE_LEVEL_VERBOSE,
4339                           "AFSBuildMountPointTarget Increment count on volume %p Cnt %d\n",
4340                           pVolumeCB,
4341                           lCount);
4342
4343             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4344         }
4345
4346         if( pVolumeCB->RootFcb == NULL)
4347         {
4348
4349             if ( bReleaseVolumeLock == FALSE)
4350             {
4351
4352                 AFSAcquireExcl( pVolumeCB->VolumeLock,
4353                                 TRUE);
4354
4355                 bReleaseVolumeLock = TRUE;
4356             }
4357
4358             //
4359             // Initialize the root fcb for this volume
4360             //
4361
4362             ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4363                                        pVolumeCB);
4364
4365             if( !NT_SUCCESS( ntStatus))
4366             {
4367
4368                 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
4369
4370                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4371                               AFS_TRACE_LEVEL_VERBOSE,
4372                               "AFSBuildMountPoint Decrement count on volume %p Cnt %d\n",
4373                               pVolumeCB,
4374                               lCount);
4375
4376                 AFSReleaseResource( pVolumeCB->VolumeLock);
4377
4378                 try_return( ntStatus);
4379             }
4380
4381             //
4382             // Drop the lock acquired above
4383             //
4384
4385             AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4386         }
4387
4388         if ( bReleaseVolumeLock == TRUE)
4389         {
4390
4391             AFSReleaseResource( pVolumeCB->VolumeLock);
4392         }
4393
4394         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4395                       AFS_TRACE_LEVEL_VERBOSE_2,
4396                       "AFSBuildMountPointTarget Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4397                       &pVolumeCB->DirectoryCB->NameInformation.FileName,
4398                       pVolumeCB->ObjectInformation.FileId.Cell,
4399                       pVolumeCB->ObjectInformation.FileId.Volume,
4400                       pVolumeCB->ObjectInformation.FileId.Vnode,
4401                       pVolumeCB->ObjectInformation.FileId.Unique);
4402
4403         *TargetVolumeCB = pVolumeCB;
4404
4405 try_exit:
4406
4407         if( pDirEntry)
4408         {
4409
4410             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
4411         }
4412     }
4413
4414     return ntStatus;
4415 }
4416
4417 NTSTATUS
4418 AFSBuildRootVolume( IN GUID *AuthGroup,
4419                     IN AFSFileID *FileId,
4420                     OUT AFSVolumeCB **TargetVolumeCB)
4421 {
4422
4423     NTSTATUS ntStatus = STATUS_SUCCESS;
4424     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4425     ULONGLONG       ullIndex = 0;
4426     AFSVolumeCB *pVolumeCB = NULL;
4427     LONG lCount;
4428     BOOLEAN bReleaseVolumeLock = FALSE;
4429
4430     __Enter
4431     {
4432
4433         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4434                       AFS_TRACE_LEVEL_VERBOSE_2,
4435                       "AFSBuildRootVolume Building target volume for FID %08lX-%08lX-%08lX-%08lX\n",
4436                       FileId->Cell,
4437                       FileId->Volume,
4438                       FileId->Vnode,
4439                       FileId->Unique);
4440
4441         ullIndex = AFSCreateHighIndex( FileId);
4442
4443         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
4444                       AFS_TRACE_LEVEL_VERBOSE,
4445                       "AFSBuildRootVolume Acquiring RDR VolumeTreeLock lock %p EXCL %08lX\n",
4446                       &pDevExt->Specific.RDR.VolumeTreeLock,
4447                       PsGetCurrentThread());
4448
4449         AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock,
4450                           TRUE);
4451
4452         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4453                       AFS_TRACE_LEVEL_VERBOSE_2,
4454                       "AFSBuildRootVolume Locating volume for target %I64X\n",
4455                       ullIndex);
4456
4457         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
4458                                        ullIndex,
4459                                        (AFSBTreeEntry **)&pVolumeCB);
4460
4461         //
4462         // We can be processing a request for a target that is on a volume
4463         // we have never seen before.
4464         //
4465
4466         if( pVolumeCB == NULL)
4467         {
4468
4469             //
4470             // Locking is held correctly in init routine
4471             //
4472
4473             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4474
4475             //
4476             // Go init the root of the volume
4477             //
4478
4479             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4480                          AFS_TRACE_LEVEL_VERBOSE_2,
4481                           "AFSBuildRootVolume Initializing root for FID %08lX-%08lX-%08lX-%08lX\n",
4482                           FileId->Cell,
4483                           FileId->Volume,
4484                           FileId->Vnode,
4485                           FileId->Unique);
4486
4487             ntStatus = AFSInitVolume( AuthGroup,
4488                                       FileId,
4489                                       &pVolumeCB);
4490
4491             if( !NT_SUCCESS( ntStatus))
4492             {
4493
4494                 try_return( ntStatus);
4495             }
4496
4497             //
4498             // pVolumeCB->VolumeLock is held exclusive
4499             // pVolumeCB->VolumeReferenceCount has been incremented
4500             // pVolumeCB->RootFcb == NULL
4501             //
4502
4503             bReleaseVolumeLock = TRUE;
4504         }
4505         else
4506         {
4507
4508             //
4509             // AFSInitVolume returns with a VolumeReferenceCount
4510             // obtain one to match
4511             //
4512
4513             lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
4514
4515             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4516                           AFS_TRACE_LEVEL_VERBOSE,
4517                           "AFSBuildRootVolume Increment count on volume %p Cnt %d\n",
4518                           pVolumeCB,
4519                           lCount);
4520
4521             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
4522         }
4523
4524
4525         if( pVolumeCB->RootFcb == NULL)
4526         {
4527
4528             if ( bReleaseVolumeLock == FALSE)
4529             {
4530
4531                 AFSAcquireExcl( pVolumeCB->VolumeLock,
4532                                 TRUE);
4533
4534                 bReleaseVolumeLock = TRUE;
4535             }
4536
4537             //
4538             // Initialize the root fcb for this volume
4539             //
4540
4541             ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
4542                                        pVolumeCB);
4543
4544             if( !NT_SUCCESS( ntStatus))
4545             {
4546
4547                 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
4548
4549                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
4550                               AFS_TRACE_LEVEL_VERBOSE,
4551                               "AFSBuildRootVolume Decrement count on volume %p Cnt %d\n",
4552                               pVolumeCB,
4553                               lCount);
4554
4555                 AFSReleaseResource( pVolumeCB->VolumeLock);
4556
4557                 try_return( ntStatus);
4558             }
4559
4560             //
4561             // Drop the lock acquired above
4562             //
4563
4564             AFSReleaseResource( &pVolumeCB->RootFcb->NPFcb->Resource);
4565         }
4566
4567         if ( bReleaseVolumeLock == TRUE)
4568         {
4569
4570             AFSReleaseResource( pVolumeCB->VolumeLock);
4571         }
4572
4573         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4574                       AFS_TRACE_LEVEL_VERBOSE_2,
4575                       "AFSBuildRootVolume Evaluated target of %wZ FID %08lX-%08lX-%08lX-%08lX as root volume\n",
4576                       &pVolumeCB->DirectoryCB->NameInformation.FileName,
4577                       pVolumeCB->ObjectInformation.FileId.Cell,
4578                       pVolumeCB->ObjectInformation.FileId.Volume,
4579                       pVolumeCB->ObjectInformation.FileId.Vnode,
4580                       pVolumeCB->ObjectInformation.FileId.Unique);
4581
4582         *TargetVolumeCB = pVolumeCB;
4583
4584 try_exit:
4585
4586         NOTHING;
4587     }
4588
4589     return ntStatus;
4590 }
4591
4592 NTSTATUS
4593 AFSProcessDFSLink( IN AFSDirectoryCB *DirEntry,
4594                    IN PFILE_OBJECT FileObject,
4595                    IN UNICODE_STRING *RemainingPath,
4596                    IN GUID *AuthGroup)
4597 {
4598
4599     NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
4600     UNICODE_STRING uniReparseName;
4601     UNICODE_STRING uniMUPDeviceName;
4602     UNICODE_STRING uniIOMgrDeviceName;
4603     AFSDirEnumEntry *pDirEntry = NULL;
4604
4605     __Enter
4606     {
4607
4608         //
4609         // Build up the name to reparse
4610         //
4611
4612         RtlInitUnicodeString( &uniMUPDeviceName,
4613                               L"\\Device\\MUP");
4614
4615         RtlInitUnicodeString( &uniIOMgrDeviceName,
4616                               L"\\??\\");
4617
4618         uniReparseName.Length = 0;
4619         uniReparseName.Buffer = NULL;
4620
4621         //
4622         // Be sure we have a target name
4623         //
4624
4625         if( DirEntry->NameInformation.TargetName.Length == 0)
4626         {
4627
4628             ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
4629                                               AuthGroup,
4630                                               FALSE,
4631                                               &pDirEntry);
4632
4633             if( !NT_SUCCESS( ntStatus) ||
4634                 pDirEntry->TargetNameLength == 0)
4635             {
4636
4637                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4638                               AFS_TRACE_LEVEL_ERROR,
4639                               "AFSProcessDFSLink EvaluateTargetByID failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4640                               &DirEntry->NameInformation.FileName,
4641                               DirEntry->ObjectInformation->FileId.Cell,
4642                               DirEntry->ObjectInformation->FileId.Volume,
4643                               DirEntry->ObjectInformation->FileId.Vnode,
4644                               DirEntry->ObjectInformation->FileId.Unique,
4645                               ntStatus);
4646
4647                 if( NT_SUCCESS( ntStatus))
4648                 {
4649
4650                     ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
4651                 }
4652
4653                 try_return( ntStatus);
4654             }
4655
4656             //
4657             // Update the target name
4658             //
4659
4660             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
4661                             TRUE);
4662
4663             ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
4664                                             &DirEntry->Flags,
4665                                             (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
4666                                             (USHORT)pDirEntry->TargetNameLength);
4667
4668             if( !NT_SUCCESS( ntStatus))
4669             {
4670
4671                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4672                               AFS_TRACE_LEVEL_ERROR,
4673                               "AFSProcessDFSLink UpdateTargetName failed for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4674                               &DirEntry->NameInformation.FileName,
4675                               DirEntry->ObjectInformation->FileId.Cell,
4676                               DirEntry->ObjectInformation->FileId.Volume,
4677                               DirEntry->ObjectInformation->FileId.Vnode,
4678                               DirEntry->ObjectInformation->FileId.Unique,
4679                               ntStatus);
4680
4681                 AFSReleaseResource( &DirEntry->NonPaged->Lock);
4682
4683                 try_return( ntStatus);
4684             }
4685
4686             AFSConvertToShared( &DirEntry->NonPaged->Lock);
4687         }
4688         else
4689         {
4690             AFSAcquireShared( &DirEntry->NonPaged->Lock,
4691                               TRUE);
4692         }
4693
4694         uniReparseName.MaximumLength = uniMUPDeviceName.Length +
4695                                                    sizeof( WCHAR) +
4696                                                    DirEntry->NameInformation.TargetName.Length +
4697                                                    sizeof( WCHAR);
4698
4699         if( RemainingPath != NULL &&
4700             RemainingPath->Length > 0)
4701         {
4702
4703             uniReparseName.MaximumLength += RemainingPath->Length;
4704         }
4705
4706         //
4707         // Allocate the reparse buffer
4708         //
4709
4710         uniReparseName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4711                                                                    uniReparseName.MaximumLength,
4712                                                                    AFS_REPARSE_NAME_TAG);
4713
4714         if( uniReparseName.Buffer == NULL)
4715         {
4716
4717             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4718                           AFS_TRACE_LEVEL_ERROR,
4719                           "AFSProcessDFSLink uniReparseName.Buffer == NULL Fcb %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4720                           &DirEntry->NameInformation.FileName,
4721                           DirEntry->ObjectInformation->FileId.Cell,
4722                           DirEntry->ObjectInformation->FileId.Volume,
4723                           DirEntry->ObjectInformation->FileId.Vnode,
4724                           DirEntry->ObjectInformation->FileId.Unique,
4725                           STATUS_INSUFFICIENT_RESOURCES);
4726
4727             AFSReleaseResource( &DirEntry->NonPaged->Lock);
4728
4729             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4730         }
4731
4732         //
4733         // Start building the name
4734         //
4735
4736         if ( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\' &&
4737              DirEntry->NameInformation.TargetName.Buffer[ 1] == L':')
4738         {
4739
4740             RtlCopyMemory( uniReparseName.Buffer,
4741                            uniIOMgrDeviceName.Buffer,
4742                            uniIOMgrDeviceName.Length);
4743
4744             uniReparseName.Length = uniIOMgrDeviceName.Length;
4745         }
4746         else
4747         {
4748
4749             RtlCopyMemory( uniReparseName.Buffer,
4750                            uniMUPDeviceName.Buffer,
4751                            uniMUPDeviceName.Length);
4752
4753             uniReparseName.Length = uniMUPDeviceName.Length;
4754
4755             if( DirEntry->NameInformation.TargetName.Buffer[ 0] != L'\\')
4756             {
4757
4758                 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
4759
4760                 uniReparseName.Length += sizeof( WCHAR);
4761             }
4762         }
4763
4764         RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
4765                        DirEntry->NameInformation.TargetName.Buffer,
4766                        DirEntry->NameInformation.TargetName.Length);
4767
4768         uniReparseName.Length += DirEntry->NameInformation.TargetName.Length;
4769
4770         AFSReleaseResource( &DirEntry->NonPaged->Lock);
4771
4772         if( RemainingPath != NULL &&
4773             RemainingPath->Length > 0)
4774         {
4775
4776             if( uniReparseName.Buffer[ (uniReparseName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
4777                 RemainingPath->Buffer[ 0] != L'\\')
4778             {
4779
4780                 uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)] = L'\\';
4781
4782                 uniReparseName.Length += sizeof( WCHAR);
4783             }
4784
4785             RtlCopyMemory( &uniReparseName.Buffer[ uniReparseName.Length/sizeof( WCHAR)],
4786                            RemainingPath->Buffer,
4787                            RemainingPath->Length);
4788
4789             uniReparseName.Length += RemainingPath->Length;
4790         }
4791
4792         //
4793         // Update the name in the file object
4794         //
4795
4796         if( FileObject->FileName.Buffer != NULL)
4797         {
4798
4799             AFSExFreePoolWithTag( FileObject->FileName.Buffer, 0);
4800         }
4801
4802         FileObject->FileName = uniReparseName;
4803
4804         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
4805                       AFS_TRACE_LEVEL_VERBOSE,
4806                       "AFSProcessDFSLink Reparsing access to Fcb %wZ FID %08lX-%08lX-%08lX-%08lX to %wZ\n",
4807                       &DirEntry->NameInformation.FileName,
4808                       DirEntry->ObjectInformation->FileId.Cell,
4809                       DirEntry->ObjectInformation->FileId.Volume,
4810                       DirEntry->ObjectInformation->FileId.Vnode,
4811                       DirEntry->ObjectInformation->FileId.Unique,
4812                       &uniReparseName);
4813
4814         //
4815         // Return status reparse ...
4816         //
4817
4818         ntStatus = STATUS_REPARSE;
4819
4820 try_exit:
4821
4822         if ( pDirEntry)
4823         {
4824
4825             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
4826         }
4827     }
4828
4829     return ntStatus;
4830 }