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