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