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