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