1854c0c4b73adaee41d2a7a4c88a5aa19fd4e440
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSGeneric.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright
13  *   notice,
14  *   this list of conditions and the following disclaimer in the
15  *   documentation
16  *   and/or other materials provided with the distribution.
17  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18  *   nor the names of their contributors may be used to endorse or promote
19  *   products derived from this software without specific prior written
20  *   permission from Kernel Drivers, LLC and Your File System, Inc.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 //
36 // File: AFSGeneric.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 //
42 // Function: AFSExceptionFilter
43 //
44 // Description:
45 //
46 //      This function is the exception handler
47 //
48 // Return:
49 //
50 //      A status is returned for the function
51 //
52
53 ULONG
54 AFSExceptionFilter( IN CHAR *FunctionString,
55                     IN ULONG Code,
56                     IN PEXCEPTION_POINTERS ExceptPtrs)
57 {
58
59     UNREFERENCED_PARAMETER(Code);
60     PEXCEPTION_RECORD ExceptRec;
61     PCONTEXT Context;
62
63     __try
64     {
65
66         ExceptRec = ExceptPtrs->ExceptionRecord;
67
68         Context = ExceptPtrs->ContextRecord;
69
70         AFSDbgTrace(( 0,
71                       0,
72                       "AFSExceptionFilter (Library) - EXR %p CXR %p Function %s Code %08lX Address %p Routine %p\n",
73                       ExceptRec,
74                       Context,
75                       FunctionString,
76                       ExceptRec->ExceptionCode,
77                       ExceptRec->ExceptionAddress,
78                       (void *)AFSExceptionFilter));
79
80         DbgPrint("**** Exception Caught in AFS Redirector Library ****\n");
81
82         DbgPrint("\n\nPerform the following WnDbg Cmds:\n");
83         DbgPrint("\n\t.exr %p ;  .cxr %p\n\n", ExceptRec, Context);
84
85         DbgPrint("**** Exception Complete from AFS Redirector Library ****\n");
86
87         if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION))
88         {
89
90             KeBugCheck( (ULONG)-2);
91         }
92         else
93         {
94
95             AFSBreakPoint();
96         }
97     }
98     __except( EXCEPTION_EXECUTE_HANDLER)
99     {
100
101         NOTHING;
102     }
103
104     return EXCEPTION_EXECUTE_HANDLER;
105 }
106
107 //
108 // Function: AFSLibExAllocatePoolWithTag()
109 //
110 // Purpose: Allocate Pool Memory.  If BugCheck Exception flag
111 //          is configured on, then bugcheck the system if
112 //          a memory allocation fails.  The routine should be
113 //          used for all memory allocations that are to be freed
114 //          when the library is unloaded.  Memory allocations that
115 //          are to survive library unload and reload should be
116 //          performed using AFSExAllocatePoolWithTag() which is
117 //          provided by the AFS Framework.
118 //
119 // Parameters:
120 //                POOL_TYPE PoolType - Paged or NonPaged
121 //                SIZE_T NumberOfBytes - requested allocation size
122 //                ULONG  Tag - Pool Allocation Tag to be applied for tracking
123 //
124 // Return:
125 //                void * - the memory allocation
126 //
127
128 void *
129 AFSLibExAllocatePoolWithTag( IN POOL_TYPE  PoolType,
130                              IN SIZE_T  NumberOfBytes,
131                              IN ULONG  Tag)
132 {
133
134     void *pBuffer = NULL;
135
136     pBuffer = ExAllocatePoolWithTag( PoolType,
137                                      NumberOfBytes,
138                                      Tag);
139
140     if( pBuffer == NULL)
141     {
142
143         if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION))
144         {
145
146             KeBugCheck( (ULONG)-2);
147         }
148         else
149         {
150
151             AFSDbgTrace(( 0,
152                           0,
153                           "AFSLibExAllocatePoolWithTag failure Type %08lX Size %08lX Tag %08lX %08lX\n",
154                           PoolType,
155                           NumberOfBytes,
156                           Tag,
157                           PsGetCurrentThread()));
158
159             AFSBreakPoint();
160         }
161     }
162
163     return pBuffer;
164 }
165
166 //
167 // Function: AFSAcquireExcl()
168 //
169 // Purpose: Called to acquire a resource exclusive with optional wait
170 //
171 // Parameters:
172 //                PERESOURCE Resource - Resource to acquire
173 //                BOOLEAN Wait - Whether to block
174 //
175 // Return:
176 //                BOOLEAN - Whether the mask was acquired
177 //
178
179 BOOLEAN
180 AFSAcquireExcl( IN PERESOURCE Resource,
181                 IN BOOLEAN wait)
182 {
183
184     BOOLEAN bStatus = FALSE;
185
186     //
187     // Normal kernel APCs must be disabled before calling
188     // ExAcquireResourceExclusiveLite. Otherwise a bugcheck occurs.
189     //
190
191     KeEnterCriticalRegion();
192
193     bStatus = ExAcquireResourceExclusiveLite( Resource,
194                                               wait);
195
196     if( !bStatus)
197     {
198
199         KeLeaveCriticalRegion();
200     }
201
202     return bStatus;
203 }
204
205 BOOLEAN
206 AFSAcquireSharedStarveExclusive( IN PERESOURCE Resource,
207                                  IN BOOLEAN Wait)
208 {
209
210     BOOLEAN bStatus = FALSE;
211
212     KeEnterCriticalRegion();
213
214     bStatus = ExAcquireSharedStarveExclusive( Resource,
215                                               Wait);
216
217     if( !bStatus)
218     {
219
220         KeLeaveCriticalRegion();
221     }
222
223     return bStatus;
224 }
225
226 //
227 // Function: AFSAcquireShared()
228 //
229 // Purpose: Called to acquire a resource shared with optional wait
230 //
231 // Parameters:
232 //                PERESOURCE Resource - Resource to acquire
233 //                BOOLEAN Wait - Whether to block
234 //
235 // Return:
236 //                BOOLEAN - Whether the mask was acquired
237 //
238
239 BOOLEAN
240 AFSAcquireShared( IN PERESOURCE Resource,
241                   IN BOOLEAN wait)
242 {
243
244     BOOLEAN bStatus = FALSE;
245
246     KeEnterCriticalRegion();
247
248     bStatus = ExAcquireResourceSharedLite( Resource,
249                                            wait);
250
251     if( !bStatus)
252     {
253
254         KeLeaveCriticalRegion();
255     }
256
257     return bStatus;
258 }
259
260 //
261 // Function: AFSReleaseResource()
262 //
263 // Purpose: Called to release a resource
264 //
265 // Parameters:
266 //                PERESOURCE Resource - Resource to release
267 //
268 // Return:
269 //                None
270 //
271
272 void
273 AFSReleaseResource( IN PERESOURCE Resource)
274 {
275
276     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
277                   AFS_TRACE_LEVEL_VERBOSE,
278                   "AFSReleaseResource Releasing lock %p Thread %08lX\n",
279                   Resource,
280                   PsGetCurrentThread()));
281
282     ExReleaseResourceLite( Resource);
283
284     KeLeaveCriticalRegion();
285
286     return;
287 }
288
289 void
290 AFSConvertToShared( IN PERESOURCE Resource)
291 {
292
293     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
294                   AFS_TRACE_LEVEL_VERBOSE,
295                   "AFSConvertToShared Converting lock %p Thread %08lX\n",
296                   Resource,
297                   PsGetCurrentThread()));
298
299     ExConvertExclusiveToSharedLite( Resource);
300
301     return;
302 }
303
304 //
305 // Function: AFSCompleteRequest
306 //
307 // Description:
308 //
309 //      This function completes irps
310 //
311 // Return:
312 //
313 //      A status is returned for the function
314 //
315
316 void
317 AFSCompleteRequest( IN PIRP Irp,
318                     IN ULONG Status)
319 {
320
321     Irp->IoStatus.Status = Status;
322
323     IoCompleteRequest( Irp,
324                        IO_NO_INCREMENT);
325
326     return;
327 }
328
329 //
330 // Function: AFSGenerateCRC
331 //
332 // Description:
333 //
334 //      Given a device and filename this function generates a CRC
335 //
336 // Return:
337 //
338 //      A status is returned for the function
339 //
340
341 ULONG
342 AFSGenerateCRC( IN PUNICODE_STRING FileName,
343                 IN BOOLEAN UpperCaseName)
344 {
345
346     ULONG ulCRC = 0;
347     NTSTATUS ntStatus = STATUS_SUCCESS;
348
349     ntStatus = RtlHashUnicodeString( FileName,
350                                      UpperCaseName,
351                                      HASH_STRING_ALGORITHM_DEFAULT,
352                                      &ulCRC);
353
354     if( !NT_SUCCESS( ntStatus))
355     {
356         ulCRC = 0;
357     }
358
359     return ulCRC;
360 }
361
362 void *
363 AFSLockSystemBuffer( IN PIRP Irp,
364                      IN ULONG Length)
365 {
366
367     void *pAddress = NULL;
368
369     if( Irp->MdlAddress != NULL)
370     {
371
372         pAddress = MmGetSystemAddressForMdlSafe( Irp->MdlAddress,
373                                                  NormalPagePriority);
374     }
375     else if( Irp->AssociatedIrp.SystemBuffer != NULL)
376     {
377
378         pAddress = Irp->AssociatedIrp.SystemBuffer;
379     }
380     else if( Irp->UserBuffer != NULL)
381     {
382
383         Irp->MdlAddress = IoAllocateMdl( Irp->UserBuffer,
384                                          Length,
385                                          FALSE,
386                                          FALSE,
387                                          Irp);
388
389         if( Irp->MdlAddress != NULL)
390         {
391
392             //
393             //  Lock the new Mdl in memory.
394             //
395
396             __try
397             {
398                 PIO_STACK_LOCATION pIoStack;
399                 pIoStack = IoGetCurrentIrpStackLocation( Irp);
400
401
402                 MmProbeAndLockPages( Irp->MdlAddress, KernelMode,
403                                      (pIoStack->MajorFunction == IRP_MJ_READ) ? IoWriteAccess : IoReadAccess);
404
405                 pAddress = MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority );
406
407             }
408             __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
409             {
410
411                 AFSDumpTraceFilesFnc();
412
413                 IoFreeMdl( Irp->MdlAddress );
414                 Irp->MdlAddress = NULL;
415                 pAddress = NULL;
416             }
417         }
418     }
419
420     return pAddress;
421 }
422
423 void *
424 AFSLockUserBuffer( IN void *UserBuffer,
425                    IN ULONG BufferLength,
426                    OUT MDL ** Mdl)
427 {
428
429     NTSTATUS ntStatus = STATUS_SUCCESS;
430     void *pAddress = NULL;
431     MDL *pMdl = NULL;
432
433     __Enter
434     {
435
436         pMdl = IoAllocateMdl( UserBuffer,
437                               BufferLength,
438                               FALSE,
439                               FALSE,
440                               NULL);
441
442             if( pMdl == NULL)
443             {
444
445                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
446             }
447
448         //
449         //  Lock the new Mdl in memory.
450         //
451
452         __try
453         {
454
455             MmProbeAndLockPages( pMdl,
456                                  KernelMode,
457                                  IoWriteAccess);
458
459             pAddress = MmGetSystemAddressForMdlSafe( pMdl,
460                                                      NormalPagePriority);
461         }
462         __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
463         {
464
465             AFSDumpTraceFilesFnc();
466
467             IoFreeMdl( pMdl);
468             pMdl = NULL;
469             pAddress = NULL;
470         }
471
472         if( pMdl != NULL)
473         {
474
475             *Mdl = pMdl;
476         }
477
478 try_exit:
479
480         NOTHING;
481     }
482
483     return pAddress;
484 }
485
486 void *
487 AFSMapToService( IN PIRP Irp,
488                  IN ULONG ByteCount)
489 {
490
491     NTSTATUS ntStatus = STATUS_SUCCESS;
492     void *pMappedBuffer = NULL;
493     AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
494     KAPC stApcState;
495
496     __Enter
497     {
498
499         if( pDevExt->Specific.Control.ServiceProcess == NULL)
500         {
501
502             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
503         }
504
505         if( Irp->MdlAddress == NULL)
506         {
507
508             if( AFSLockSystemBuffer( Irp,
509                                      ByteCount) == NULL)
510             {
511
512                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
513             }
514         }
515
516         //
517         // Attach to the service process for mapping
518         //
519
520         KeStackAttachProcess( pDevExt->Specific.Control.ServiceProcess,
521                               (PRKAPC_STATE)&stApcState);
522
523         pMappedBuffer = MmMapLockedPagesSpecifyCache( Irp->MdlAddress,
524                                                       UserMode,
525                                                       MmCached,
526                                                       NULL,
527                                                       FALSE,
528                                                       NormalPagePriority);
529
530         KeUnstackDetachProcess( (PRKAPC_STATE)&stApcState);
531
532 try_exit:
533
534         NOTHING;
535     }
536
537     return pMappedBuffer;
538 }
539
540 NTSTATUS
541 AFSUnmapServiceMappedBuffer( IN void *MappedBuffer,
542                              IN PMDL Mdl)
543 {
544
545     NTSTATUS ntStatus = STATUS_SUCCESS;
546     AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
547     KAPC stApcState;
548
549     __Enter
550     {
551
552         if( pDevExt->Specific.Control.ServiceProcess == NULL)
553         {
554
555             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
556         }
557
558         if( Mdl != NULL)
559         {
560
561             //
562             // Attach to the service process for mapping
563             //
564
565             KeStackAttachProcess( pDevExt->Specific.Control.ServiceProcess,
566                                   (PRKAPC_STATE)&stApcState);
567
568             MmUnmapLockedPages( MappedBuffer,
569                                 Mdl);
570
571             KeUnstackDetachProcess( (PRKAPC_STATE)&stApcState);
572         }
573
574 try_exit:
575
576         NOTHING;
577     }
578
579     return ntStatus;
580 }
581
582 NTSTATUS
583 AFSInitializeLibraryDevice()
584 {
585
586     NTSTATUS ntStatus = STATUS_SUCCESS;
587     AFSDeviceExt *pDeviceExt = NULL;
588
589     __Enter
590     {
591
592         pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
593
594         //
595         // The PIOCtl file name
596         //
597
598         RtlInitUnicodeString( &AFSPIOCtlName,
599                               AFS_PIOCTL_FILE_INTERFACE_NAME);
600
601         //
602         // And the global root share name
603         //
604
605         RtlInitUnicodeString( &AFSGlobalRootName,
606                               AFS_GLOBAL_ROOT_SHARE_NAME);
607
608     }
609
610     return ntStatus;
611 }
612
613 NTSTATUS
614 AFSRemoveLibraryDevice()
615 {
616
617     NTSTATUS ntStatus = STATUS_SUCCESS;
618
619     __Enter
620     {
621
622     }
623
624     return ntStatus;
625 }
626
627 NTSTATUS
628 AFSDefaultDispatch( IN PDEVICE_OBJECT DeviceObject,
629                     IN PIRP Irp)
630 {
631
632     UNREFERENCED_PARAMETER(DeviceObject);
633     NTSTATUS            ntStatus = STATUS_INVALID_DEVICE_REQUEST;
634
635     AFSCompleteRequest( Irp,
636                         ntStatus);
637
638     return ntStatus;
639 }
640
641 NTSTATUS
642 AFSInitializeGlobalDirectoryEntries()
643 {
644
645     NTSTATUS ntStatus = STATUS_SUCCESS;
646     AFSDirectoryCB *pDirNode = NULL;
647     ULONG ulEntryLength = 0;
648     AFSObjectInfoCB *pObjectInfoCB = NULL;
649     AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
650     LONG lCount;
651
652     __Enter
653     {
654
655         //
656         // Initialize the global . entry
657         //
658
659         pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
660                                                0);
661
662         if( pObjectInfoCB == NULL)
663         {
664
665             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
666                           AFS_TRACE_LEVEL_ERROR,
667                           "AFSInitializeGlobalDirectory AFSAllocateObjectInfo failure %08lX\n",
668                           ntStatus));
669
670             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
671         }
672
673         lCount = AFSObjectInfoIncrement( pObjectInfoCB,
674                                          AFS_OBJECT_REFERENCE_GLOBAL);
675
676         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
677                       AFS_TRACE_LEVEL_VERBOSE,
678                       "AFSInitializeGlobalDirectoryEntries Increment count on object %p Cnt %d\n",
679                       pObjectInfoCB,
680                       lCount));
681
682         ntStatus = STATUS_SUCCESS;
683
684         ulEntryLength = sizeof( AFSDirectoryCB) +
685                                      sizeof( WCHAR);
686
687         pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
688                                                                   ulEntryLength,
689                                                                   AFS_DIR_ENTRY_TAG);
690
691         if( pDirNode == NULL)
692         {
693
694             AFSDeleteObjectInfo( &pObjectInfoCB);
695
696             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
697                           AFS_TRACE_LEVEL_ERROR,
698                           "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_TAG allocation failure\n"));
699
700             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
701         }
702
703         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
704                       AFS_TRACE_LEVEL_VERBOSE,
705                       "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_TAG allocated %p\n",
706                       pDirNode));
707
708         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
709                                                                                    sizeof( AFSNonPagedDirectoryCB),
710                                                                                    AFS_DIR_ENTRY_NP_TAG);
711
712         if( pNonPagedDirEntry == NULL)
713         {
714
715             ExFreePool( pDirNode);
716
717             AFSDeleteObjectInfo( &pObjectInfoCB);
718
719             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
720                           AFS_TRACE_LEVEL_ERROR,
721                           "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_NP_TAG allocation failure\n"));
722
723             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
724         }
725
726         RtlZeroMemory( pDirNode,
727                        ulEntryLength);
728
729         RtlZeroMemory( pNonPagedDirEntry,
730                        sizeof( AFSNonPagedDirectoryCB));
731
732         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
733
734         pDirNode->NonPaged = pNonPagedDirEntry;
735
736         pDirNode->ObjectInformation = pObjectInfoCB;
737
738         //
739         // Set valid entry
740         //
741
742         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE | AFS_DIR_ENTRY_FAKE | AFS_DIR_ENTRY_VALID);
743
744         pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_DOT_INDEX;
745
746         //
747         // Setup the names in the entry
748         //
749
750         pDirNode->NameInformation.FileName.Length = sizeof( WCHAR);
751
752         pDirNode->NameInformation.FileName.MaximumLength = sizeof( WCHAR);
753
754         pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
755
756         pDirNode->NameInformation.FileName.Buffer[ 0] = L'.';
757
758         //
759         // Populate the rest of the data
760         //
761
762         pObjectInfoCB->FileType = AFS_FILE_TYPE_DIRECTORY;
763
764         pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
765
766         AFSGlobalDotDirEntry = pDirNode;
767
768         //
769         // Now the .. entry
770         //
771
772         pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
773                                                0);
774
775         if( pObjectInfoCB == NULL)
776         {
777
778             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
779                           AFS_TRACE_LEVEL_ERROR,
780                           "AFSInitializeGlobalDirectory AFSAllocateObjectInfo (2) failure %08lX\n",
781                           ntStatus));
782
783             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
784         }
785
786         lCount = AFSObjectInfoIncrement( pObjectInfoCB,
787                                          AFS_OBJECT_REFERENCE_GLOBAL);
788
789         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
790                       AFS_TRACE_LEVEL_VERBOSE,
791                       "AFSInitializeGlobalDirectoryEntries Increment count on object %p Cnt %d\n",
792                       pObjectInfoCB,
793                       lCount));
794
795         ntStatus = STATUS_SUCCESS;
796
797         ulEntryLength = sizeof( AFSDirectoryCB) +
798                                      ( 2 * sizeof( WCHAR));
799
800         pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
801                                                                   ulEntryLength,
802                                                                   AFS_DIR_ENTRY_TAG);
803
804         if( pDirNode == NULL)
805         {
806
807             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
808                           AFS_TRACE_LEVEL_ERROR,
809                           "AFSInitializeGlobalDirectoryEntries AFS_DIR_ENTRY_TAG allocation failure\n"));
810
811             AFSDeleteObjectInfo( &pObjectInfoCB);
812
813             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
814         }
815
816         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
817                       AFS_TRACE_LEVEL_VERBOSE,
818                       "AFSInitializeGlobalDirectoryEntries AFS_DIR_ENTRY_TAG allocated %p\n",
819                       pDirNode));
820
821         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
822                                                                                    sizeof( AFSNonPagedDirectoryCB),
823                                                                                    AFS_DIR_ENTRY_NP_TAG);
824
825         if( pNonPagedDirEntry == NULL)
826         {
827
828             ExFreePool( pDirNode);
829
830             AFSDeleteObjectInfo( &pObjectInfoCB);
831
832             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
833         }
834
835         RtlZeroMemory( pDirNode,
836                        ulEntryLength);
837
838         RtlZeroMemory( pNonPagedDirEntry,
839                        sizeof( AFSNonPagedDirectoryCB));
840
841         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
842
843         pDirNode->NonPaged = pNonPagedDirEntry;
844
845         pDirNode->ObjectInformation = pObjectInfoCB;
846
847         //
848         // Set valid entry
849         //
850
851         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE | AFS_DIR_ENTRY_FAKE | AFS_DIR_ENTRY_VALID);
852
853         pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX;
854
855         //
856         // Setup the names in the entry
857         //
858
859         pDirNode->NameInformation.FileName.Length = 2 * sizeof( WCHAR);
860
861         pDirNode->NameInformation.FileName.MaximumLength = 2 * sizeof( WCHAR);
862
863         pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
864
865         pDirNode->NameInformation.FileName.Buffer[ 0] = L'.';
866
867         pDirNode->NameInformation.FileName.Buffer[ 1] = L'.';
868
869         //
870         // Populate the rest of the data
871         //
872
873         pObjectInfoCB->FileType = AFS_FILE_TYPE_DIRECTORY;
874
875         pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
876
877         AFSGlobalDotDotDirEntry = pDirNode;
878
879 try_exit:
880
881         if( !NT_SUCCESS( ntStatus))
882         {
883
884             if( AFSGlobalDotDirEntry != NULL)
885             {
886
887                 AFSDeleteObjectInfo( &AFSGlobalDotDirEntry->ObjectInformation);
888
889                 ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
890
891                 ExFreePool( AFSGlobalDotDirEntry->NonPaged);
892
893                 ExFreePool( AFSGlobalDotDirEntry);
894
895                 AFSGlobalDotDirEntry = NULL;
896             }
897
898             if( AFSGlobalDotDotDirEntry != NULL)
899             {
900
901                 AFSDeleteObjectInfo( &AFSGlobalDotDotDirEntry->ObjectInformation);
902
903                 ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
904
905                 ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
906
907                 ExFreePool( AFSGlobalDotDotDirEntry);
908
909                 AFSGlobalDotDotDirEntry = NULL;
910             }
911         }
912     }
913
914     return ntStatus;
915 }
916
917 AFSDirectoryCB *
918 AFSInitDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
919                  IN PUNICODE_STRING FileName,
920                  IN PUNICODE_STRING TargetName,
921                  IN AFSDirEnumEntry *DirEnumEntry,
922                  IN ULONG FileIndex)
923 {
924
925     AFSDirectoryCB *pDirNode = NULL;
926     NTSTATUS ntStatus = STATUS_SUCCESS;
927     ULONG ulEntryLength = 0;
928     AFSObjectInfoCB *pObjectInfoCB = NULL;
929     BOOLEAN bAllocatedObjectCB = FALSE;
930     ULONGLONG ullIndex = 0;
931     AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
932     LONG lCount;
933
934     __Enter
935     {
936
937         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
938                       AFS_TRACE_LEVEL_VERBOSE,
939                       "AFSInitDirEntry Initializing entry %wZ parent FID %08lX-%08lX-%08lX-%08lX\n",
940                       FileName,
941                       ParentObjectInfo->FileId.Cell,
942                       ParentObjectInfo->FileId.Volume,
943                       ParentObjectInfo->FileId.Vnode,
944                       ParentObjectInfo->FileId.Unique));
945
946         //
947         // First thing is to locate/create our object information block
948         // for this entry
949         //
950
951         AFSAcquireExcl( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
952                         TRUE);
953
954         ullIndex = AFSCreateLowIndex( &DirEnumEntry->FileId);
955
956         ntStatus = AFSLocateHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
957                                        ullIndex,
958                                        (AFSBTreeEntry **)&pObjectInfoCB);
959
960         if( !NT_SUCCESS( ntStatus) ||
961             pObjectInfoCB == NULL)
962         {
963
964             //
965             // Allocate our object info cb
966             //
967
968             pObjectInfoCB = AFSAllocateObjectInfo( ParentObjectInfo,
969                                                    ullIndex);
970
971             if( pObjectInfoCB == NULL)
972             {
973
974                 AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
975
976                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
977             }
978
979             bAllocatedObjectCB = TRUE;
980
981             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
982                           AFS_TRACE_LEVEL_VERBOSE,
983                           "AFSInitDirEntry initialized object %p Parent Object %p for %wZ\n",
984                           pObjectInfoCB,
985                           ParentObjectInfo,
986                           FileName));
987         }
988
989         lCount = AFSObjectInfoIncrement( pObjectInfoCB,
990                                          AFS_OBJECT_REFERENCE_DIRENTRY);
991
992         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
993                       AFS_TRACE_LEVEL_VERBOSE,
994                       "AFSInitDirEntry Increment count on object %p Cnt %d\n",
995                       pObjectInfoCB,
996                       lCount));
997
998         AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
999
1000         ntStatus = STATUS_SUCCESS;
1001
1002         ulEntryLength = sizeof( AFSDirectoryCB) +
1003                                      FileName->Length;
1004
1005         if( TargetName != NULL)
1006         {
1007
1008             ulEntryLength += TargetName->Length;
1009         }
1010
1011         pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
1012                                                                ulEntryLength,
1013                                                                AFS_DIR_ENTRY_TAG);
1014
1015         if( pDirNode == NULL)
1016         {
1017
1018             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1019         }
1020
1021         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1022                       AFS_TRACE_LEVEL_VERBOSE,
1023                       "AFSInitDirEntry AFS_DIR_ENTRY_TAG allocated %p\n",
1024                       pDirNode));
1025
1026         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
1027                                                                                 sizeof( AFSNonPagedDirectoryCB),
1028                                                                                 AFS_DIR_ENTRY_NP_TAG);
1029
1030         if( pNonPagedDirEntry == NULL)
1031         {
1032
1033             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1034         }
1035
1036         RtlZeroMemory( pDirNode,
1037                        ulEntryLength);
1038
1039         RtlZeroMemory( pNonPagedDirEntry,
1040                        sizeof( AFSNonPagedDirectoryCB));
1041
1042         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
1043
1044         pDirNode->NonPaged = pNonPagedDirEntry;
1045
1046         pDirNode->ObjectInformation = pObjectInfoCB;
1047
1048         //
1049         // Set valid entry and NOT_IN_PARENT flag
1050         //
1051
1052         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1053
1054         pDirNode->FileIndex = FileIndex;
1055
1056         //
1057         // Setup the names in the entry
1058         //
1059
1060         if( FileName->Length > 0)
1061         {
1062
1063             pDirNode->NameInformation.FileName.Length = FileName->Length;
1064
1065             pDirNode->NameInformation.FileName.MaximumLength = FileName->Length;
1066
1067             pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
1068
1069             RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
1070                            FileName->Buffer,
1071                            pDirNode->NameInformation.FileName.Length);
1072
1073             //
1074             // Create a CRC for the file
1075             //
1076
1077             pDirNode->CaseSensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1078                                                                          FALSE);
1079
1080             pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1081                                                                            TRUE);
1082         }
1083
1084         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1085                       AFS_TRACE_LEVEL_VERBOSE,
1086                       "AFSInitDirEntry Initialized DE %p for %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1087                       pDirNode,
1088                       FileName,
1089                       ParentObjectInfo->FileId.Cell,
1090                       ParentObjectInfo->FileId.Volume,
1091                       ParentObjectInfo->FileId.Vnode,
1092                       ParentObjectInfo->FileId.Unique));
1093
1094         if( TargetName != NULL &&
1095             TargetName->Length > 0)
1096         {
1097
1098             pDirNode->NameInformation.TargetName.Length = TargetName->Length;
1099
1100             pDirNode->NameInformation.TargetName.MaximumLength = pDirNode->NameInformation.TargetName.Length;
1101
1102             pDirNode->NameInformation.TargetName.Buffer = (WCHAR *)((char *)pDirNode +
1103                                                                             sizeof( AFSDirectoryCB) +
1104                                                                             pDirNode->NameInformation.FileName.Length);
1105
1106             RtlCopyMemory( pDirNode->NameInformation.TargetName.Buffer,
1107                            TargetName->Buffer,
1108                            pDirNode->NameInformation.TargetName.Length);
1109         }
1110
1111         //
1112         // If we allocated the object information cb then update the information
1113         //
1114
1115         if( bAllocatedObjectCB)
1116         {
1117
1118             //
1119             // Populate the rest of the data
1120             //
1121
1122             pObjectInfoCB->FileId = DirEnumEntry->FileId;
1123
1124             pObjectInfoCB->TargetFileId = DirEnumEntry->TargetFileId;
1125
1126             pObjectInfoCB->FileType = DirEnumEntry->FileType;
1127
1128             pObjectInfoCB->CreationTime = DirEnumEntry->CreationTime;
1129
1130             pObjectInfoCB->LastAccessTime = DirEnumEntry->LastAccessTime;
1131
1132             pObjectInfoCB->LastWriteTime = DirEnumEntry->LastWriteTime;
1133
1134             pObjectInfoCB->ChangeTime = DirEnumEntry->ChangeTime;
1135
1136             pObjectInfoCB->EndOfFile = DirEnumEntry->EndOfFile;
1137
1138             pObjectInfoCB->AllocationSize = DirEnumEntry->AllocationSize;
1139
1140             pObjectInfoCB->FileAttributes = DirEnumEntry->FileAttributes;
1141
1142             if( pObjectInfoCB->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1143                 pObjectInfoCB->FileType == AFS_FILE_TYPE_DFSLINK)
1144             {
1145
1146                 pObjectInfoCB->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1147             }
1148
1149             if (pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK)
1150             {
1151
1152                 if ( pObjectInfoCB->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1153                 {
1154
1155                     pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1156                 }
1157                 else
1158                 {
1159
1160                     pObjectInfoCB->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1161                 }
1162             }
1163
1164             pObjectInfoCB->EaSize = DirEnumEntry->EaSize;
1165
1166             //
1167             // Check for the case where we have a filetype of SymLink but both the TargetFid and the
1168             // TargetName are empty. In this case set the filetype to zero so we evaluate it later in
1169             // the code
1170             //
1171
1172             if( pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK &&
1173                 pObjectInfoCB->TargetFileId.Vnode == 0 &&
1174                 pObjectInfoCB->TargetFileId.Unique == 0 &&
1175                 pDirNode->NameInformation.TargetName.Length == 0)
1176             {
1177
1178                 //
1179                 // This will ensure we perform a validation on the node
1180                 //
1181
1182                 pObjectInfoCB->FileType = AFS_FILE_TYPE_UNKNOWN;
1183             }
1184
1185             if( pObjectInfoCB->FileType == AFS_FILE_TYPE_UNKNOWN)
1186             {
1187
1188                 SetFlag( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
1189             }
1190         }
1191
1192         //
1193         // Object specific information
1194         //
1195
1196         pObjectInfoCB->Links = DirEnumEntry->Links;
1197
1198         pObjectInfoCB->Expiration = DirEnumEntry->Expiration;
1199
1200         pObjectInfoCB->DataVersion = DirEnumEntry->DataVersion;
1201
1202 try_exit:
1203
1204         if( !NT_SUCCESS( ntStatus))
1205         {
1206
1207             if( pNonPagedDirEntry != NULL)
1208             {
1209
1210                 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
1211
1212                 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
1213             }
1214
1215             if( pDirNode != NULL)
1216             {
1217
1218                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1219                               AFS_TRACE_LEVEL_VERBOSE,
1220                               "AFSInitDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
1221                               pDirNode));
1222
1223                 AFSExFreePoolWithTag( pDirNode, AFS_DIR_ENTRY_TAG);
1224
1225                 pDirNode = NULL;
1226             }
1227
1228             //
1229             // Dereference our object info block if we have one
1230             //
1231
1232             if( pObjectInfoCB != NULL)
1233             {
1234
1235                 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
1236                                                  AFS_OBJECT_REFERENCE_DIRENTRY);
1237
1238                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1239                               AFS_TRACE_LEVEL_VERBOSE,
1240                               "AFSInitDirEntry Decrement count on object %p Cnt %d\n",
1241                               pObjectInfoCB,
1242                               lCount));
1243
1244                 if( bAllocatedObjectCB)
1245                 {
1246
1247                     ASSERT( pObjectInfoCB->ObjectReferenceCount == 0);
1248
1249                     AFSDeleteObjectInfo( &pObjectInfoCB);
1250                 }
1251             }
1252         }
1253     }
1254
1255     return pDirNode;
1256 }
1257
1258 BOOLEAN
1259 AFSCheckForReadOnlyAccess( IN ACCESS_MASK DesiredAccess,
1260                            IN BOOLEAN DirectoryEntry)
1261 {
1262
1263     BOOLEAN bReturn = TRUE;
1264     ACCESS_MASK stAccessMask = 0;
1265
1266     //
1267     // Get rid of anything we don't know about
1268     //
1269
1270     DesiredAccess = (DesiredAccess   &
1271                           ( DELETE |
1272                             READ_CONTROL |
1273                             WRITE_OWNER |
1274                             WRITE_DAC |
1275                             SYNCHRONIZE |
1276                             ACCESS_SYSTEM_SECURITY |
1277                             FILE_WRITE_DATA |
1278                             FILE_READ_EA |
1279                             FILE_WRITE_EA |
1280                             FILE_READ_ATTRIBUTES |
1281                             FILE_WRITE_ATTRIBUTES |
1282                             FILE_LIST_DIRECTORY |
1283                             FILE_TRAVERSE |
1284                             FILE_DELETE_CHILD |
1285                             FILE_APPEND_DATA));
1286
1287     //
1288     // Our 'read only' access mask. These are the accesses we will
1289     // allow for a read only file
1290     //
1291
1292     stAccessMask = DELETE |
1293                         READ_CONTROL |
1294                         WRITE_OWNER |
1295                         WRITE_DAC |
1296                         SYNCHRONIZE |
1297                         ACCESS_SYSTEM_SECURITY |
1298                         FILE_READ_DATA |
1299                         FILE_READ_EA |
1300                         FILE_WRITE_EA |
1301                         FILE_READ_ATTRIBUTES |
1302                         FILE_WRITE_ATTRIBUTES |
1303                         FILE_EXECUTE |
1304                         FILE_LIST_DIRECTORY |
1305                         FILE_TRAVERSE;
1306
1307     //
1308     // For a directory, add in the directory specific accesses
1309     //
1310
1311     if( DirectoryEntry)
1312     {
1313
1314         stAccessMask |= FILE_ADD_SUBDIRECTORY |
1315                                 FILE_ADD_FILE |
1316                                 FILE_DELETE_CHILD;
1317     }
1318
1319     if( FlagOn( DesiredAccess, ~stAccessMask))
1320     {
1321
1322         //
1323         // A write access is set ...
1324         //
1325
1326         bReturn = FALSE;
1327     }
1328
1329     return bReturn;
1330 }
1331
1332 NTSTATUS
1333 AFSEvaluateNode( IN GUID *AuthGroup,
1334                  IN AFSDirectoryCB *DirEntry)
1335 {
1336
1337     NTSTATUS ntStatus = STATUS_SUCCESS;
1338     AFSDirEnumEntry *pDirEntry = NULL;
1339     UNICODE_STRING uniTargetName;
1340
1341     __Enter
1342     {
1343
1344         ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1345                                           AuthGroup,
1346                                           FALSE,
1347                                           &pDirEntry);
1348
1349         if( !NT_SUCCESS( ntStatus))
1350         {
1351
1352             try_return( ntStatus);
1353         }
1354
1355         DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1356
1357         DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1358
1359         DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1360
1361         DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1362
1363         DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1364
1365         DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1366
1367         DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1368
1369         DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1370
1371         DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1372
1373         DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1374
1375         DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1376
1377         if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1378             pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1379         {
1380
1381             DirEntry->ObjectInformation->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1382         }
1383
1384         if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK)
1385         {
1386
1387             if ( DirEntry->ObjectInformation->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1388             {
1389
1390                 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1391             }
1392             else
1393             {
1394
1395                 DirEntry->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1396             }
1397         }
1398
1399         DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1400
1401         DirEntry->ObjectInformation->Links = pDirEntry->Links;
1402
1403         //
1404         // If we have a target name then see if it needs updating ...
1405         //
1406
1407         if( pDirEntry->TargetNameLength > 0)
1408         {
1409
1410             //
1411             // Update the target name information if needed
1412             //
1413
1414             uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1415
1416             uniTargetName.MaximumLength = uniTargetName.Length;
1417
1418             uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1419
1420             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1421                             TRUE);
1422
1423             if( DirEntry->NameInformation.TargetName.Length == 0 ||
1424                 RtlCompareUnicodeString( &uniTargetName,
1425                                          &DirEntry->NameInformation.TargetName,
1426                                          TRUE) != 0)
1427             {
1428
1429                 //
1430                 // Update the target name
1431                 //
1432
1433                 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1434                                                 &DirEntry->Flags,
1435                                                 uniTargetName.Buffer,
1436                                                 uniTargetName.Length);
1437
1438                 if( !NT_SUCCESS( ntStatus))
1439                 {
1440
1441                     AFSReleaseResource( &DirEntry->NonPaged->Lock);
1442
1443                     try_return( ntStatus);
1444                 }
1445             }
1446
1447             AFSReleaseResource( &DirEntry->NonPaged->Lock);
1448         }
1449
1450 try_exit:
1451
1452         if( pDirEntry != NULL)
1453         {
1454
1455             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
1456         }
1457     }
1458
1459     return ntStatus;
1460 }
1461
1462 NTSTATUS
1463 AFSValidateSymLink( IN GUID *AuthGroup,
1464                     IN AFSDirectoryCB *DirEntry)
1465 {
1466
1467     NTSTATUS ntStatus = STATUS_SUCCESS;
1468     AFSDirEnumEntry *pDirEntry = NULL;
1469     UNICODE_STRING uniTargetName;
1470
1471     __Enter
1472     {
1473
1474         ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1475                                           AuthGroup,
1476                                           FALSE,
1477                                           &pDirEntry);
1478
1479         if( !NT_SUCCESS( ntStatus))
1480         {
1481
1482             try_return( ntStatus);
1483         }
1484
1485         if( pDirEntry->FileType == AFS_FILE_TYPE_UNKNOWN ||
1486             pDirEntry->FileType == AFS_FILE_TYPE_INVALID)
1487         {
1488
1489             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1490                           AFS_TRACE_LEVEL_VERBOSE_2,
1491                           "AFSValidateSymLink Invalid type Status %08lX\n",
1492                           STATUS_OBJECT_NAME_NOT_FOUND));
1493
1494             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
1495         }
1496
1497         DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1498
1499         DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1500
1501         DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1502
1503         //
1504         // Update the target name information if needed
1505         //
1506
1507         uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1508
1509         uniTargetName.MaximumLength = uniTargetName.Length;
1510
1511         uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1512
1513         if( uniTargetName.Length > 0)
1514         {
1515
1516             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1517                             TRUE);
1518
1519             if( DirEntry->NameInformation.TargetName.Length == 0 ||
1520                 RtlCompareUnicodeString( &uniTargetName,
1521                                          &DirEntry->NameInformation.TargetName,
1522                                          TRUE) != 0)
1523             {
1524
1525                 //
1526                 // Update the target name
1527                 //
1528
1529                 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1530                                                 &DirEntry->Flags,
1531                                                 uniTargetName.Buffer,
1532                                                 uniTargetName.Length);
1533
1534                 if( !NT_SUCCESS( ntStatus))
1535                 {
1536
1537                     AFSReleaseResource( &DirEntry->NonPaged->Lock);
1538
1539                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1540                 }
1541             }
1542
1543             AFSReleaseResource( &DirEntry->NonPaged->Lock);
1544         }
1545
1546         //
1547         // If the FileType is the same then nothing to do since it IS
1548         // a SymLink
1549         //
1550
1551         if( pDirEntry->FileType == DirEntry->ObjectInformation->FileType)
1552         {
1553
1554             ASSERT( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK);
1555
1556             try_return( ntStatus = STATUS_SUCCESS);
1557         }
1558
1559         DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1560
1561         DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1562
1563         DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1564
1565         DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1566
1567         DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1568
1569         DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1570
1571         DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1572
1573         DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1574
1575         if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1576             pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1577         {
1578
1579             DirEntry->ObjectInformation->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1580         }
1581
1582         if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK)
1583         {
1584
1585             if ( DirEntry->ObjectInformation->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1586             {
1587
1588                 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1589             }
1590             else
1591             {
1592
1593                 DirEntry->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1594             }
1595         }
1596
1597         DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1598
1599         DirEntry->ObjectInformation->Links = pDirEntry->Links;
1600
1601 try_exit:
1602
1603         if( pDirEntry != NULL)
1604         {
1605
1606             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
1607         }
1608     }
1609
1610     return ntStatus;
1611 }
1612
1613 NTSTATUS
1614 AFSInvalidateObject( IN OUT AFSObjectInfoCB **ppObjectInfo,
1615                      IN     ULONG Reason)
1616 {
1617
1618     NTSTATUS ntStatus = STATUS_SUCCESS;
1619     IO_STATUS_BLOCK stIoStatus;
1620     ULONG ulFilter = 0;
1621     AFSObjectInfoCB * pParentObjectInfo = NULL;
1622
1623     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1624                   AFS_TRACE_LEVEL_VERBOSE,
1625                   "AFSInvalidateObject Invalidation on node type %d for fid %08lX-%08lX-%08lX-%08lX Reason %d\n",
1626                   (*ppObjectInfo)->FileType,
1627                   (*ppObjectInfo)->FileId.Cell,
1628                   (*ppObjectInfo)->FileId.Volume,
1629                   (*ppObjectInfo)->FileId.Vnode,
1630                   (*ppObjectInfo)->FileId.Unique,
1631                   Reason));
1632
1633     if ( BooleanFlagOn( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1634     {
1635
1636         pParentObjectInfo = AFSFindObjectInfo( (*ppObjectInfo)->VolumeCB,
1637                                                &(*ppObjectInfo)->ParentFileId);
1638     }
1639
1640     if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_SYMLINK ||
1641         (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DFSLINK ||
1642         (*ppObjectInfo)->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1643     {
1644         //
1645         // We only act on the mount point itself, not the target. If the
1646         // node has been deleted then mark it as such otherwise indicate
1647         // it requires verification
1648         //
1649
1650         if( Reason == AFS_INVALIDATE_DELETED)
1651         {
1652             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
1653         }
1654         else
1655         {
1656
1657             if( Reason == AFS_INVALIDATE_FLUSHED)
1658             {
1659
1660                 (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1661
1662                 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1663             }
1664
1665             (*ppObjectInfo)->Expiration.QuadPart = 0;
1666
1667             (*ppObjectInfo)->TargetFileId.Vnode = 0;
1668
1669             (*ppObjectInfo)->TargetFileId.Unique = 0;
1670
1671             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1672                           AFS_TRACE_LEVEL_VERBOSE,
1673                           "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1674                           (*ppObjectInfo)->FileId.Cell,
1675                           (*ppObjectInfo)->FileId.Volume,
1676                           (*ppObjectInfo)->FileId.Vnode,
1677                           (*ppObjectInfo)->FileId.Unique));
1678
1679             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1680         }
1681
1682         if ( pParentObjectInfo != NULL)
1683         {
1684
1685             ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1686
1687             if( Reason == AFS_INVALIDATE_CREDS)
1688             {
1689                 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1690             }
1691
1692             if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1693                 Reason == AFS_INVALIDATE_FLUSHED)
1694             {
1695                 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1696             }
1697             else
1698             {
1699                 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1700             }
1701
1702             AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1703                                             NULL,
1704                                             ulFilter,
1705                                             FILE_ACTION_MODIFIED);
1706         }
1707
1708         try_return( ntStatus);
1709     }
1710
1711     //
1712     // Depending on the reason for invalidation then perform work on the node
1713     //
1714
1715     switch( Reason)
1716     {
1717
1718     case AFS_INVALIDATE_DELETED:
1719         {
1720
1721             //
1722             // Mark this node as invalid
1723             //
1724
1725             (*ppObjectInfo)->Links = 0;
1726
1727             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_DELETED);
1728
1729             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1730                           AFS_TRACE_LEVEL_VERBOSE,
1731                           "AFSInvalidateObject Set DELETE flag on fid %08lX-%08lX-%08lX-%08lX\n",
1732                           (*ppObjectInfo)->FileId.Cell,
1733                           (*ppObjectInfo)->FileId.Volume,
1734                           (*ppObjectInfo)->FileId.Vnode,
1735                           (*ppObjectInfo)->FileId.Unique));
1736
1737             if( pParentObjectInfo != NULL)
1738             {
1739
1740                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1741                               AFS_TRACE_LEVEL_VERBOSE,
1742                               "AFSInvalidateObject Set VERIFY flag on parent fid %08lX-%08lX-%08lX-%08lX\n",
1743                               pParentObjectInfo->FileId.Cell,
1744                               pParentObjectInfo->FileId.Volume,
1745                               pParentObjectInfo->FileId.Vnode,
1746                               pParentObjectInfo->FileId.Unique));
1747
1748                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1749
1750                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1751
1752                 pParentObjectInfo->Expiration.QuadPart = 0;
1753
1754                 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1755                 {
1756                     ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1757                 }
1758                 else
1759                 {
1760                     ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1761                 }
1762
1763                 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1764                                                 NULL,
1765                                                 ulFilter,
1766                                                 FILE_ACTION_REMOVED);
1767             }
1768
1769             if( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1770                                                       Reason)))
1771             {
1772                 (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1773             }
1774
1775             break;
1776         }
1777
1778     case AFS_INVALIDATE_FLUSHED:
1779         {
1780
1781             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1782                 (*ppObjectInfo)->Fcb != NULL)
1783             {
1784
1785                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1786                               AFS_TRACE_LEVEL_VERBOSE,
1787                               "AFSInvalidateObject Flush/purge file fid %08lX-%08lX-%08lX-%08lX\n",
1788                               (*ppObjectInfo)->FileId.Cell,
1789                               (*ppObjectInfo)->FileId.Volume,
1790                               (*ppObjectInfo)->FileId.Vnode,
1791                               (*ppObjectInfo)->FileId.Unique));
1792
1793                 AFSAcquireExcl( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectResource,
1794                                 TRUE);
1795
1796                 __try
1797                 {
1798
1799                     CcFlushCache( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1800                                   NULL,
1801                                   0,
1802                                   &stIoStatus);
1803
1804                     if( !NT_SUCCESS( stIoStatus.Status))
1805                     {
1806
1807                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1808                                       AFS_TRACE_LEVEL_ERROR,
1809                                       "AFSInvalidateObject CcFlushCache failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1810                                       (*ppObjectInfo)->FileId.Cell,
1811                                       (*ppObjectInfo)->FileId.Volume,
1812                                       (*ppObjectInfo)->FileId.Vnode,
1813                                       (*ppObjectInfo)->FileId.Unique,
1814                                       stIoStatus.Status,
1815                                       stIoStatus.Information));
1816
1817                         ntStatus = stIoStatus.Status;
1818                     }
1819
1820
1821                     if ( (*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
1822                     {
1823
1824                         if ( !CcPurgeCacheSection( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1825                                                    NULL,
1826                                                    0,
1827                                                    FALSE))
1828                         {
1829
1830                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1831                                           AFS_TRACE_LEVEL_WARNING,
1832                                           "AFSInvalidateObject CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
1833                                           (*ppObjectInfo)->FileId.Cell,
1834                                           (*ppObjectInfo)->FileId.Volume,
1835                                           (*ppObjectInfo)->FileId.Vnode,
1836                                           (*ppObjectInfo)->FileId.Unique));
1837
1838                             SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1839                         }
1840                     }
1841                 }
1842                 __except( EXCEPTION_EXECUTE_HANDLER)
1843                 {
1844
1845                     ntStatus = GetExceptionCode();
1846
1847                     AFSDbgTrace(( 0,
1848                                   0,
1849                                   "EXCEPTION - AFSInvalidateObject Cc FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
1850                                   (*ppObjectInfo)->FileId.Cell,
1851                                   (*ppObjectInfo)->FileId.Volume,
1852                                   (*ppObjectInfo)->FileId.Vnode,
1853                                   (*ppObjectInfo)->FileId.Unique,
1854                                   ntStatus));
1855
1856                     SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1857                 }
1858
1859                 AFSReleaseResource( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectResource);
1860
1861                 //
1862                 // Clear out the extents
1863                 // Get rid of them (note this involves waiting
1864                 // for any writes or reads to the cache to complete)
1865                 //
1866
1867                 AFSTearDownFcbExtents( (*ppObjectInfo)->Fcb,
1868                                        NULL);
1869             }
1870
1871             (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1872
1873
1874             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE)
1875             {
1876
1877                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1878                               AFS_TRACE_LEVEL_VERBOSE,
1879                               "AFSInvalidateObject Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
1880                               (*ppObjectInfo)->FileId.Cell,
1881                               (*ppObjectInfo)->FileId.Volume,
1882                               (*ppObjectInfo)->FileId.Vnode,
1883                               (*ppObjectInfo)->FileId.Unique));
1884
1885                 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1886             }
1887
1888             // Fall through to the default processing
1889         }
1890
1891     default:
1892         {
1893
1894             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1895             {
1896                 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1897             }
1898             else
1899             {
1900                 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1901             }
1902
1903             if( Reason == AFS_INVALIDATE_CREDS)
1904             {
1905                 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1906             }
1907
1908             if( Reason == AFS_INVALIDATE_DATA_VERSION)
1909             {
1910                 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1911             }
1912             else
1913             {
1914                 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1915             }
1916
1917             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1918             {
1919
1920                 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo),
1921                                                 NULL,
1922                                                 ulFilter,
1923                                                 FILE_ACTION_MODIFIED);
1924             }
1925             else if ( pParentObjectInfo != NULL)
1926             {
1927
1928                 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1929                                                 NULL,
1930                                                 ulFilter,
1931                                                 FILE_ACTION_MODIFIED);
1932             }
1933
1934             //
1935             // Indicate this node requires re-evaluation for the remaining reasons
1936             //
1937
1938             (*ppObjectInfo)->Expiration.QuadPart = 0;
1939
1940             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1941                           AFS_TRACE_LEVEL_VERBOSE,
1942                           "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1943                           (*ppObjectInfo)->FileId.Cell,
1944                           (*ppObjectInfo)->FileId.Volume,
1945                           (*ppObjectInfo)->FileId.Vnode,
1946                           (*ppObjectInfo)->FileId.Unique));
1947
1948             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1949
1950             if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1951                 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1952                 ( Reason == AFS_INVALIDATE_CALLBACK ||
1953                   Reason == AFS_INVALIDATE_EXPIRED))
1954             {
1955                 if ( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1956                                                            AFS_INVALIDATE_DATA_VERSION)))
1957                 {
1958
1959                     (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1960                 }
1961             }
1962
1963             break;
1964         }
1965     }
1966
1967   try_exit:
1968
1969     if ( pParentObjectInfo != NULL)
1970     {
1971
1972         AFSReleaseObjectInfo( &pParentObjectInfo);
1973     }
1974
1975     return ntStatus;
1976 }
1977
1978 NTSTATUS
1979 AFSInvalidateCache( IN AFSInvalidateCacheCB *InvalidateCB)
1980 {
1981
1982     NTSTATUS ntStatus = STATUS_SUCCESS;
1983     AFSVolumeCB *pVolumeCB = NULL;
1984     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1985     ULONGLONG   ullIndex = 0;
1986     AFSObjectInfoCB *pObjectInfo = NULL;
1987     LONG lCount;
1988
1989     __Enter
1990     {
1991
1992         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1993                       AFS_TRACE_LEVEL_VERBOSE,
1994                       "AFSInvalidateCache Invalidation FID %08lX-%08lX-%08lX-%08lX Type %d WholeVolume %d Reason %d\n",
1995                       InvalidateCB->FileID.Cell,
1996                       InvalidateCB->FileID.Volume,
1997                       InvalidateCB->FileID.Vnode,
1998                       InvalidateCB->FileID.Unique,
1999                       InvalidateCB->FileType,
2000                       InvalidateCB->WholeVolume,
2001                       InvalidateCB->Reason));
2002
2003         //
2004         // Need to locate the Fcb for the directory to purge
2005         //
2006
2007         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2008                       AFS_TRACE_LEVEL_VERBOSE,
2009                       "AFSInvalidateCache Acquiring RDR VolumeTreeLock lock %p SHARED %08lX\n",
2010                       &pDevExt->Specific.RDR.VolumeTreeLock,
2011                       PsGetCurrentThread()));
2012
2013         //
2014         // Starve any exclusive waiters on this paticular call
2015         //
2016
2017         AFSAcquireSharedStarveExclusive( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2018
2019         //
2020         // Locate the volume node
2021         //
2022
2023         ullIndex = AFSCreateHighIndex( &InvalidateCB->FileID);
2024
2025         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2026                                        ullIndex,
2027                                        (AFSBTreeEntry **)&pVolumeCB);
2028
2029         if( pVolumeCB != NULL)
2030         {
2031
2032             lCount = AFSVolumeIncrement( pVolumeCB,
2033                                          AFS_VOLUME_REFERENCE_INVALIDATE);
2034
2035             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2036                           AFS_TRACE_LEVEL_VERBOSE,
2037                           "AFSInvalidateCache Increment count on volume %p Cnt %d\n",
2038                           pVolumeCB,
2039                           lCount));
2040         }
2041
2042         AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2043
2044         if( !NT_SUCCESS( ntStatus) ||
2045             pVolumeCB == NULL)
2046         {
2047
2048             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2049                           AFS_TRACE_LEVEL_WARNING,
2050                           "AFSInvalidateCache Invalidation FAILURE Unable to locate volume node FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2051                           InvalidateCB->FileID.Cell,
2052                           InvalidateCB->FileID.Volume,
2053                           InvalidateCB->FileID.Vnode,
2054                           InvalidateCB->FileID.Unique,
2055                           ntStatus));
2056
2057             try_return( ntStatus = STATUS_SUCCESS);
2058         }
2059
2060         //
2061         // If this is a whole volume invalidation then go do it now
2062         //
2063
2064         if( InvalidateCB->WholeVolume)
2065         {
2066
2067             ntStatus = AFSInvalidateVolume( pVolumeCB,
2068                                             InvalidateCB->Reason);
2069
2070             try_return( ntStatus);
2071         }
2072
2073         AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2074                           TRUE);
2075
2076         if ( AFSIsVolumeFID( &InvalidateCB->FileID))
2077         {
2078
2079             pObjectInfo = &pVolumeCB->ObjectInformation;
2080         }
2081         else
2082         {
2083
2084             ullIndex = AFSCreateLowIndex( &InvalidateCB->FileID);
2085
2086             ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2087                                            ullIndex,
2088                                            (AFSBTreeEntry **)&pObjectInfo);
2089         }
2090
2091         if( pObjectInfo != NULL)
2092         {
2093
2094             //
2095             // Reference the node so it won't be torn down
2096             //
2097
2098             lCount = AFSObjectInfoIncrement( pObjectInfo,
2099                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2100
2101             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2102                           AFS_TRACE_LEVEL_VERBOSE,
2103                           "AFSInvalidateCache Increment count on object %p Cnt %d\n",
2104                           pObjectInfo,
2105                           lCount));
2106         }
2107
2108         AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2109
2110         if( !NT_SUCCESS( ntStatus) ||
2111             pObjectInfo == NULL)
2112         {
2113
2114             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2115                           AFS_TRACE_LEVEL_VERBOSE,
2116                           "AFSInvalidateCache Invalidation FAILURE Unable to locate object FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2117                           InvalidateCB->FileID.Cell,
2118                           InvalidateCB->FileID.Volume,
2119                           InvalidateCB->FileID.Vnode,
2120                           InvalidateCB->FileID.Unique,
2121                           ntStatus));
2122
2123             try_return( ntStatus = STATUS_SUCCESS);
2124         }
2125
2126         AFSInvalidateObject( &pObjectInfo,
2127                              InvalidateCB->Reason);
2128
2129 try_exit:
2130
2131         if( pObjectInfo != NULL)
2132         {
2133
2134             lCount = AFSObjectInfoDecrement( pObjectInfo,
2135                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2136
2137             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2138                           AFS_TRACE_LEVEL_VERBOSE,
2139                           "AFSInvalidateCache Decrement count on object %p Cnt %d\n",
2140                           pObjectInfo,
2141                           lCount));
2142         }
2143
2144         if ( pVolumeCB != NULL)
2145         {
2146
2147             lCount = AFSVolumeDecrement( pVolumeCB,
2148                                          AFS_VOLUME_REFERENCE_INVALIDATE);
2149
2150             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2151                           AFS_TRACE_LEVEL_VERBOSE,
2152                           "AFSInvalidateCache Decrement count on volume %p Cnt %d\n",
2153                           pVolumeCB,
2154                           lCount));
2155         }
2156     }
2157
2158     return ntStatus;
2159 }
2160
2161 BOOLEAN
2162 AFSIsChildOfParent( IN AFSFcb *Dcb,
2163                     IN AFSFcb *Fcb)
2164 {
2165
2166     BOOLEAN bIsChild = FALSE;
2167     AFSFcb *pCurrentFcb = Fcb;
2168     AFSObjectInfoCB * pParentObjectInfo = NULL;
2169
2170     while( pCurrentFcb != NULL)
2171     {
2172
2173         if( BooleanFlagOn( pCurrentFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
2174             AFSIsEqualFID( &pCurrentFcb->ObjectInformation->ParentFileId, &Dcb->ObjectInformation->FileId))
2175         {
2176
2177             bIsChild = TRUE;
2178
2179             break;
2180         }
2181
2182         pParentObjectInfo = AFSFindObjectInfo( pCurrentFcb->ObjectInformation->VolumeCB,
2183                                                &pCurrentFcb->ObjectInformation->ParentFileId);
2184
2185         if ( pParentObjectInfo != NULL)
2186         {
2187
2188             pCurrentFcb = pParentObjectInfo->Fcb;
2189
2190             AFSReleaseObjectInfo( &pParentObjectInfo);
2191         }
2192         else
2193         {
2194
2195             pCurrentFcb = NULL;
2196         }
2197     }
2198
2199     return bIsChild;
2200 }
2201
2202 inline
2203 ULONGLONG
2204 AFSCreateHighIndex( IN AFSFileID *FileID)
2205 {
2206
2207     ULONGLONG ullIndex = 0;
2208
2209     ullIndex = (((ULONGLONG)FileID->Cell << 32) | FileID->Volume);
2210
2211     return ullIndex;
2212 }
2213
2214 inline
2215 ULONGLONG
2216 AFSCreateLowIndex( IN AFSFileID *FileID)
2217 {
2218
2219     ULONGLONG ullIndex = 0;
2220
2221     ullIndex = (((ULONGLONG)FileID->Vnode << 32) | FileID->Unique);
2222
2223     return ullIndex;
2224 }
2225
2226 BOOLEAN
2227 AFSCheckAccess( IN ACCESS_MASK DesiredAccess,
2228                 IN ACCESS_MASK GrantedAccess,
2229                 IN BOOLEAN DirectoryEntry)
2230 {
2231
2232     BOOLEAN bAccessGranted = TRUE;
2233
2234     //
2235     // Check if we are asking for read/write and granted only read only
2236     // NOTE: There will be more checks here
2237     //
2238
2239     if( !AFSCheckForReadOnlyAccess( DesiredAccess,
2240                                     DirectoryEntry) &&
2241         AFSCheckForReadOnlyAccess( GrantedAccess,
2242                                    DirectoryEntry))
2243     {
2244
2245         bAccessGranted = FALSE;
2246     }
2247
2248     return bAccessGranted;
2249 }
2250
2251 NTSTATUS
2252 AFSGetDriverStatus( IN AFSDriverStatusRespCB *DriverStatus)
2253 {
2254
2255     NTSTATUS         ntStatus = STATUS_SUCCESS;
2256     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2257
2258     //
2259     // Start with read
2260     //
2261
2262     DriverStatus->Status = AFS_DRIVER_STATUS_READY;
2263
2264     if( AFSGlobalRoot == NULL)
2265     {
2266
2267         //
2268         // We are not ready
2269         //
2270
2271         DriverStatus->Status = AFS_DRIVER_STATUS_NOT_READY;
2272     }
2273
2274     if( pControlDevExt->Specific.Control.CommServiceCB.IrpPoolControlFlag != POOL_ACTIVE)
2275     {
2276
2277         //
2278         // No service yet
2279         //
2280
2281         DriverStatus->Status = AFS_DRIVER_STATUS_NO_SERVICE;
2282     }
2283
2284     return ntStatus;
2285 }
2286
2287 NTSTATUS
2288 AFSSubstituteSysName( IN UNICODE_STRING *ComponentName,
2289                       IN UNICODE_STRING *SubstituteName,
2290                       IN ULONG StringIndex)
2291 {
2292
2293     NTSTATUS ntStatus = STATUS_SUCCESS;
2294     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2295     AFSSysNameCB    *pSysName = NULL;
2296     ERESOURCE       *pSysNameLock = NULL;
2297     ULONG            ulIndex = 1;
2298     USHORT           usIndex = 0;
2299     UNICODE_STRING   uniSysName;
2300
2301     __Enter
2302     {
2303
2304 #if defined(_WIN64)
2305
2306         if( IoIs32bitProcess( NULL))
2307         {
2308
2309             pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2310
2311             pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2312         }
2313         else
2314         {
2315
2316             pSysNameLock = &pControlDevExt->Specific.Control.SysName64ListLock;
2317
2318             pSysName = pControlDevExt->Specific.Control.SysName64ListHead;
2319         }
2320 #else
2321
2322         pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2323
2324         pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2325
2326 #endif
2327
2328         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2329                       AFS_TRACE_LEVEL_VERBOSE,
2330                       "AFSSubstituteSysName Acquiring SysName lock %p SHARED %08lX\n",
2331                       pSysNameLock,
2332                       PsGetCurrentThread()));
2333
2334         AFSAcquireShared( pSysNameLock,
2335                           TRUE);
2336
2337         //
2338         // Find where we are in the list
2339         //
2340
2341         while( pSysName != NULL &&
2342             ulIndex < StringIndex)
2343         {
2344
2345             pSysName = pSysName->fLink;
2346
2347             ulIndex++;
2348         }
2349
2350         if( pSysName == NULL)
2351         {
2352
2353             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2354                           AFS_TRACE_LEVEL_VERBOSE_2,
2355                           "AFSSubstituteSysName No sysname %wZ Status %08lX\n",
2356                           &ComponentName,
2357                           STATUS_OBJECT_NAME_NOT_FOUND));
2358
2359             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
2360         }
2361
2362         RtlInitUnicodeString( &uniSysName,
2363                               L"@SYS");
2364         //
2365         // If it is a full component of @SYS then just substitue the
2366         // name in
2367         //
2368
2369         if( RtlCompareUnicodeString( &uniSysName,
2370                                      ComponentName,
2371                                      TRUE) == 0)
2372         {
2373
2374             SubstituteName->Length = pSysName->SysName.Length;
2375             SubstituteName->MaximumLength = SubstituteName->Length;
2376
2377             SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2378                                                                         SubstituteName->Length,
2379                                                                         AFS_SUBST_BUFFER_TAG);
2380
2381             if( SubstituteName->Buffer == NULL)
2382             {
2383
2384                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2385             }
2386
2387             RtlCopyMemory( SubstituteName->Buffer,
2388                            pSysName->SysName.Buffer,
2389                            pSysName->SysName.Length);
2390         }
2391         else
2392         {
2393
2394             usIndex = 0;
2395
2396             while( ComponentName->Buffer[ usIndex] != L'@')
2397             {
2398
2399                 usIndex++;
2400             }
2401
2402             SubstituteName->Length = (usIndex * sizeof( WCHAR)) + pSysName->SysName.Length;
2403             SubstituteName->MaximumLength = SubstituteName->Length;
2404
2405             SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2406                                                                         SubstituteName->Length,
2407                                                                         AFS_SUBST_BUFFER_TAG);
2408
2409             if( SubstituteName->Buffer == NULL)
2410             {
2411
2412                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2413             }
2414
2415             RtlCopyMemory( SubstituteName->Buffer,
2416                            ComponentName->Buffer,
2417                            usIndex * sizeof( WCHAR));
2418
2419             RtlCopyMemory( &SubstituteName->Buffer[ usIndex],
2420                            pSysName->SysName.Buffer,
2421                            pSysName->SysName.Length);
2422         }
2423
2424 try_exit:
2425
2426         AFSReleaseResource( pSysNameLock);
2427     }
2428
2429     return ntStatus;
2430 }
2431
2432 NTSTATUS
2433 AFSSubstituteNameInPath( IN OUT UNICODE_STRING *FullPathName,
2434                          IN OUT UNICODE_STRING *ComponentName,
2435                          IN UNICODE_STRING *SubstituteName,
2436                          IN OUT UNICODE_STRING *RemainingPath,
2437                          IN BOOLEAN FreePathName)
2438 {
2439
2440     NTSTATUS ntStatus = STATUS_SUCCESS;
2441     UNICODE_STRING uniPathName;
2442     USHORT usPrefixNameLen = 0;
2443     SHORT  sNameLenDelta = 0;
2444
2445     __Enter
2446     {
2447
2448         //
2449         // If the passed in name can handle the additional length
2450         // then just moves things around
2451         //
2452
2453         sNameLenDelta = SubstituteName->Length - ComponentName->Length;
2454
2455         usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2456
2457         if( FullPathName->MaximumLength > FullPathName->Length + sNameLenDelta)
2458         {
2459
2460             if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2461             {
2462
2463                 RtlMoveMemory( &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + SubstituteName->Length)/sizeof( WCHAR))],
2464                                &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + ComponentName->Length)/sizeof( WCHAR))],
2465                                FullPathName->Length - usPrefixNameLen*sizeof( WCHAR) - ComponentName->Length);
2466             }
2467
2468             RtlCopyMemory( &FullPathName->Buffer[ usPrefixNameLen],
2469                            SubstituteName->Buffer,
2470                            SubstituteName->Length);
2471
2472             FullPathName->Length += sNameLenDelta;
2473
2474             ComponentName->Length += sNameLenDelta;
2475
2476             ComponentName->MaximumLength = ComponentName->Length;
2477
2478             if ( RemainingPath->Buffer)
2479             {
2480
2481                 RemainingPath->Buffer += sNameLenDelta/sizeof( WCHAR);
2482             }
2483
2484             try_return( ntStatus);
2485         }
2486
2487         //
2488         // Need to re-allocate the buffer
2489         //
2490
2491         uniPathName.Length = FullPathName->Length -
2492                                          ComponentName->Length +
2493                                          SubstituteName->Length;
2494
2495         uniPathName.MaximumLength = FullPathName->MaximumLength + PAGE_SIZE;
2496
2497         uniPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2498                                                                 uniPathName.MaximumLength,
2499                                                                 AFS_NAME_BUFFER_FOUR_TAG);
2500
2501         if( uniPathName.Buffer == NULL)
2502         {
2503
2504             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2505         }
2506
2507         usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2508
2509         usPrefixNameLen *= sizeof( WCHAR);
2510
2511         RtlZeroMemory( uniPathName.Buffer,
2512                        uniPathName.MaximumLength);
2513
2514         RtlCopyMemory( uniPathName.Buffer,
2515                        FullPathName->Buffer,
2516                        usPrefixNameLen);
2517
2518         RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen/sizeof( WCHAR))],
2519                        SubstituteName->Buffer,
2520                        SubstituteName->Length);
2521
2522         if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2523         {
2524
2525             RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen + SubstituteName->Length)/sizeof( WCHAR)],
2526                            &FullPathName->Buffer[ (usPrefixNameLen + ComponentName->Length)/sizeof( WCHAR)],
2527                            FullPathName->Length - usPrefixNameLen - ComponentName->Length);
2528         }
2529
2530         ComponentName->Buffer = uniPathName.Buffer + (ComponentName->Buffer - FullPathName->Buffer);
2531
2532         ComponentName->Length += sNameLenDelta;
2533
2534         ComponentName->MaximumLength = ComponentName->Length;
2535
2536         if ( RemainingPath->Buffer)
2537         {
2538
2539             RemainingPath->Buffer = uniPathName.Buffer
2540                 + (RemainingPath->Buffer - FullPathName->Buffer)
2541                 + sNameLenDelta/sizeof( WCHAR);
2542         }
2543
2544         if( FreePathName)
2545         {
2546             AFSExFreePoolWithTag( FullPathName->Buffer, 0);
2547         }
2548
2549         *FullPathName = uniPathName;
2550
2551 try_exit:
2552
2553         NOTHING;
2554     }
2555
2556     return ntStatus;
2557 }
2558
2559 NTSTATUS
2560 AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
2561                      IN ULONG Reason)
2562 {
2563
2564     NTSTATUS ntStatus = STATUS_SUCCESS;
2565     AFSObjectInfoCB *pCurrentObject = NULL;
2566     AFSObjectInfoCB *pNextObject = NULL;
2567     LONG lCount;
2568
2569     __Enter
2570     {
2571
2572         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2573                       AFS_TRACE_LEVEL_VERBOSE,
2574                       "AFSInvalidateVolume Invalidate volume fid %08lX-%08lX-%08lX-%08lX Reason %08lX\n",
2575                       VolumeCB->ObjectInformation.FileId.Cell,
2576                       VolumeCB->ObjectInformation.FileId.Volume,
2577                       VolumeCB->ObjectInformation.FileId.Vnode,
2578                       VolumeCB->ObjectInformation.FileId.Unique,
2579                       Reason));
2580
2581         //
2582         // Depending on the reason for invalidation then perform work on the node
2583         //
2584
2585         switch( Reason)
2586         {
2587
2588             case AFS_INVALIDATE_DELETED:
2589             {
2590
2591                 //
2592                 // Mark this volume as invalid
2593                 //
2594
2595                 SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
2596
2597                 SetFlag( VolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE);
2598
2599                 break;
2600             }
2601         }
2602
2603         //
2604         // Invalidate the volume root directory
2605         //
2606
2607         pCurrentObject = &VolumeCB->ObjectInformation;
2608
2609         if ( pCurrentObject )
2610         {
2611
2612             lCount = AFSObjectInfoIncrement( pCurrentObject,
2613                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2614
2615             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2616                           AFS_TRACE_LEVEL_VERBOSE,
2617                           "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2618                           pCurrentObject,
2619                           lCount));
2620
2621             AFSInvalidateObject( &pCurrentObject,
2622                                  Reason);
2623
2624             if ( pCurrentObject)
2625             {
2626
2627                 lCount = AFSObjectInfoDecrement( pCurrentObject,
2628                                                  AFS_OBJECT_REFERENCE_INVALIDATION);
2629
2630                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2631                               AFS_TRACE_LEVEL_VERBOSE,
2632                               "AFSInvalidateVolumeObjects Decrement count on object %p Cnt %d\n",
2633                               pCurrentObject,
2634                               lCount));
2635             }
2636         }
2637
2638         //
2639         // Apply invalidation to all other volume objects
2640         //
2641
2642         AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2643                           TRUE);
2644
2645         pCurrentObject = VolumeCB->ObjectInfoListHead;
2646
2647         if ( pCurrentObject)
2648         {
2649
2650             //
2651             // Reference the node so it won't be torn down
2652             //
2653
2654             lCount = AFSObjectInfoIncrement( pCurrentObject,
2655                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2656
2657             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2658                           AFS_TRACE_LEVEL_VERBOSE,
2659                           "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2660                           pCurrentObject,
2661                           lCount));
2662         }
2663
2664         while( pCurrentObject != NULL)
2665         {
2666
2667             pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2668
2669             if ( pNextObject)
2670             {
2671
2672                 //
2673                 // Reference the node so it won't be torn down
2674                 //
2675
2676                 lCount = AFSObjectInfoIncrement( pNextObject,
2677                                                  AFS_OBJECT_REFERENCE_INVALIDATION);
2678
2679                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2680                               AFS_TRACE_LEVEL_VERBOSE,
2681                               "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2682                               pNextObject,
2683                               lCount));
2684             }
2685
2686             AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2687
2688             AFSInvalidateObject( &pCurrentObject,
2689                                  Reason);
2690
2691             if ( pCurrentObject )
2692             {
2693
2694                 lCount = AFSObjectInfoDecrement( pCurrentObject,
2695                                                  AFS_OBJECT_REFERENCE_INVALIDATION);
2696
2697                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2698                               AFS_TRACE_LEVEL_VERBOSE,
2699                               "AFSInvalidateVolumeObjects Decrement count on object %p Cnt %d\n",
2700                               pCurrentObject,
2701                               lCount));
2702             }
2703
2704             AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2705                               TRUE);
2706
2707             pCurrentObject = pNextObject;
2708         }
2709
2710         AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2711     }
2712
2713     return ntStatus;
2714 }
2715
2716 VOID
2717 AFSInvalidateAllVolumes( VOID)
2718 {
2719     AFSVolumeCB *pVolumeCB = NULL;
2720     AFSVolumeCB *pNextVolumeCB = NULL;
2721     AFSDeviceExt *pRDRDeviceExt = NULL;
2722     LONG lCount;
2723
2724     pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2725
2726     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2727                   AFS_TRACE_LEVEL_VERBOSE,
2728                   "AFSInvalidateAllVolumes Acquiring RDR VolumeListLock lock %p SHARED %08lX\n",
2729                   &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2730                   PsGetCurrentThread()));
2731
2732     AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2733                       TRUE);
2734
2735     pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
2736
2737     if ( pVolumeCB)
2738     {
2739
2740         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2741                       AFS_TRACE_LEVEL_VERBOSE,
2742                       "AFSInvalidateAllVolumes Acquiring VolumeRoot ObjectInfoTree lock %p SHARED %08lX\n",
2743                       pVolumeCB->ObjectInfoTree.TreeLock,
2744                       PsGetCurrentThread()));
2745
2746         lCount = AFSVolumeIncrement( pVolumeCB,
2747                                      AFS_VOLUME_REFERENCE_INVALIDATE);
2748
2749         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2750                       AFS_TRACE_LEVEL_VERBOSE,
2751                       "AFSInvalidateAllVolumes Increment count on volume %p Cnt %d\n",
2752                       pVolumeCB,
2753                       lCount));
2754     }
2755
2756     while( pVolumeCB != NULL)
2757     {
2758
2759         pNextVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2760
2761         if ( pNextVolumeCB)
2762         {
2763
2764             lCount = AFSVolumeIncrement( pNextVolumeCB,
2765                                          AFS_VOLUME_REFERENCE_INVALIDATE);
2766
2767             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2768                           AFS_TRACE_LEVEL_VERBOSE,
2769                           "AFSInvalidateAllVolumes Increment count on volume %p Cnt %d\n",
2770                           pVolumeCB,
2771                           lCount));
2772         }
2773
2774         AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2775
2776         // do I need to hold the volume lock here?
2777
2778         AFSInvalidateVolume( pVolumeCB, AFS_INVALIDATE_EXPIRED);
2779
2780         AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2781                           TRUE);
2782
2783         lCount = AFSVolumeDecrement( pVolumeCB,
2784                                      AFS_VOLUME_REFERENCE_INVALIDATE);
2785
2786         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2787                       AFS_TRACE_LEVEL_VERBOSE,
2788                       "AFSInvalidateAllVolumes Decrement count on volume %p Cnt %d\n",
2789                       pVolumeCB,
2790                       lCount));
2791
2792         pVolumeCB = pNextVolumeCB;
2793     }
2794
2795     AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2796 }
2797
2798 NTSTATUS
2799 AFSVerifyEntry( IN GUID *AuthGroup,
2800                 IN AFSDirectoryCB *DirEntry)
2801 {
2802
2803     NTSTATUS ntStatus = STATUS_SUCCESS;
2804     AFSDirEnumEntry *pDirEnumEntry = NULL;
2805     AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
2806     IO_STATUS_BLOCK stIoStatus;
2807
2808     __Enter
2809     {
2810
2811         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2812                       AFS_TRACE_LEVEL_VERBOSE_2,
2813                       "AFSVerifyEntry Verifying entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2814                       &DirEntry->NameInformation.FileName,
2815                       pObjectInfo->FileId.Cell,
2816                       pObjectInfo->FileId.Volume,
2817                       pObjectInfo->FileId.Vnode,
2818                       pObjectInfo->FileId.Unique));
2819
2820         ntStatus = AFSEvaluateTargetByID( pObjectInfo,
2821                                           AuthGroup,
2822                                           FALSE,
2823                                           &pDirEnumEntry);
2824
2825         if( !NT_SUCCESS( ntStatus))
2826         {
2827
2828             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2829                           AFS_TRACE_LEVEL_ERROR,
2830                           "AFSVerifyEntry Evaluate Target failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2831                           &DirEntry->NameInformation.FileName,
2832                           pObjectInfo->FileId.Cell,
2833                           pObjectInfo->FileId.Volume,
2834                           pObjectInfo->FileId.Vnode,
2835                           pObjectInfo->FileId.Unique,
2836                           ntStatus));
2837
2838             try_return( ntStatus);
2839         }
2840
2841         //
2842         // Check the data version of the file
2843         //
2844
2845         if( pObjectInfo->DataVersion.QuadPart == pDirEnumEntry->DataVersion.QuadPart)
2846         {
2847             if ( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2848             {
2849
2850                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2851                               AFS_TRACE_LEVEL_VERBOSE,
2852                               "AFSVerifyEntry No DV change %I64X for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2853                               pObjectInfo->DataVersion.QuadPart,
2854                               &DirEntry->NameInformation.FileName,
2855                               pObjectInfo->FileId.Cell,
2856                               pObjectInfo->FileId.Volume,
2857                               pObjectInfo->FileId.Vnode,
2858                               pObjectInfo->FileId.Unique));
2859
2860                 //
2861                 // We are ok, just get out
2862                 //
2863
2864                 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2865
2866                 try_return( ntStatus = STATUS_SUCCESS);
2867             }
2868         }
2869
2870         //
2871         // New data version so we will need to process the node based on the type
2872         //
2873
2874         switch( pDirEnumEntry->FileType)
2875         {
2876
2877             case AFS_FILE_TYPE_MOUNTPOINT:
2878             {
2879
2880                 //
2881                 // For a mount point we need to ensure the target is the same
2882                 //
2883
2884                 if( !AFSIsEqualFID( &pObjectInfo->TargetFileId,
2885                                     &pDirEnumEntry->TargetFileId))
2886                 {
2887
2888                 }
2889
2890                 //
2891                 // Update the metadata for the entry
2892                 //
2893
2894                 ntStatus = AFSUpdateMetaData( DirEntry,
2895                                               pDirEnumEntry);
2896
2897                 if( NT_SUCCESS( ntStatus))
2898                 {
2899
2900                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2901                 }
2902
2903                 break;
2904             }
2905
2906             case AFS_FILE_TYPE_SYMLINK:
2907             {
2908
2909                 //
2910                 // Update the metadata for the entry
2911                 //
2912
2913                 ntStatus = AFSUpdateMetaData( DirEntry,
2914                                               pDirEnumEntry);
2915
2916                 if( NT_SUCCESS( ntStatus))
2917                 {
2918
2919                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2920                 }
2921
2922                 break;
2923             }
2924
2925             case AFS_FILE_TYPE_FILE:
2926             {
2927                 FILE_OBJECT * pCCFileObject = NULL;
2928                 BOOLEAN bPurgeExtents = FALSE;
2929
2930                 if ( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
2931                 {
2932
2933                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2934                                   AFS_TRACE_LEVEL_VERBOSE,
2935                                   "AFSVerifyEntry DV Change %wZ FID %08lX-%08lX-%08lX-%08lX (%08lX != %08lX)\n",
2936                                   &DirEntry->NameInformation.FileName,
2937                                   pObjectInfo->FileId.Cell,
2938                                   pObjectInfo->FileId.Volume,
2939                                   pObjectInfo->FileId.Vnode,
2940                                   pObjectInfo->FileId.Unique,
2941                                   pObjectInfo->DataVersion.LowPart,
2942                                   pDirEnumEntry->DataVersion.LowPart));
2943
2944                     bPurgeExtents = TRUE;
2945                 }
2946
2947                 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2948                 {
2949
2950                     bPurgeExtents = TRUE;
2951
2952                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2953                                   AFS_TRACE_LEVEL_VERBOSE,
2954                                   "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2955                                   &DirEntry->NameInformation.FileName,
2956                                   pObjectInfo->FileId.Cell,
2957                                   pObjectInfo->FileId.Volume,
2958                                   pObjectInfo->FileId.Vnode,
2959                                   pObjectInfo->FileId.Unique));
2960
2961                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
2962                 }
2963
2964                 if( pObjectInfo->Fcb != NULL)
2965                 {
2966
2967                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2968                                   AFS_TRACE_LEVEL_VERBOSE,
2969                                   "AFSVerifyEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2970                                   &DirEntry->NameInformation.FileName,
2971                                   pObjectInfo->FileId.Cell,
2972                                   pObjectInfo->FileId.Volume,
2973                                   pObjectInfo->FileId.Vnode,
2974                                   pObjectInfo->FileId.Unique));
2975
2976                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
2977                                     TRUE);
2978
2979                     __try
2980                     {
2981
2982                         CcFlushCache( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2983                                       NULL,
2984                                       0,
2985                                       &stIoStatus);
2986
2987                         if( !NT_SUCCESS( stIoStatus.Status))
2988                         {
2989
2990                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2991                                           AFS_TRACE_LEVEL_ERROR,
2992                                           "AFSVerifyEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
2993                                           &DirEntry->NameInformation.FileName,
2994                                           pObjectInfo->FileId.Cell,
2995                                           pObjectInfo->FileId.Volume,
2996                                           pObjectInfo->FileId.Vnode,
2997                                           pObjectInfo->FileId.Unique,
2998                                           stIoStatus.Status,
2999                                           stIoStatus.Information));
3000
3001                             ntStatus = stIoStatus.Status;
3002                         }
3003
3004                         if ( bPurgeExtents &&
3005                              pObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
3006                         {
3007
3008                             if ( !CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
3009                                                        NULL,
3010                                                        0,
3011                                                        FALSE))
3012                             {
3013
3014                                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
3015                                               AFS_TRACE_LEVEL_WARNING,
3016                                               "AFSVerifyEntry CcPurgeCacheSection failure %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3017                                               &DirEntry->NameInformation.FileName,
3018                                               pObjectInfo->FileId.Cell,
3019                                               pObjectInfo->FileId.Volume,
3020                                               pObjectInfo->FileId.Vnode,
3021                                               pObjectInfo->FileId.Unique));
3022
3023                                 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
3024                             }
3025                         }
3026                     }
3027                     __except( EXCEPTION_EXECUTE_HANDLER)
3028                     {
3029                         ntStatus = GetExceptionCode();
3030
3031                         AFSDbgTrace(( 0,
3032                                       0,
3033                                       "EXCEPTION - AFSVerifyEntry CcFlushCache or CcPurgeCacheSection %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
3034                                       &DirEntry->NameInformation.FileName,
3035                                       pObjectInfo->FileId.Cell,
3036                                       pObjectInfo->FileId.Volume,
3037                                       pObjectInfo->FileId.Vnode,
3038                                       pObjectInfo->FileId.Unique,
3039                                       ntStatus));
3040
3041                         SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
3042                     }
3043
3044                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
3045
3046                     if ( bPurgeExtents)
3047                     {
3048                         AFSFlushExtents( pObjectInfo->Fcb,
3049                                          AuthGroup);
3050                     }
3051
3052                     //
3053                     // Reacquire the Fcb to purge the cache
3054                     //
3055
3056                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3057                                   AFS_TRACE_LEVEL_VERBOSE,
3058                                   "AFSVerifyEntry Acquiring Fcb lock %p EXCL %08lX\n",
3059                                   &pObjectInfo->Fcb->NPFcb->Resource,
3060                                   PsGetCurrentThread()));
3061
3062                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
3063                                     TRUE);
3064
3065                     //
3066                     // Update the metadata for the entry
3067                     //
3068
3069                     ntStatus = AFSUpdateMetaData( DirEntry,
3070                                                   pDirEnumEntry);
3071
3072                     if( !NT_SUCCESS( ntStatus))
3073                     {
3074
3075                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3076                                       AFS_TRACE_LEVEL_ERROR,
3077                                       "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
3078                                       &DirEntry->NameInformation.FileName,
3079                                       pObjectInfo->FileId.Cell,
3080                                       pObjectInfo->FileId.Volume,
3081                                       pObjectInfo->FileId.Vnode,
3082                                       pObjectInfo->FileId.Unique,
3083                                       ntStatus));
3084
3085                         break;
3086                     }
3087
3088                     //
3089                     // Update file sizes
3090                     //
3091
3092                     pObjectInfo->Fcb->Header.AllocationSize.QuadPart  = pObjectInfo->AllocationSize.QuadPart;
3093                     pObjectInfo->Fcb->Header.FileSize.QuadPart        = pObjectInfo->EndOfFile.QuadPart;
3094                     pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
3095
3096                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3097                                   AFS_TRACE_LEVEL_VERBOSE,
3098                                   "AFSVerifyEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
3099                                   &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3100                                   PsGetCurrentThread()));
3101
3102                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3103                                     TRUE);
3104
3105                     pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
3106
3107                     if ( pCCFileObject != NULL)
3108                     {
3109                         CcSetFileSizes( pCCFileObject,
3110                                         (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
3111                     }
3112
3113                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3114                                   AFS_TRACE_LEVEL_VERBOSE,
3115                                   "AFSVerifyEntry Releasing Fcb SectionObject lock %p EXCL %08lX\n",
3116                                   &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3117                                   PsGetCurrentThread()));
3118
3119                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
3120
3121                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
3122                 }
3123                 else
3124                 {
3125
3126                     //
3127                     // Update the metadata for the entry
3128                     //
3129
3130                     ntStatus = AFSUpdateMetaData( DirEntry,
3131                                                   pDirEnumEntry);
3132
3133                     if( !NT_SUCCESS( ntStatus))
3134                     {
3135
3136                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3137                                       AFS_TRACE_LEVEL_ERROR,
3138                                       "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
3139                                       &DirEntry->NameInformation.FileName,
3140                                       pObjectInfo->FileId.Cell,
3141                                       pObjectInfo->FileId.Volume,
3142                                       pObjectInfo->FileId.Vnode,
3143                                       pObjectInfo->FileId.Unique,
3144                                       ntStatus));
3145
3146                         break;
3147                     }
3148
3149                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3150                                   AFS_TRACE_LEVEL_WARNING,
3151                                   "AFSVerifyEntry Fcb NULL %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3152                                   &DirEntry->NameInformation.FileName,
3153                                   pObjectInfo->FileId.Cell,
3154                                   pObjectInfo->FileId.Volume,
3155                                   pObjectInfo->FileId.Vnode,
3156                                   pObjectInfo->FileId.Unique));
3157                 }
3158
3159                 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3160
3161                 break;
3162             }
3163
3164             case AFS_FILE_TYPE_DIRECTORY:
3165             {
3166
3167                 //
3168                 // For a directory or root entry flush the content of
3169                 // the directory enumeration.
3170                 //
3171
3172                 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3173                 {
3174
3175                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3176                                   AFS_TRACE_LEVEL_VERBOSE_2,
3177                                   "AFSVerifyEntry Validating directory content for entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3178                                   &DirEntry->NameInformation.FileName,
3179                                   pObjectInfo->FileId.Cell,
3180                                   pObjectInfo->FileId.Volume,
3181                                   pObjectInfo->FileId.Vnode,
3182                                   pObjectInfo->FileId.Unique));
3183
3184                     AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3185                                     TRUE);
3186
3187                     ntStatus = AFSValidateDirectoryCache( pObjectInfo,
3188                                                           AuthGroup);
3189
3190                     AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3191
3192                     if ( !NT_SUCCESS( ntStatus))
3193                     {
3194
3195                         try_return( ntStatus);
3196                     }
3197                 }
3198
3199                 //
3200                 // Update the metadata for the entry
3201                 //
3202
3203                 ntStatus = AFSUpdateMetaData( DirEntry,
3204                                               pDirEnumEntry);
3205
3206                 if( NT_SUCCESS( ntStatus))
3207                 {
3208
3209                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3210                 }
3211
3212                 break;
3213             }
3214
3215             case AFS_FILE_TYPE_DFSLINK:
3216             {
3217
3218                 UNICODE_STRING uniTargetName;
3219
3220                 //
3221                 // For a DFS link need to check the target name has not changed
3222                 //
3223
3224                 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
3225
3226                 uniTargetName.MaximumLength = uniTargetName.Length;
3227
3228                 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
3229
3230                 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3231                                 TRUE);
3232
3233                 if( DirEntry->NameInformation.TargetName.Length == 0 ||
3234                     RtlCompareUnicodeString( &uniTargetName,
3235                                              &DirEntry->NameInformation.TargetName,
3236                                              TRUE) != 0)
3237                 {
3238
3239                     //
3240                     // Update the target name
3241                     //
3242
3243                     ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3244                                                     &DirEntry->Flags,
3245                                                     uniTargetName.Buffer,
3246                                                     uniTargetName.Length);
3247
3248                     if( !NT_SUCCESS( ntStatus))
3249                     {
3250
3251                         AFSReleaseResource( &DirEntry->NonPaged->Lock);
3252
3253                         break;
3254                     }
3255                 }
3256
3257                 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3258
3259                 //
3260                 // Update the metadata for the entry
3261                 //
3262
3263                 ntStatus = AFSUpdateMetaData( DirEntry,
3264                                               pDirEnumEntry);
3265
3266                 if( NT_SUCCESS( ntStatus))
3267                 {
3268
3269                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3270                 }
3271
3272                 break;
3273             }
3274
3275             default:
3276
3277                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3278                               AFS_TRACE_LEVEL_WARNING,
3279                               "AFSVerifyEntry Attempt to verify node of type %d %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3280                               pObjectInfo->FileType,
3281                               &DirEntry->NameInformation.FileName,
3282                               pObjectInfo->FileId.Cell,
3283                               pObjectInfo->FileId.Volume,
3284                               pObjectInfo->FileId.Vnode,
3285                               pObjectInfo->FileId.Unique));
3286
3287                 break;
3288         }
3289
3290  try_exit:
3291
3292         if( pDirEnumEntry != NULL)
3293         {
3294
3295             AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_2_TAG);
3296         }
3297     }
3298
3299     return ntStatus;
3300 }
3301
3302 NTSTATUS
3303 AFSSetVolumeState( IN AFSVolumeStatusCB *VolumeStatus)
3304 {
3305
3306     NTSTATUS ntStatus = STATUS_SUCCESS;
3307     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
3308     ULONGLONG   ullIndex = 0;
3309     AFSVolumeCB *pVolumeCB = NULL;
3310     LONG lCount;
3311
3312     __Enter
3313     {
3314
3315         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3316                       AFS_TRACE_LEVEL_VERBOSE,
3317                       "AFSSetVolumeState Marking volume state %d Volume Cell %08lX Volume %08lX\n",
3318                       VolumeStatus->Online,
3319                       VolumeStatus->FileID.Cell,
3320                       VolumeStatus->FileID.Volume));
3321
3322         //
3323         // Need to locate the Fcb for the directory to purge
3324         //
3325
3326         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3327                       AFS_TRACE_LEVEL_VERBOSE,
3328                       "AFSSetVolumeState Acquiring RDR VolumeTreeLock lock %p SHARED %08lX\n",
3329                       &pDevExt->Specific.RDR.VolumeTreeLock,
3330                       PsGetCurrentThread()));
3331
3332         AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
3333
3334         //
3335         // Locate the volume node
3336         //
3337
3338         ullIndex = AFSCreateHighIndex( &VolumeStatus->FileID);
3339
3340         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
3341                                        ullIndex,
3342                                        (AFSBTreeEntry **)&pVolumeCB);
3343
3344         if( pVolumeCB != NULL)
3345         {
3346
3347             lCount = AFSVolumeIncrement( pVolumeCB,
3348                                          AFS_VOLUME_REFERENCE_INVALIDATE);
3349
3350             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3351                           AFS_TRACE_LEVEL_VERBOSE,
3352                           "AFSSetVolumeState Increment count on volume %p Cnt %d\n",
3353                           pVolumeCB,
3354                           lCount));
3355
3356             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3357
3358             //
3359             // Set the volume state accordingly
3360             //
3361
3362             if( VolumeStatus->Online)
3363             {
3364
3365                 InterlockedAnd( (LONG *)&(pVolumeCB->Flags), ~AFS_VOLUME_FLAGS_OFFLINE);
3366             }
3367             else
3368             {
3369
3370                 InterlockedOr( (LONG *)&(pVolumeCB->Flags), AFS_VOLUME_FLAGS_OFFLINE);
3371             }
3372         }
3373     }
3374
3375     return ntStatus;
3376 }
3377
3378 NTSTATUS
3379 AFSSetNetworkState( IN AFSNetworkStatusCB *NetworkStatus)
3380 {
3381
3382     NTSTATUS ntStatus = STATUS_SUCCESS;
3383
3384     __Enter
3385     {
3386
3387         if( AFSGlobalRoot == NULL)
3388         {
3389
3390             try_return( ntStatus);
3391         }
3392
3393         AFSAcquireExcl( AFSGlobalRoot->VolumeLock,
3394                         TRUE);
3395
3396         //
3397         // Set the network state according to the information
3398         //
3399
3400         if( NetworkStatus->Online)
3401         {
3402
3403             ClearFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3404         }
3405         else
3406         {
3407
3408             SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3409         }
3410
3411         AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3412
3413 try_exit:
3414
3415         NOTHING;
3416     }
3417
3418     return ntStatus;
3419 }
3420
3421 NTSTATUS
3422 AFSValidateDirectoryCache( IN AFSObjectInfoCB *ObjectInfo,
3423                            IN GUID *AuthGroup)
3424 {
3425
3426     NTSTATUS ntStatus = STATUS_SUCCESS;
3427     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3428     BOOLEAN  bAcquiredLock = FALSE;
3429     AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
3430
3431     __Enter
3432     {
3433
3434         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3435                       AFS_TRACE_LEVEL_VERBOSE,
3436                       "AFSValidateDirectoryCache Validating content for FID %08lX-%08lX-%08lX-%08lX\n",
3437                       ObjectInfo->FileId.Cell,
3438                       ObjectInfo->FileId.Volume,
3439                       ObjectInfo->FileId.Vnode,
3440                       ObjectInfo->FileId.Unique));
3441
3442         if( !ExIsResourceAcquiredLite( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock))
3443         {
3444
3445             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3446                           AFS_TRACE_LEVEL_VERBOSE,
3447                           "AFSValidateDirectoryCache Acquiring DirectoryNodeHdr.TreeLock lock %p EXCL %08lX\n",
3448                           ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3449                           PsGetCurrentThread()));
3450
3451             AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3452                             TRUE);
3453
3454             bAcquiredLock = TRUE;
3455         }
3456
3457         //
3458         // Check for inconsistency between DirectoryNodeList and DirectoryNodeCount
3459         //
3460
3461         if ( ObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL &&
3462              ObjectInfo->Specific.Directory.DirectoryNodeCount > 0)
3463         {
3464
3465             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3466                           AFS_TRACE_LEVEL_ERROR,
3467                           "AFSValidateDirectoryCache Empty Node List but Non-Zero Node Count %d for dir FID %08lX-%08lX-%08lX-%08lX\n",
3468                           ObjectInfo->Specific.Directory.DirectoryNodeCount,
3469                           ObjectInfo->FileId.Cell,
3470                           ObjectInfo->FileId.Volume,
3471                           ObjectInfo->FileId.Vnode,
3472                           ObjectInfo->FileId.Unique));
3473         }
3474
3475         //
3476         // Reset the directory list information by clearing all valid entries
3477         //
3478
3479         pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3480
3481         while( pCurrentDirEntry != NULL)
3482         {
3483
3484             pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3485
3486             if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
3487             {
3488
3489                 //
3490                 // If this entry has been deleted then process it here
3491                 //
3492
3493                 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
3494                     pCurrentDirEntry->DirOpenReferenceCount <= 0 &&
3495                     pCurrentDirEntry->NameArrayReferenceCount <= 0)
3496                 {
3497
3498                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3499                                   AFS_TRACE_LEVEL_VERBOSE,
3500                                   "AFSValidateDirectoryCache Deleting dir entry %p name %wZ\n",
3501                                   pCurrentDirEntry,
3502                                   &pCurrentDirEntry->NameInformation.FileName));
3503
3504                     AFSDeleteDirEntry( ObjectInfo,
3505                                        pCurrentDirEntry);
3506                 }
3507                 else
3508                 {
3509
3510                     ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID);
3511
3512                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3513                                   AFS_TRACE_LEVEL_VERBOSE,
3514                                   "AFSValidateDirectoryCache Clear VALID flag on DE %p Reference count %d\n",
3515                                   pCurrentDirEntry,
3516                                   pCurrentDirEntry->DirOpenReferenceCount));
3517
3518                     //
3519                     // We pull the short name from the parent tree since it could change below
3520                     //
3521
3522                     if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
3523                     {
3524
3525                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3526                                       AFS_TRACE_LEVEL_VERBOSE,
3527                                       "AFSValidateDirectoryCache Removing DE %p (%08lX) from shortname tree for %wZ\n",
3528                                       pCurrentDirEntry,
3529                                       pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3530                                       &pCurrentDirEntry->NameInformation.FileName));
3531
3532                         AFSRemoveShortNameDirEntry( &ObjectInfo->Specific.Directory.ShortNameTree,
3533                                                     pCurrentDirEntry);
3534
3535                         ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3536                     }
3537                 }
3538             }
3539
3540             pCurrentDirEntry = pNextDirEntry;
3541         }
3542
3543         //
3544         // Reget the directory contents
3545         //
3546
3547         ntStatus = AFSVerifyDirectoryContent( ObjectInfo,
3548                                               AuthGroup);
3549
3550         if ( !NT_SUCCESS( ntStatus))
3551         {
3552             try_return( ntStatus);
3553         }
3554
3555         //
3556         // Now start again and tear down any entries not valid
3557         //
3558
3559         pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3560
3561         while( pCurrentDirEntry != NULL)
3562         {
3563
3564             pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3565
3566             if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID))
3567             {
3568
3569                 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3570                     !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME) &&
3571                     pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex > 0)
3572                 {
3573
3574                     if( ObjectInfo->Specific.Directory.ShortNameTree == NULL)
3575                     {
3576
3577                         ObjectInfo->Specific.Directory.ShortNameTree = pCurrentDirEntry;
3578
3579                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3580                                       AFS_TRACE_LEVEL_VERBOSE,
3581                                       "AFSValidateDirectoryCache Insert DE %p to head of shortname tree for %wZ\n",
3582                                       pCurrentDirEntry,
3583                                       &pCurrentDirEntry->NameInformation.FileName));
3584
3585                         SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3586                     }
3587                     else
3588                     {
3589
3590                         if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfo->Specific.Directory.ShortNameTree,
3591                                                                      pCurrentDirEntry)))
3592                         {
3593                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3594                                           AFS_TRACE_LEVEL_VERBOSE,
3595                                           "AFSValidateDirectoryCache Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
3596                                           pCurrentDirEntry,
3597                                           pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3598                                           &pCurrentDirEntry->NameInformation.FileName));
3599                         }
3600                         else
3601                         {
3602                             SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3603
3604                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3605                                           AFS_TRACE_LEVEL_VERBOSE,
3606                                           "AFSValidateDirectoryCache Insert DE %p to shortname tree for %wZ\n",
3607                                           pCurrentDirEntry,
3608                                           &pCurrentDirEntry->NameInformation.FileName));
3609                         }
3610                     }
3611                 }
3612
3613                 pCurrentDirEntry = pNextDirEntry;
3614
3615                 continue;
3616             }
3617
3618             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3619                           AFS_TRACE_LEVEL_VERBOSE,
3620                           "AFSValidateDirectoryCache Processing INVALID DE %p Reference count %d\n",
3621                           pCurrentDirEntry,
3622                           pCurrentDirEntry->DirOpenReferenceCount));
3623
3624             if( pCurrentDirEntry->DirOpenReferenceCount <= 0 &&
3625                 pCurrentDirEntry->NameArrayReferenceCount <= 0)
3626             {
3627
3628                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3629                               AFS_TRACE_LEVEL_VERBOSE,
3630                               "AFSValidateDirectoryCache Deleting dir entry %wZ from parent FID %08lX-%08lX-%08lX-%08lX\n",
3631                               &pCurrentDirEntry->NameInformation.FileName,
3632                               ObjectInfo->FileId.Cell,
3633                               ObjectInfo->FileId.Volume,
3634                               ObjectInfo->FileId.Vnode,
3635                               ObjectInfo->FileId.Unique));
3636
3637                 AFSDeleteDirEntry( ObjectInfo,
3638                                    pCurrentDirEntry);
3639             }
3640             else
3641             {
3642
3643                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3644                               AFS_TRACE_LEVEL_VERBOSE,
3645                               "AFSValidateDirectoryCache Setting dir entry %p Name %wZ DELETED in parent FID %08lX-%08lX-%08lX-%08lX\n",
3646                               pCurrentDirEntry,
3647                               &pCurrentDirEntry->NameInformation.FileName,
3648                               ObjectInfo->FileId.Cell,
3649                               ObjectInfo->FileId.Volume,
3650                               ObjectInfo->FileId.Vnode,
3651                               ObjectInfo->FileId.Unique));
3652
3653                 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
3654
3655                 AFSRemoveNameEntry( ObjectInfo,
3656                                     pCurrentDirEntry);
3657             }
3658
3659             pCurrentDirEntry = pNextDirEntry;
3660         }
3661
3662 #if DBG
3663         if( !AFSValidateDirList( ObjectInfo))
3664         {
3665
3666             AFSPrint("AFSValidateDirectoryCache Invalid count ...\n");
3667         }
3668 #endif
3669
3670 try_exit:
3671
3672         if( bAcquiredLock)
3673         {
3674
3675             AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3676         }
3677     }
3678
3679     return ntStatus;
3680 }
3681
3682 BOOLEAN
3683 AFSIsVolumeFID( IN AFSFileID *FileID)
3684 {
3685
3686     BOOLEAN bIsVolume = FALSE;
3687
3688     if( FileID->Vnode == 1 &&
3689         FileID->Unique == 1)
3690     {
3691
3692         bIsVolume = TRUE;
3693     }
3694
3695     return bIsVolume;
3696 }
3697
3698 BOOLEAN
3699 AFSIsFinalNode( IN AFSFcb *Fcb)
3700 {
3701
3702     BOOLEAN bIsFinalNode = FALSE;
3703
3704     if( Fcb->Header.NodeTypeCode == AFS_ROOT_FCB ||
3705         Fcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB ||
3706         Fcb->Header.NodeTypeCode == AFS_FILE_FCB ||
3707         Fcb->Header.NodeTypeCode == AFS_DFS_LINK_FCB ||
3708         Fcb->Header.NodeTypeCode == AFS_INVALID_FCB )
3709     {
3710
3711         bIsFinalNode = TRUE;
3712     }
3713     else
3714     {
3715
3716         ASSERT( Fcb->Header.NodeTypeCode == AFS_MOUNT_POINT_FCB ||
3717                 Fcb->Header.NodeTypeCode == AFS_SYMBOLIC_LINK_FCB);
3718     }
3719
3720     return bIsFinalNode;
3721 }
3722
3723 NTSTATUS
3724 AFSUpdateMetaData( IN AFSDirectoryCB *DirEntry,
3725                    IN AFSDirEnumEntry *DirEnumEntry)
3726 {
3727
3728     NTSTATUS ntStatus = STATUS_SUCCESS;
3729     UNICODE_STRING uniTargetName;
3730     AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
3731
3732     __Enter
3733     {
3734
3735         pObjectInfo->TargetFileId = DirEnumEntry->TargetFileId;
3736
3737         pObjectInfo->Expiration = DirEnumEntry->Expiration;
3738
3739         pObjectInfo->DataVersion = DirEnumEntry->DataVersion;
3740
3741         pObjectInfo->FileType = DirEnumEntry->FileType;
3742
3743         pObjectInfo->CreationTime = DirEnumEntry->CreationTime;
3744
3745         pObjectInfo->LastAccessTime = DirEnumEntry->LastAccessTime;
3746
3747         pObjectInfo->LastWriteTime = DirEnumEntry->LastWriteTime;
3748
3749         pObjectInfo->ChangeTime = DirEnumEntry->ChangeTime;
3750
3751         pObjectInfo->EndOfFile = DirEnumEntry->EndOfFile;
3752
3753         pObjectInfo->AllocationSize = DirEnumEntry->AllocationSize;
3754
3755         pObjectInfo->FileAttributes = DirEnumEntry->FileAttributes;
3756
3757         if( pObjectInfo->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
3758             pObjectInfo->FileType == AFS_FILE_TYPE_DFSLINK)
3759         {
3760
3761             pObjectInfo->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
3762         }
3763
3764         if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK)
3765         {
3766
3767             if ( pObjectInfo->FileAttributes == FILE_ATTRIBUTE_NORMAL)
3768             {
3769
3770                 pObjectInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
3771             }
3772             else
3773             {
3774
3775                 pObjectInfo->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
3776             }
3777         }
3778
3779         pObjectInfo->EaSize = DirEnumEntry->EaSize;
3780
3781         pObjectInfo->Links = DirEnumEntry->Links;
3782
3783         if( DirEnumEntry->TargetNameLength > 0 &&
3784             ( DirEntry->NameInformation.TargetName.Length != DirEnumEntry->TargetNameLength ||
3785               DirEntry->ObjectInformation->DataVersion.QuadPart != DirEnumEntry->DataVersion.QuadPart))
3786         {
3787
3788             //
3789             // Update the target name information if needed
3790             //
3791
3792             uniTargetName.Length = (USHORT)DirEnumEntry->TargetNameLength;
3793
3794             uniTargetName.MaximumLength = uniTargetName.Length;
3795
3796             uniTargetName.Buffer = (WCHAR *)((char *)DirEnumEntry + DirEnumEntry->TargetNameOffset);
3797
3798             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3799                             TRUE);
3800
3801             if( DirEntry->NameInformation.TargetName.Length == 0 ||
3802                 RtlCompareUnicodeString( &uniTargetName,
3803                                          &DirEntry->NameInformation.TargetName,
3804                                          TRUE) != 0)
3805             {
3806
3807                 //
3808                 // Update the target name
3809                 //
3810
3811                 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3812                                                 &DirEntry->Flags,
3813                                                 uniTargetName.Buffer,
3814                                                 uniTargetName.Length);
3815
3816                 if( !NT_SUCCESS( ntStatus))
3817                 {
3818
3819                     AFSReleaseResource( &DirEntry->NonPaged->Lock);
3820
3821                     try_return( ntStatus);
3822                 }
3823             }
3824
3825             AFSReleaseResource( &DirEntry->NonPaged->Lock);
3826         }
3827         else if( DirEntry->NameInformation.TargetName.Length > 0 &&
3828                  DirEntry->ObjectInformation->DataVersion.QuadPart != DirEnumEntry->DataVersion.QuadPart)
3829         {
3830
3831             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3832                             TRUE);
3833
3834             if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER) &&
3835                 DirEntry->NameInformation.TargetName.Buffer != NULL)
3836             {
3837                 AFSExFreePoolWithTag( DirEntry->NameInformation.TargetName.Buffer, AFS_NAME_BUFFER_FIVE_TAG);
3838             }
3839
3840             ClearFlag( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER);
3841
3842             DirEntry->NameInformation.TargetName.Length = 0;
3843             DirEntry->NameInformation.TargetName.MaximumLength = 0;
3844             DirEntry->NameInformation.TargetName.Buffer = NULL;
3845
3846             AFSReleaseResource( &DirEntry->NonPaged->Lock);
3847         }
3848
3849 try_exit:
3850
3851         NOTHING;
3852     }
3853
3854     return ntStatus;
3855 }
3856
3857 NTSTATUS
3858 AFSValidateEntry( IN AFSDirectoryCB *DirEntry,
3859                   IN GUID *AuthGroup,
3860                   IN BOOLEAN FastCall,
3861                   IN BOOLEAN bSafeToPurge)
3862 {
3863
3864     NTSTATUS ntStatus = STATUS_SUCCESS;
3865     LARGE_INTEGER liSystemTime;
3866     AFSDirEnumEntry *pDirEnumEntry = NULL;
3867     AFSFcb *pCurrentFcb = NULL;
3868     BOOLEAN bReleaseFcb = FALSE;
3869     AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
3870
3871     __Enter
3872     {
3873
3874         //
3875         // If we have an Fcb hanging off the directory entry then be sure to acquire the locks in the
3876         // correct order
3877         //
3878
3879         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3880                       AFS_TRACE_LEVEL_VERBOSE_2,
3881                       "AFSValidateEntry Validating entry %wZ FID %08lX-%08lX-%08lX-%08lX FastCall %u\n",
3882                       &DirEntry->NameInformation.FileName,
3883                       pObjectInfo->FileId.Cell,
3884                       pObjectInfo->FileId.Volume,
3885                       pObjectInfo->FileId.Vnode,
3886                       pObjectInfo->FileId.Unique,
3887                       FastCall));
3888
3889         //
3890         // If this is a fake node then bail since the service knows nothing about it
3891         //
3892
3893         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_FAKE))
3894         {
3895
3896             try_return( ntStatus);
3897         }
3898
3899         //
3900         // This routine ensures that the current entry is valid by:
3901         //
3902         //      1) Checking that the expiration time is non-zero and after where we
3903         //         currently are
3904         //
3905
3906         KeQuerySystemTime( &liSystemTime);
3907
3908         if( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) &&
3909             !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
3910             !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA) &&
3911             pObjectInfo->Expiration.QuadPart >= liSystemTime.QuadPart)
3912         {
3913
3914             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3915                           AFS_TRACE_LEVEL_VERBOSE_2,
3916                           "AFSValidateEntry Directory entry %wZ FID %08lX-%08lX-%08lX-%08lX VALID\n",
3917                           &DirEntry->NameInformation.FileName,
3918                           pObjectInfo->FileId.Cell,
3919                           pObjectInfo->FileId.Volume,
3920                           pObjectInfo->FileId.Vnode,
3921                           pObjectInfo->FileId.Unique));
3922
3923             try_return( ntStatus);
3924         }
3925
3926         //
3927         // This node requires updating
3928         //
3929
3930         ntStatus = AFSEvaluateTargetByID( pObjectInfo,
3931                                           AuthGroup,
3932                                           FastCall,
3933                                           &pDirEnumEntry);
3934
3935         if( !NT_SUCCESS( ntStatus))
3936         {
3937
3938             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3939                           AFS_TRACE_LEVEL_ERROR,
3940                           "AFSValidateEntry Failed to evaluate entry FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3941                           FastCall,
3942                           &DirEntry->NameInformation.FileName,
3943                           pObjectInfo->FileId.Cell,
3944                           pObjectInfo->FileId.Volume,
3945                           pObjectInfo->FileId.Vnode,
3946                           pObjectInfo->FileId.Unique,
3947                           ntStatus));
3948
3949             //
3950             // Failed validation of node so return access-denied
3951             //
3952
3953             try_return( ntStatus);
3954         }
3955
3956         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3957                       AFS_TRACE_LEVEL_VERBOSE,
3958                       "AFSValidateEntry Validating entry FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX DV %I64X returned DV %I64X FT %d\n",
3959                       FastCall,
3960                       &DirEntry->NameInformation.FileName,
3961                       pObjectInfo->FileId.Cell,
3962                       pObjectInfo->FileId.Volume,
3963                       pObjectInfo->FileId.Vnode,
3964                       pObjectInfo->FileId.Unique,
3965                       pObjectInfo->DataVersion.QuadPart,
3966                       pDirEnumEntry->DataVersion.QuadPart,
3967                       pDirEnumEntry->FileType));
3968
3969
3970         //
3971         // Based on the file type, process the node
3972         //
3973
3974         switch( pDirEnumEntry->FileType)
3975         {
3976
3977             case AFS_FILE_TYPE_MOUNTPOINT:
3978             {
3979
3980                 //
3981                 // Update the metadata for the entry
3982                 //
3983
3984                 ntStatus = AFSUpdateMetaData( DirEntry,
3985                                               pDirEnumEntry);
3986
3987                 if( NT_SUCCESS( ntStatus))
3988                 {
3989
3990                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
3991                 }
3992
3993                 break;
3994             }
3995
3996             case AFS_FILE_TYPE_SYMLINK:
3997             case AFS_FILE_TYPE_DFSLINK:
3998             {
3999
4000                 //
4001                 // Update the metadata for the entry
4002                 //
4003
4004                 ntStatus = AFSUpdateMetaData( DirEntry,
4005                                               pDirEnumEntry);
4006
4007                 if( NT_SUCCESS( ntStatus))
4008                 {
4009
4010                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
4011                 }
4012
4013                 break;
4014             }
4015
4016             case AFS_FILE_TYPE_FILE:
4017             {
4018
4019                 BOOLEAN bPurgeExtents = FALSE;
4020
4021                 //
4022                 // For a file where the data version has become invalid we need to
4023                 // fail any current extent requests and purge the cache for the file
4024                 // Can't hold the Fcb resource while doing this
4025                 //
4026
4027                 if( pObjectInfo->Fcb != NULL &&
4028                     (pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart ||
4029                       BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA)))
4030                 {
4031
4032                     pCurrentFcb = pObjectInfo->Fcb;
4033
4034                     if( !ExIsResourceAcquiredLite( &pCurrentFcb->NPFcb->Resource))
4035                     {
4036
4037                         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4038                                       AFS_TRACE_LEVEL_VERBOSE,
4039                                       "AFSValidateEntry Acquiring Fcb lock %p EXCL %08lX\n",
4040                                       &pCurrentFcb->NPFcb->Resource,
4041                                       PsGetCurrentThread()));
4042
4043                         AFSAcquireExcl( &pCurrentFcb->NPFcb->Resource,
4044                                         TRUE);
4045
4046                         bReleaseFcb = TRUE;
4047                     }
4048
4049                     if( pCurrentFcb != NULL)
4050                     {
4051
4052                         IO_STATUS_BLOCK stIoStatus;
4053
4054                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4055                                       AFS_TRACE_LEVEL_VERBOSE_2,
4056                                       "AFSValidateEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4057                                       &DirEntry->NameInformation.FileName,
4058                                       pObjectInfo->FileId.Cell,
4059                                       pObjectInfo->FileId.Volume,
4060                                       pObjectInfo->FileId.Vnode,
4061                                       pObjectInfo->FileId.Unique));
4062
4063                         if ( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
4064                         {
4065
4066                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4067                                           AFS_TRACE_LEVEL_VERBOSE,
4068                                           "AFSValidateEntry DV Change %wZ FID %08lX-%08lX-%08lX-%08lX (%08lX != %08lX)\n",
4069                                           &DirEntry->NameInformation.FileName,
4070                                           pObjectInfo->FileId.Cell,
4071                                           pObjectInfo->FileId.Volume,
4072                                           pObjectInfo->FileId.Vnode,
4073                                           pObjectInfo->FileId.Unique,
4074                                           pObjectInfo->DataVersion.LowPart,
4075                                           pDirEnumEntry->DataVersion.LowPart));
4076
4077                             bPurgeExtents = TRUE;
4078                         }
4079
4080                         if ( bSafeToPurge)
4081                         {
4082
4083                             if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
4084                             {
4085                                 bPurgeExtents = TRUE;
4086
4087                                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4088                                               AFS_TRACE_LEVEL_VERBOSE,
4089                                               "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4090                                               &DirEntry->NameInformation.FileName,
4091                                               pObjectInfo->FileId.Cell,
4092                                               pObjectInfo->FileId.Volume,
4093                                               pObjectInfo->FileId.Vnode,
4094                                               pObjectInfo->FileId.Unique));
4095
4096                                 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
4097                             }
4098
4099                             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4100                                           AFS_TRACE_LEVEL_VERBOSE,
4101                                           "AFSValidateEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
4102                                           &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
4103                                           PsGetCurrentThread()));
4104
4105                             AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
4106                                             TRUE);
4107
4108                             //
4109                             // Release Fcb->Resource to avoid Trend Micro deadlock
4110                             //
4111
4112                             AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
4113
4114                             __try
4115                             {
4116
4117                                 CcFlushCache( &pCurrentFcb->NPFcb->SectionObjectPointers,
4118                                               NULL,
4119                                               0,
4120                                               &stIoStatus);
4121
4122                                 if( !NT_SUCCESS( stIoStatus.Status))
4123                                 {
4124
4125                                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
4126                                                   AFS_TRACE_LEVEL_ERROR,
4127                                                   "AFSValidateEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
4128                                                   &DirEntry->NameInformation.FileName,
4129                                                   pObjectInfo->FileId.Cell,
4130                                                   pObjectInfo->FileId.Volume,
4131                                                   pObjectInfo->FileId.Vnode,
4132                                                   pObjectInfo->FileId.Unique,
4133                                                   stIoStatus.Status,
4134                                                   stIoStatus.Information));
4135
4136                                     ntStatus = stIoStatus.Status;
4137                                 }
4138
4139                                 if ( bPurgeExtents &&
4140                                      pObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
4141                                 {
4142
4143                                     if ( !CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
4144                                                                NULL,
4145                                                                0,
4146                                                                FALSE))
4147                                     {
4148
4149                                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
4150                                                       AFS_TRACE_LEVEL_WARNING,
4151                                                       "AFSValidateEntry CcPurgeCacheSection failure %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4152                                                       &DirEntry->NameInformation.FileName,
4153                                                       pObjectInfo->FileId.Cell,
4154                                                       pObjectInfo->FileId.Volume,
4155                                                       pObjectInfo->FileId.Vnode,
4156                                                       pObjectInfo->FileId.Unique));
4157
4158                                         SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
4159                                     }
4160                                 }
4161                             }
4162                             __except( EXCEPTION_EXECUTE_HANDLER)
4163                             {
4164                                 ntStatus = GetExceptionCode();
4165
4166                                 AFSDbgTrace(( 0,
4167                                               0,
4168                                               "EXCEPTION - AFSValidateEntry CcFlushCache or CcPurgeCacheSection %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
4169                                               &DirEntry->NameInformation.FileName,
4170                                               pObjectInfo->FileId.Cell,
4171                                               pObjectInfo->FileId.Volume,
4172                                               pObjectInfo->FileId.Vnode,
4173                                               pObjectInfo->FileId.Unique,
4174                                               ntStatus));
4175
4176                                 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
4177                             }
4178
4179                             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4180                                           AFS_TRACE_LEVEL_VERBOSE,
4181                                           "AFSValidateEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
4182                                           &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
4183                                           PsGetCurrentThread()));
4184
4185                             AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
4186
4187                             AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
4188                                             TRUE);
4189                         }
4190                         else
4191                         {
4192
4193                             if ( bPurgeExtents)
4194                             {
4195
4196                                 SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
4197                             }
4198                         }
4199
4200
4201                         AFSReleaseResource( &pCurrentFcb->NPFcb->Resource);
4202
4203                         bReleaseFcb = FALSE;
4204
4205                         if ( bPurgeExtents &&
4206                              bSafeToPurge)
4207                         {
4208                             AFSFlushExtents( pCurrentFcb,
4209                                              AuthGroup);
4210                         }
4211                     }
4212                 }
4213
4214                 //
4215                 // Update the metadata for the entry but only if it is safe to do so.
4216                 // If it was determined that a data version change has occurred or
4217                 // that a pending data verification was required, do not update the
4218                 // ObjectInfo meta data or the FileObject size information.  That
4219                 // way it is consistent for the next time that the data is verified
4220                 // or validated.
4221                 //
4222
4223                 if ( !(bPurgeExtents && bSafeToPurge))
4224                 {
4225
4226                     ntStatus = AFSUpdateMetaData( DirEntry,
4227                                                   pDirEnumEntry);
4228
4229                     if( !NT_SUCCESS( ntStatus))
4230                     {
4231
4232                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4233                                       AFS_TRACE_LEVEL_ERROR,
4234                                       "AFSValidateEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
4235                                       &DirEntry->NameInformation.FileName,
4236                                       pObjectInfo->FileId.Cell,
4237                                       pObjectInfo->FileId.Volume,
4238                                       pObjectInfo->FileId.Vnode,
4239                                       pObjectInfo->FileId.Unique,
4240                                       ntStatus));
4241
4242                         break;
4243                     }
4244
4245                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
4246
4247                     //
4248                     // Update file sizes
4249                     //
4250
4251                     if( pObjectInfo->Fcb != NULL)
4252                     {
4253                         FILE_OBJECT *pCCFileObject;
4254
4255                         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4256                                       AFS_TRACE_LEVEL_VERBOSE,
4257                                       "AFSValidateEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
4258                                       &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
4259                                       PsGetCurrentThread()));
4260
4261                         AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
4262                                         TRUE);
4263
4264                         pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
4265
4266                         pObjectInfo->Fcb->Header.AllocationSize.QuadPart  = pObjectInfo->AllocationSize.QuadPart;
4267                         pObjectInfo->Fcb->Header.FileSize.QuadPart        = pObjectInfo->EndOfFile.QuadPart;
4268                         pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
4269
4270                         if ( pCCFileObject != NULL)
4271                         {
4272                             CcSetFileSizes( pCCFileObject,
4273                                             (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
4274                         }
4275
4276                         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4277                                       AFS_TRACE_LEVEL_VERBOSE,
4278                                       "AFSValidateEntry Releasing Fcb SectionObject lock %p EXCL %08lX\n",
4279                                       &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
4280                                       PsGetCurrentThread()));
4281
4282                         AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
4283                     }
4284                 }
4285                 break;
4286             }
4287
4288             case AFS_FILE_TYPE_DIRECTORY:
4289             {
4290
4291                 if( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
4292                 {
4293
4294                     //
4295                     // For a directory or root entry flush the content of
4296                     // the directory enumeration.
4297                     //
4298
4299                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4300                                   AFS_TRACE_LEVEL_VERBOSE,
4301                                   "AFSValidateEntry Acquiring DirectoryNodeHdr.TreeLock lock %p EXCL %08lX\n",
4302                                   pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
4303                                   PsGetCurrentThread()));
4304
4305                     if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
4306                     {
4307
4308                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4309                                       AFS_TRACE_LEVEL_VERBOSE_2,
4310                                       "AFSValidateEntry Validating directory content for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4311                                       &DirEntry->NameInformation.FileName,
4312                                       pObjectInfo->FileId.Cell,
4313                                       pObjectInfo->FileId.Volume,
4314                                       pObjectInfo->FileId.Vnode,
4315                                       pObjectInfo->FileId.Unique));
4316
4317                         AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
4318                                         TRUE);
4319
4320                         ntStatus = AFSValidateDirectoryCache( pObjectInfo,
4321                                                               AuthGroup);
4322
4323                         AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
4324                     }
4325
4326                     if( !NT_SUCCESS( ntStatus))
4327                     {
4328
4329                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4330                                       AFS_TRACE_LEVEL_ERROR,
4331                                       "AFSValidateEntry Failed to re-enumerate %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4332                                       &DirEntry->NameInformation.FileName,
4333                                       pObjectInfo->FileId.Cell,
4334                                       pObjectInfo->FileId.Volume,
4335                                       pObjectInfo->FileId.Vnode,
4336                                       pObjectInfo->FileId.Unique,
4337                                       ntStatus));
4338
4339                         break;
4340                     }
4341                 }
4342
4343                 //
4344                 // Update the metadata for the entry
4345                 //
4346
4347                 ntStatus = AFSUpdateMetaData( DirEntry,
4348                                               pDirEnumEntry);
4349
4350                 if( NT_SUCCESS( ntStatus))
4351                 {
4352
4353                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
4354                 }
4355
4356                 break;
4357             }
4358
4359             default:
4360
4361                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4362                               AFS_TRACE_LEVEL_WARNING,
4363                               "AFSValidateEntry Attempt to verify node of type %d FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4364                               pObjectInfo->FileType,
4365                               FastCall,
4366                               &DirEntry->NameInformation.FileName,
4367                               pObjectInfo->FileId.Cell,
4368                               pObjectInfo->FileId.Volume,
4369                               pObjectInfo->FileId.Vnode,
4370                               pObjectInfo->FileId.Unique));
4371
4372                 break;
4373         }
4374
4375  try_exit:
4376
4377         if( bReleaseFcb)
4378         {
4379
4380             AFSReleaseResource( &pCurrentFcb->NPFcb->Resource);
4381         }
4382
4383         if( pDirEnumEntry != NULL)
4384         {
4385
4386             AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_2_TAG);
4387         }
4388     }
4389
4390     return ntStatus;
4391 }
4392
4393 NTSTATUS
4394 AFSInitializeSpecialShareNameList()
4395 {
4396
4397     NTSTATUS ntStatus = STATUS_SUCCESS;
4398     AFSDirectoryCB *pDirNode = NULL, *pLastDirNode = NULL;
4399     AFSObjectInfoCB *pObjectInfoCB = NULL;
4400     UNICODE_STRING uniShareName;
4401     ULONG ulEntryLength = 0;
4402     AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
4403     LONG lCount;
4404
4405     __Enter
4406     {
4407
4408         RtlInitUnicodeString( &uniShareName,
4409                               L"PIPE");
4410
4411         pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
4412                                                0);
4413
4414         if( pObjectInfoCB == NULL)
4415         {
4416
4417             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4418         }
4419
4420         lCount = AFSObjectInfoIncrement( pObjectInfoCB,
4421                                          AFS_OBJECT_REFERENCE_GLOBAL);
4422
4423         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4424                       AFS_TRACE_LEVEL_VERBOSE,
4425                       "AFSInitializeSpecialShareNameList (srvsvc) Increment count on object %p Cnt %d\n",
4426                       pObjectInfoCB,
4427                       lCount));
4428
4429         pObjectInfoCB->FileType = (ULONG) AFS_FILE_TYPE_SPECIAL_SHARE_NAME;
4430
4431         ulEntryLength = sizeof( AFSDirectoryCB) +
4432                                      uniShareName.Length;
4433
4434         pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
4435                                                                   ulEntryLength,
4436                                                                   AFS_DIR_ENTRY_TAG);
4437
4438         if( pDirNode == NULL)
4439         {
4440
4441             AFSDeleteObjectInfo( &pObjectInfoCB);
4442
4443             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4444         }
4445
4446         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
4447                       AFS_TRACE_LEVEL_VERBOSE,
4448                       "AFSInitializeSpecialShareNameList (srvsvc) AFS_DIR_ENTRY_TAG allocated %p\n",
4449                       pDirNode));
4450
4451         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
4452                                                                                    sizeof( AFSNonPagedDirectoryCB),
4453                                                                                    AFS_DIR_ENTRY_NP_TAG);
4454
4455         if( pNonPagedDirEntry == NULL)
4456         {
4457
4458             ExFreePool( pDirNode);
4459
4460             AFSDeleteObjectInfo( &pObjectInfoCB);
4461
4462             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4463         }
4464
4465         RtlZeroMemory( pDirNode,
4466                        ulEntryLength);
4467
4468         RtlZeroMemory( pNonPagedDirEntry,
4469                        sizeof( AFSNonPagedDirectoryCB));
4470
4471         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
4472
4473         pDirNode->NonPaged = pNonPagedDirEntry;
4474
4475         pDirNode->ObjectInformation = pObjectInfoCB;
4476
4477         //
4478         // Set valid entry
4479         //
4480
4481         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_PIPE_SERVICE);
4482
4483         pDirNode->NameInformation.FileName.Length = uniShareName.Length;
4484
4485         pDirNode->NameInformation.FileName.MaximumLength = uniShareName.Length;
4486
4487         pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
4488
4489         RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
4490                        uniShareName.Buffer,
4491                        pDirNode->NameInformation.FileName.Length);
4492
4493         pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
4494                                                                        TRUE);
4495
4496         AFSSpecialShareNames = pDirNode;
4497
4498         pLastDirNode = pDirNode;
4499
4500
4501         RtlInitUnicodeString( &uniShareName,
4502                               L"IPC$");
4503
4504         pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
4505                                                0);
4506
4507         if( pObjectInfoCB == NULL)
4508         {
4509
4510             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4511         }
4512
4513         lCount = AFSObjectInfoIncrement( pObjectInfoCB,
4514                                          AFS_OBJECT_REFERENCE_GLOBAL);
4515
4516         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4517                       AFS_TRACE_LEVEL_VERBOSE,
4518                       "AFSInitializeSpecialShareNameList (ipc$) Incrementing count on object %p Cnt %d\n",
4519                       pObjectInfoCB,
4520                       lCount));
4521
4522         pObjectInfoCB->FileType = (ULONG) AFS_FILE_TYPE_SPECIAL_SHARE_NAME;
4523
4524         ulEntryLength = sizeof( AFSDirectoryCB) +
4525                                      uniShareName.Length;
4526
4527         pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
4528                                                                   ulEntryLength,
4529                                                                   AFS_DIR_ENTRY_TAG);
4530
4531         if( pDirNode == NULL)
4532         {
4533
4534             AFSDeleteObjectInfo( &pObjectInfoCB);
4535
4536             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4537         }
4538
4539         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
4540                       AFS_TRACE_LEVEL_VERBOSE,
4541                       "AFSInitializeSpecialShareNameList (ipc$) AFS_DIR_ENTRY_TAG allocated %p\n",
4542                       pDirNode));
4543
4544         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
4545                                                                                    sizeof( AFSNonPagedDirectoryCB),
4546                                                                                    AFS_DIR_ENTRY_NP_TAG);
4547
4548         if( pNonPagedDirEntry == NULL)
4549         {
4550
4551             ExFreePool( pDirNode);
4552
4553             AFSDeleteObjectInfo( &pObjectInfoCB);
4554
4555             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4556         }
4557
4558         RtlZeroMemory( pDirNode,
4559                        ulEntryLength);
4560
4561         RtlZeroMemory( pNonPagedDirEntry,
4562                        sizeof( AFSNonPagedDirectoryCB));
4563
4564         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
4565
4566         pDirNode->NonPaged = pNonPagedDirEntry;
4567
4568         pDirNode->ObjectInformation = pObjectInfoCB;
4569
4570         //
4571         // Set valid entry
4572         //
4573
4574         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_IPC);
4575
4576         pDirNode->NameInformation.FileName.Length = uniShareName.Length;
4577
4578         pDirNode->NameInformation.FileName.MaximumLength = uniShareName.Length;
4579
4580         pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
4581
4582         RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
4583                        uniShareName.Buffer,
4584                        pDirNode->NameInformation.FileName.Length);
4585
4586         pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
4587                                                                        TRUE);
4588
4589         pLastDirNode->ListEntry.fLink = pDirNode;
4590
4591         pDirNode->ListEntry.bLink = pLastDirNode;
4592
4593 try_exit:
4594
4595         if( !NT_SUCCESS( ntStatus))
4596         {
4597
4598             if( AFSSpecialShareNames != NULL)
4599             {
4600
4601                 pDirNode = AFSSpecialShareNames;
4602
4603                 while( pDirNode != NULL)
4604                 {
4605
4606                     pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
4607
4608                     AFSDeleteObjectInfo( &pDirNode->ObjectInformation);
4609
4610                     ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
4611
4612                     ExFreePool( pDirNode->NonPaged);
4613
4614                     ExFreePool( pDirNode);
4615
4616                     pDirNode = pLastDirNode;
4617                 }
4618
4619                 AFSSpecialShareNames = NULL;
4620             }
4621         }
4622     }
4623
4624     return ntStatus;
4625 }
4626
4627 AFSDirectoryCB *
4628 AFSGetSpecialShareNameEntry( IN UNICODE_STRING *ShareName,
4629                              IN UNICODE_STRING *SecondaryName)
4630 {
4631
4632     AFSDirectoryCB *pDirectoryCB = NULL;
4633     ULONGLONG ullHash = 0;
4634     UNICODE_STRING uniFullShareName;
4635
4636     __Enter
4637     {
4638
4639
4640         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4641                       AFS_TRACE_LEVEL_VERBOSE_2,
4642                       "AFSGetSpecialShareNameEntry share name %wZ secondary name %wZ\n",
4643                       ShareName,
4644                       SecondaryName));
4645
4646         uniFullShareName = *ShareName;
4647
4648         //
4649         // Generate our hash value
4650         //
4651
4652         ullHash = AFSGenerateCRC( &uniFullShareName,
4653                                   TRUE);
4654
4655         //
4656         // Loop through our special share names to see if this is one of them
4657         //
4658
4659         pDirectoryCB = AFSSpecialShareNames;
4660
4661         while( pDirectoryCB != NULL)
4662         {
4663
4664             if( ullHash == pDirectoryCB->CaseInsensitiveTreeEntry.HashIndex)
4665             {
4666
4667                 break;
4668             }
4669
4670             pDirectoryCB = (AFSDirectoryCB *)pDirectoryCB->ListEntry.fLink;
4671         }
4672     }
4673
4674     return pDirectoryCB;
4675 }
4676
4677 void
4678 AFSWaitOnQueuedFlushes( IN AFSFcb *Fcb)
4679 {
4680
4681     //
4682     // Block on the queue flush event
4683     //
4684
4685     KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
4686                            Executive,
4687                            KernelMode,
4688                            FALSE,
4689                            NULL);
4690
4691     return;
4692 }
4693
4694 void
4695 AFSWaitOnQueuedReleases()
4696 {
4697
4698     AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
4699
4700     //
4701     // Block on the queue flush event
4702     //
4703
4704     KeWaitForSingleObject( &pRDRDeviceExt->Specific.RDR.QueuedReleaseExtentEvent,
4705                            Executive,
4706                            KernelMode,
4707                            FALSE,
4708                            NULL);
4709
4710     return;
4711 }
4712
4713 BOOLEAN
4714 AFSIsEqualFID( IN AFSFileID *FileId1,
4715                IN AFSFileID *FileId2)
4716 {
4717
4718     BOOLEAN bIsEqual = FALSE;
4719
4720     if( FileId1->Hash == FileId2->Hash &&
4721         FileId1->Unique == FileId2->Unique &&
4722         FileId1->Vnode == FileId2->Vnode &&
4723         FileId1->Volume == FileId2->Volume &&
4724         FileId1->Cell == FileId2->Cell)
4725     {
4726
4727         bIsEqual = TRUE;
4728     }
4729
4730     return bIsEqual;
4731 }
4732
4733 NTSTATUS
4734 AFSResetDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB)
4735 {
4736
4737     NTSTATUS ntStatus = STATUS_SUCCESS;
4738     AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
4739
4740     __Enter
4741     {
4742
4743         ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
4744
4745         //
4746         // Reset the directory list information
4747         //
4748
4749         pCurrentDirEntry = ObjectInfoCB->Specific.Directory.DirectoryNodeListHead;
4750
4751         while( pCurrentDirEntry != NULL)
4752         {
4753
4754             pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
4755
4756             if( pCurrentDirEntry->DirOpenReferenceCount <= 0 &&
4757                 pCurrentDirEntry->NameArrayReferenceCount <= 0)
4758             {
4759
4760                 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
4761                               AFS_TRACE_LEVEL_VERBOSE,
4762                               "AFSResetDirectoryContent Deleting dir entry %p for %wZ\n",
4763                               pCurrentDirEntry,
4764                               &pCurrentDirEntry->NameInformation.FileName));
4765
4766                 AFSDeleteDirEntry( ObjectInfoCB,
4767                                    pCurrentDirEntry);
4768             }
4769             else
4770             {
4771
4772                 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
4773                               AFS_TRACE_LEVEL_VERBOSE,
4774                               "AFSResetDirectoryContent Setting DELETE flag in dir entry %p for %wZ\n",
4775                               pCurrentDirEntry,
4776                               &pCurrentDirEntry->NameInformation.FileName));
4777
4778                 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
4779
4780                 AFSRemoveNameEntry( ObjectInfoCB,
4781                                     pCurrentDirEntry);
4782             }
4783
4784             pCurrentDirEntry = pNextDirEntry;
4785         }
4786
4787         ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = NULL;
4788
4789         ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = NULL;
4790
4791         ObjectInfoCB->Specific.Directory.ShortNameTree = NULL;
4792
4793         ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = NULL;
4794
4795         ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = NULL;
4796
4797         ObjectInfoCB->Specific.Directory.DirectoryNodeCount = 0;
4798
4799         AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
4800                       AFS_TRACE_LEVEL_VERBOSE,
4801                       "AFSResetDirectoryContent Reset count to 0 on parent FID %08lX-%08lX-%08lX-%08lX\n",
4802                       ObjectInfoCB->FileId.Cell,
4803                       ObjectInfoCB->FileId.Volume,
4804                       ObjectInfoCB->FileId.Vnode,
4805                       ObjectInfoCB->FileId.Unique));
4806     }
4807
4808     return ntStatus;
4809 }
4810
4811 NTSTATUS
4812 AFSEnumerateGlobalRoot( IN GUID *AuthGroup)
4813 {
4814
4815     NTSTATUS ntStatus = STATUS_SUCCESS;
4816     AFSDirectoryCB *pDirGlobalDirNode = NULL;
4817     UNICODE_STRING uniFullName;
4818
4819     __Enter
4820     {
4821
4822         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4823                       AFS_TRACE_LEVEL_VERBOSE,
4824                       "AFSEnumerateGlobalRoot Acquiring GlobalRoot DirectoryNodeHdr.TreeLock lock %p EXCL %08lX\n",
4825                       AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4826                       PsGetCurrentThread()));
4827
4828         AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
4829                         TRUE);
4830
4831         if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
4832         {
4833
4834             try_return( ntStatus);
4835         }
4836
4837         //
4838         // Initialize the root information
4839         //
4840
4841         AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.ContentIndex = 1;
4842
4843         //
4844         // Enumerate the shares in the volume
4845         //
4846
4847         ntStatus = AFSEnumerateDirectory( AuthGroup,
4848                                           &AFSGlobalRoot->ObjectInformation,
4849                                           TRUE);
4850
4851         if( !NT_SUCCESS( ntStatus))
4852         {
4853
4854             try_return( ntStatus);
4855         }
4856
4857         pDirGlobalDirNode = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead;
4858
4859         uniFullName.MaximumLength = PAGE_SIZE;
4860         uniFullName.Length = 0;
4861
4862         uniFullName.Buffer = (WCHAR *)AFSLibExAllocatePoolWithTag( PagedPool,
4863                                                                    uniFullName.MaximumLength,
4864                                                                    AFS_GENERIC_MEMORY_12_TAG);
4865
4866         if( uniFullName.Buffer == NULL)
4867         {
4868
4869             //
4870             // Reset the directory content
4871             //
4872
4873             AFSResetDirectoryContent( &AFSGlobalRoot->ObjectInformation);
4874
4875             ClearFlag( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
4876
4877             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4878         }
4879
4880         //
4881         // Populate our list of entries in the NP enumeration list
4882         //
4883
4884         while( pDirGlobalDirNode != NULL)
4885         {
4886
4887             uniFullName.Buffer[ 0] = L'\\';
4888             uniFullName.Buffer[ 1] = L'\\';
4889
4890             uniFullName.Length = 2 * sizeof( WCHAR);
4891
4892             RtlCopyMemory( &uniFullName.Buffer[ 2],
4893                            AFSServerName.Buffer,
4894                            AFSServerName.Length);
4895
4896             uniFullName.Length += AFSServerName.Length;
4897
4898             uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)] = L'\\';
4899
4900             uniFullName.Length += sizeof( WCHAR);
4901
4902             RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
4903                            pDirGlobalDirNode->NameInformation.FileName.Buffer,
4904                            pDirGlobalDirNode->NameInformation.FileName.Length);
4905
4906             uniFullName.Length += pDirGlobalDirNode->NameInformation.FileName.Length;
4907
4908             AFSAddConnectionEx( &uniFullName,
4909                                 RESOURCEDISPLAYTYPE_SHARE,
4910                                 0);
4911
4912             pDirGlobalDirNode = (AFSDirectoryCB *)pDirGlobalDirNode->ListEntry.fLink;
4913         }
4914
4915         AFSExFreePoolWithTag( uniFullName.Buffer, 0);
4916
4917 try_exit:
4918
4919         AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
4920     }
4921
4922     return ntStatus;
4923 }
4924
4925 BOOLEAN
4926 AFSIsRelativeName( IN UNICODE_STRING *Name)
4927 {
4928
4929     BOOLEAN bIsRelative = FALSE;
4930
4931     if( Name->Length > 0 &&
4932         Name->Buffer[ 0] != L'\\')
4933     {
4934
4935         bIsRelative = TRUE;
4936     }
4937
4938     return bIsRelative;
4939 }
4940
4941 BOOLEAN
4942 AFSIsAbsoluteAFSName( IN UNICODE_STRING *Name)
4943 {
4944     UNICODE_STRING uniTempName;
4945     BOOLEAN        bIsAbsolute = FALSE;
4946
4947     //
4948     // An absolute AFS path must begin with \afs\... or equivalent
4949     //
4950
4951     if ( Name->Length == 0 ||
4952          Name->Length <= AFSMountRootName.Length + sizeof( WCHAR) ||
4953          Name->Buffer[ 0] != L'\\' ||
4954          Name->Buffer[ AFSMountRootName.Length/sizeof( WCHAR)] != L'\\')
4955     {
4956
4957         return FALSE;
4958     }
4959
4960     uniTempName.Length = AFSMountRootName.Length;
4961     uniTempName.MaximumLength = AFSMountRootName.Length;
4962
4963     uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
4964                                                             uniTempName.MaximumLength,
4965                                                             AFS_NAME_BUFFER_TWO_TAG);
4966
4967     if( uniTempName.Buffer == NULL)
4968     {
4969
4970         return FALSE;
4971     }
4972
4973     RtlCopyMemory( uniTempName.Buffer,
4974                    Name->Buffer,
4975                    AFSMountRootName.Length);
4976
4977     bIsAbsolute = (0 == RtlCompareUnicodeString( &uniTempName,
4978                                                  &AFSMountRootName,
4979                                                  TRUE));
4980
4981     AFSExFreePoolWithTag( uniTempName.Buffer,
4982                           AFS_NAME_BUFFER_TWO_TAG);
4983
4984     return bIsAbsolute;
4985 }
4986
4987
4988 void
4989 AFSUpdateName( IN UNICODE_STRING *Name)
4990 {
4991
4992     USHORT usIndex = 0;
4993
4994     while( usIndex < Name->Length/sizeof( WCHAR))
4995     {
4996
4997         if( Name->Buffer[ usIndex] == L'/')
4998         {
4999
5000             Name->Buffer[ usIndex] = L'\\';
5001         }
5002
5003         usIndex++;
5004     }
5005
5006     return;
5007 }
5008
5009 NTSTATUS
5010 AFSUpdateTargetName( IN OUT UNICODE_STRING *TargetName,
5011                      IN OUT ULONG *Flags,
5012                      IN WCHAR *NameBuffer,
5013                      IN USHORT NameLength)
5014 {
5015
5016     NTSTATUS ntStatus = STATUS_SUCCESS;
5017     WCHAR *pTmpBuffer = NULL;
5018
5019     __Enter
5020     {
5021
5022         //
5023         // If we have enough space then just move in the name otherwise
5024         // allocate a new buffer
5025         //
5026
5027         if( TargetName->Length < NameLength)
5028         {
5029
5030             pTmpBuffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5031                                                             NameLength,
5032                                                             AFS_NAME_BUFFER_FIVE_TAG);
5033
5034             if( pTmpBuffer == NULL)
5035             {
5036
5037                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5038             }
5039
5040             if( BooleanFlagOn( *Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
5041             {
5042
5043                 AFSExFreePoolWithTag( TargetName->Buffer, AFS_NAME_BUFFER_FIVE_TAG);
5044             }
5045
5046             TargetName->MaximumLength = NameLength;
5047
5048             TargetName->Buffer = pTmpBuffer;
5049
5050             SetFlag( *Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER);
5051         }
5052
5053         TargetName->Length = NameLength;
5054
5055         RtlCopyMemory( TargetName->Buffer,
5056                        NameBuffer,
5057                        TargetName->Length);
5058
5059         //
5060         // Update the name in the buffer
5061         //
5062
5063         AFSUpdateName( TargetName);
5064
5065 try_exit:
5066
5067         NOTHING;
5068     }
5069
5070     return ntStatus;
5071 }
5072
5073 AFSNameArrayHdr *
5074 AFSInitNameArray( IN AFSDirectoryCB *DirectoryCB,
5075                   IN ULONG InitialElementCount)
5076 {
5077
5078     AFSNameArrayHdr *pNameArray = NULL;
5079     AFSNameArrayCB *pCurrentElement = NULL;
5080     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
5081     LONG lCount;
5082
5083     __Enter
5084     {
5085
5086         if( InitialElementCount == 0)
5087         {
5088
5089             InitialElementCount = pDevExt->Specific.RDR.NameArrayLength;
5090         }
5091
5092         pNameArray = (AFSNameArrayHdr *)AFSExAllocatePoolWithTag( PagedPool,
5093                                                                   sizeof( AFSNameArrayHdr) +
5094                                                                     (InitialElementCount * sizeof( AFSNameArrayCB)),
5095                                                                   AFS_NAME_ARRAY_TAG);
5096
5097         if( pNameArray == NULL)
5098         {
5099
5100             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5101                           AFS_TRACE_LEVEL_ERROR,
5102                           "AFSInitNameArray Failed to allocate name array\n"));
5103
5104             try_return( pNameArray);
5105         }
5106
5107         RtlZeroMemory( pNameArray,
5108                        sizeof( AFSNameArrayHdr) +
5109                           (InitialElementCount * sizeof( AFSNameArrayCB)));
5110
5111         pNameArray->MaxElementCount = InitialElementCount;
5112
5113         if( DirectoryCB != NULL)
5114         {
5115
5116             pCurrentElement = &pNameArray->ElementArray[ 0];
5117
5118             pNameArray->CurrentEntry = pCurrentElement;
5119
5120             pNameArray->Count = 1;
5121
5122             pNameArray->LinkCount = 0;
5123
5124             lCount = InterlockedIncrement( &DirectoryCB->NameArrayReferenceCount);
5125
5126             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_REF_COUNTING,
5127                           AFS_TRACE_LEVEL_VERBOSE,
5128                           "AFSInitNameArray [NA:%p] Increment count on %wZ DE %p Cnt %d\n",
5129                           pNameArray,
5130                           &DirectoryCB->NameInformation.FileName,
5131                           DirectoryCB,
5132                           lCount));
5133
5134             pCurrentElement->DirectoryCB = DirectoryCB;
5135
5136             pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
5137
5138             pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
5139
5140             if( pCurrentElement->FileId.Vnode == 1)
5141             {
5142
5143                 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5144             }
5145
5146             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5147                           AFS_TRACE_LEVEL_VERBOSE,
5148                           "AFSInitNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5149                           pNameArray,
5150                           pCurrentElement->DirectoryCB,
5151                           pCurrentElement->FileId.Cell,
5152                           pCurrentElement->FileId.Volume,
5153                           pCurrentElement->FileId.Vnode,
5154                           pCurrentElement->FileId.Unique,
5155                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
5156                           pCurrentElement->DirectoryCB->ObjectInformation->FileType));
5157         }
5158
5159 try_exit:
5160
5161         NOTHING;
5162     }
5163
5164     return pNameArray;
5165 }
5166
5167 NTSTATUS
5168 AFSPopulateNameArray( IN AFSNameArrayHdr *NameArray,
5169                       IN UNICODE_STRING *Path,
5170                       IN AFSDirectoryCB *DirectoryCB)
5171 {
5172
5173     NTSTATUS ntStatus = STATUS_SUCCESS;
5174     AFSNameArrayCB *pCurrentElement = NULL;
5175     LONG lCount;
5176
5177     __Enter
5178     {
5179
5180         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5181                       AFS_TRACE_LEVEL_VERBOSE,
5182                       "AFSPopulateNameArray [NA:%p] passed Path %wZ DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5183                       NameArray,
5184                       &Path,
5185                       DirectoryCB,
5186                       DirectoryCB->ObjectInformation->FileId.Cell,
5187                       DirectoryCB->ObjectInformation->FileId.Volume,
5188                       DirectoryCB->ObjectInformation->FileId.Vnode,
5189                       DirectoryCB->ObjectInformation->FileId.Unique,
5190                       &DirectoryCB->NameInformation.FileName,
5191                       DirectoryCB->ObjectInformation->FileType));
5192
5193         //
5194         // Init some info in the header
5195         //
5196
5197         pCurrentElement = &NameArray->ElementArray[ 0];
5198
5199         NameArray->CurrentEntry = pCurrentElement;
5200
5201         //
5202         // The first entry points at the root
5203         //
5204
5205         pCurrentElement->DirectoryCB = DirectoryCB->ObjectInformation->VolumeCB->DirectoryCB;
5206
5207         lCount = InterlockedIncrement( &pCurrentElement->DirectoryCB->NameArrayReferenceCount);
5208
5209         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_REF_COUNTING,
5210                       AFS_TRACE_LEVEL_VERBOSE,
5211                       "AFSPopulateNameArray [NA:%p] Increment count on volume %wZ DE %p Cnt %d\n",
5212                       NameArray,
5213                       &pCurrentElement->DirectoryCB->NameInformation.FileName,
5214                       pCurrentElement->DirectoryCB,
5215                       lCount));
5216
5217         pCurrentElement->Component = DirectoryCB->ObjectInformation->VolumeCB->DirectoryCB->NameInformation.FileName;
5218
5219         pCurrentElement->FileId = DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
5220
5221         pCurrentElement->Flags = 0;
5222
5223         if( pCurrentElement->FileId.Vnode == 1)
5224         {
5225
5226             SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5227         }
5228
5229         NameArray->Count = 1;
5230
5231         NameArray->LinkCount = 0;
5232
5233         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5234                       AFS_TRACE_LEVEL_VERBOSE,
5235                       "AFSPopulateNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5236                       NameArray,
5237                       pCurrentElement->DirectoryCB,
5238                       pCurrentElement->FileId.Cell,
5239                       pCurrentElement->FileId.Volume,
5240                       pCurrentElement->FileId.Vnode,
5241                       pCurrentElement->FileId.Unique,
5242                       &pCurrentElement->DirectoryCB->NameInformation.FileName,
5243                       pCurrentElement->DirectoryCB->ObjectInformation->FileType));
5244
5245         //
5246         // If the root is the parent then we are done ...
5247         //
5248
5249         if( &DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation == DirectoryCB->ObjectInformation)
5250         {
5251             try_return( ntStatus);
5252         }
5253
5254 try_exit:
5255
5256         NOTHING;
5257     }
5258
5259     return ntStatus;
5260 }
5261
5262 NTSTATUS
5263 AFSPopulateNameArrayFromRelatedArray( IN AFSNameArrayHdr *NameArray,
5264                                       IN AFSNameArrayHdr *RelatedNameArray,
5265                                       IN AFSDirectoryCB *DirectoryCB)
5266 {
5267
5268     NTSTATUS ntStatus = STATUS_SUCCESS;
5269     AFSNameArrayCB *pCurrentElement = NULL, *pCurrentRelatedElement = NULL;
5270     LONG lCount;
5271
5272     __Enter
5273     {
5274
5275         if ( DirectoryCB)
5276         {
5277
5278             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5279                           AFS_TRACE_LEVEL_VERBOSE,
5280                           "AFSPopulateNameArray [NA:%p] passed RelatedNameArray %p DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5281                           NameArray,
5282                           RelatedNameArray,
5283                           DirectoryCB,
5284                           DirectoryCB->ObjectInformation->FileId.Cell,
5285                           DirectoryCB->ObjectInformation->FileId.Volume,
5286                           DirectoryCB->ObjectInformation->FileId.Vnode,
5287                           DirectoryCB->ObjectInformation->FileId.Unique,
5288                           &DirectoryCB->NameInformation.FileName,
5289                           DirectoryCB->ObjectInformation->FileType));
5290         }
5291         else
5292         {
5293
5294             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5295                           AFS_TRACE_LEVEL_VERBOSE,
5296                           "AFSPopulateNameArray [NA:%p] passed RelatedNameArray %p DE NULL\n",
5297                           NameArray,
5298                           RelatedNameArray));
5299         }
5300
5301         //
5302         // Init some info in the header
5303         //
5304
5305         pCurrentElement = &NameArray->ElementArray[ 0];
5306
5307         pCurrentRelatedElement = &RelatedNameArray->ElementArray[ 0];
5308
5309         NameArray->Count = 0;
5310
5311         NameArray->LinkCount = RelatedNameArray->LinkCount;
5312
5313         //
5314         // Populate the name array with the data from the related array
5315         //
5316
5317         while( TRUE)
5318         {
5319
5320             pCurrentElement->DirectoryCB = pCurrentRelatedElement->DirectoryCB;
5321
5322             pCurrentElement->Component = pCurrentRelatedElement->DirectoryCB->NameInformation.FileName;
5323
5324             pCurrentElement->FileId    = pCurrentElement->DirectoryCB->ObjectInformation->FileId;
5325
5326             pCurrentElement->Flags = 0;
5327
5328             if( pCurrentElement->FileId.Vnode == 1)
5329             {
5330
5331                 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5332             }
5333
5334             lCount = InterlockedIncrement( &pCurrentElement->DirectoryCB->NameArrayReferenceCount);
5335
5336             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_REF_COUNTING,
5337                           AFS_TRACE_LEVEL_VERBOSE,
5338                           "AFSPopulateNameArrayFromRelatedArray [NA:%p] Increment count on %wZ DE %p Cnt %d\n",
5339                           NameArray,
5340                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
5341                           pCurrentElement->DirectoryCB,
5342                           lCount));
5343
5344             lCount = InterlockedIncrement( &NameArray->Count);
5345
5346             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5347                           AFS_TRACE_LEVEL_VERBOSE,
5348                           "AFSPopulateNameArrayFromRelatedArray [NA:%p] Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5349                           NameArray,
5350                           lCount - 1,
5351                           pCurrentElement->DirectoryCB,
5352                           pCurrentElement->FileId.Cell,
5353                           pCurrentElement->FileId.Volume,
5354                           pCurrentElement->FileId.Vnode,
5355                           pCurrentElement->FileId.Unique,
5356                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
5357                           pCurrentElement->DirectoryCB->ObjectInformation->FileType));
5358
5359             if( pCurrentElement->DirectoryCB == DirectoryCB ||
5360                 NameArray->Count == RelatedNameArray->Count)
5361             {
5362
5363                 //
5364                 // Done ...
5365                 //
5366
5367                 break;
5368             }
5369
5370             pCurrentElement++;
5371
5372             pCurrentRelatedElement++;
5373         }
5374
5375         NameArray->CurrentEntry = NameArray->Count > 0 ? pCurrentElement : NULL;
5376     }
5377
5378     return ntStatus;
5379 }
5380
5381 NTSTATUS
5382 AFSFreeNameArray( IN AFSNameArrayHdr *NameArray)
5383 {
5384
5385     NTSTATUS ntStatus = STATUS_SUCCESS;
5386     AFSNameArrayCB *pCurrentElement = NULL;
5387     LONG lCount, lElement;
5388
5389     __Enter
5390     {
5391
5392         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5393                       AFS_TRACE_LEVEL_VERBOSE,
5394                       "AFSFreeNameArray [NA:%p]\n",
5395                       NameArray));
5396
5397         for ( lElement = 0; lElement < NameArray->Count; lElement++)
5398         {
5399
5400             pCurrentElement = &NameArray->ElementArray[ lElement];
5401
5402             lCount = InterlockedDecrement( &pCurrentElement->DirectoryCB->NameArrayReferenceCount);
5403
5404             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_REF_COUNTING,
5405                           AFS_TRACE_LEVEL_VERBOSE,
5406                           "AFSFreeNameArray [NA:%p] Decrement count on %wZ DE %p Cnt %d\n",
5407                           NameArray,
5408                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
5409                           pCurrentElement->DirectoryCB,
5410                           lCount));
5411
5412             ASSERT( lCount >= 0);
5413         }
5414
5415         AFSExFreePoolWithTag( NameArray, AFS_NAME_ARRAY_TAG);
5416     }
5417
5418     return ntStatus;
5419 }
5420
5421 NTSTATUS
5422 AFSInsertNextElement( IN AFSNameArrayHdr *NameArray,
5423                       IN AFSDirectoryCB *DirectoryCB)
5424 {
5425
5426     NTSTATUS ntStatus = STATUS_SUCCESS;
5427     AFSNameArrayCB *pCurrentElement = NULL;
5428     LONG lCount;
5429
5430     __Enter
5431     {
5432
5433         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5434                       AFS_TRACE_LEVEL_VERBOSE,
5435                       "AFSInsertNextElement [NA:%p] passed DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5436                       NameArray,
5437                       DirectoryCB,
5438                       DirectoryCB->ObjectInformation->FileId.Cell,
5439                       DirectoryCB->ObjectInformation->FileId.Volume,
5440                       DirectoryCB->ObjectInformation->FileId.Vnode,
5441                       DirectoryCB->ObjectInformation->FileId.Unique,
5442                       &DirectoryCB->NameInformation.FileName,
5443                       DirectoryCB->ObjectInformation->FileType));
5444
5445         if( NameArray->Count == (LONG) NameArray->MaxElementCount)
5446         {
5447
5448             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5449                           AFS_TRACE_LEVEL_ERROR,
5450                           "AFSInsertNextElement [NA:%p] Name has reached Maximum Size\n",
5451                           NameArray));
5452
5453             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5454         }
5455
5456         for ( lCount = 0; lCount < NameArray->Count; lCount++)
5457         {
5458
5459             if ( AFSIsEqualFID( &NameArray->ElementArray[ lCount].FileId,
5460                                 &DirectoryCB->ObjectInformation->FileId) )
5461             {
5462
5463                 AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5464                               AFS_TRACE_LEVEL_WARNING,
5465                               "AFSInsertNextElement [NA:%p] DE %p recursion Status %08X\n",
5466                               NameArray,
5467                               DirectoryCB,
5468                               STATUS_ACCESS_DENIED));
5469
5470                 try_return( ntStatus = STATUS_ACCESS_DENIED);
5471             }
5472         }
5473
5474         if( NameArray->Count > 0)
5475         {
5476
5477             NameArray->CurrentEntry++;
5478         }
5479         else
5480         {
5481             NameArray->CurrentEntry = &NameArray->ElementArray[ 0];
5482         }
5483
5484         pCurrentElement = NameArray->CurrentEntry;
5485
5486         lCount = InterlockedIncrement( &NameArray->Count);
5487
5488         lCount = InterlockedIncrement( &DirectoryCB->NameArrayReferenceCount);
5489
5490         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_REF_COUNTING,
5491                       AFS_TRACE_LEVEL_VERBOSE,
5492                       "AFSInsertNextElement [NA:%p] Increment count on %wZ DE %p Cnt %d\n",
5493                       NameArray,
5494                       &DirectoryCB->NameInformation.FileName,
5495                       DirectoryCB,
5496                       lCount));
5497
5498         ASSERT( lCount > 0);
5499
5500         pCurrentElement->DirectoryCB = DirectoryCB;
5501
5502         pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
5503
5504         pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
5505
5506         pCurrentElement->Flags = 0;
5507
5508         if( pCurrentElement->FileId.Vnode == 1)
5509         {
5510
5511             SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5512         }
5513
5514         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5515                       AFS_TRACE_LEVEL_VERBOSE,
5516                       "AFSInsertNextElement [NA:%p] Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5517                       NameArray,
5518                       NameArray->Count - 1,
5519                       pCurrentElement->DirectoryCB,
5520                       pCurrentElement->FileId.Cell,
5521                       pCurrentElement->FileId.Volume,
5522                       pCurrentElement->FileId.Vnode,
5523                       pCurrentElement->FileId.Unique,
5524                       &pCurrentElement->DirectoryCB->NameInformation.FileName,
5525                       pCurrentElement->DirectoryCB->ObjectInformation->FileType));
5526
5527 try_exit:
5528
5529         NOTHING;
5530     }
5531
5532     return ntStatus;
5533 }
5534
5535 AFSDirectoryCB *
5536 AFSBackupEntry( IN AFSNameArrayHdr *NameArray)
5537 {
5538
5539     AFSDirectoryCB *pDirectoryCB = NULL;
5540     AFSNameArrayCB *pCurrentElement = NULL;
5541     BOOLEAN         bVolumeRoot = FALSE;
5542     LONG lCount;
5543
5544     __Enter
5545     {
5546
5547         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5548                       AFS_TRACE_LEVEL_VERBOSE,
5549                       "AFSBackupEntry [NA:%p]\n",
5550                       NameArray));
5551
5552         if( NameArray->Count == 0)
5553         {
5554
5555             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5556                           AFS_TRACE_LEVEL_ERROR,
5557                           "AFSBackupEntry [NA:%p] No more entries\n",
5558                           NameArray));
5559
5560             try_return( pCurrentElement);
5561         }
5562
5563         lCount = InterlockedDecrement( &NameArray->CurrentEntry->DirectoryCB->NameArrayReferenceCount);
5564
5565         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_REF_COUNTING,
5566                       AFS_TRACE_LEVEL_VERBOSE,
5567                       "AFSBackupEntry [NA:%p] Decrement count on %wZ DE %p Cnt %d\n",
5568                       NameArray,
5569                       &NameArray->CurrentEntry->DirectoryCB->NameInformation.FileName,
5570                       NameArray->CurrentEntry->DirectoryCB,
5571                       lCount));
5572
5573         ASSERT( lCount >= 0);
5574
5575         NameArray->CurrentEntry->DirectoryCB = NULL;
5576
5577         lCount = InterlockedDecrement( &NameArray->Count);
5578
5579         if( lCount == 0)
5580         {
5581             NameArray->CurrentEntry = NULL;
5582
5583             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5584                           AFS_TRACE_LEVEL_ERROR,
5585                           "AFSBackupEntry [NA:%p] No more entries\n",
5586                           NameArray));
5587         }
5588         else
5589         {
5590
5591             bVolumeRoot = BooleanFlagOn( NameArray->CurrentEntry->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5592
5593             NameArray->CurrentEntry--;
5594
5595             pCurrentElement = NameArray->CurrentEntry;
5596
5597             pDirectoryCB = pCurrentElement->DirectoryCB;
5598
5599             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5600                           AFS_TRACE_LEVEL_VERBOSE,
5601                           "AFSBackupEntry [NA:%p] Returning Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5602                           NameArray,
5603                           NameArray->Count - 1,
5604                           pCurrentElement->DirectoryCB,
5605                           pCurrentElement->FileId.Cell,
5606                           pCurrentElement->FileId.Volume,
5607                           pCurrentElement->FileId.Vnode,
5608                           pCurrentElement->FileId.Unique,
5609                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
5610                           pCurrentElement->DirectoryCB->ObjectInformation->FileType));
5611
5612             //
5613             // If the entry we are removing is a volume root,
5614             // we must remove the mount point entry as well.
5615             // If the NameArray was constructed by checking the
5616             // share name via the service, the name array can
5617             // contain two volume roots in sequence without a
5618             // mount point separating them.
5619             //
5620
5621             if ( bVolumeRoot &&
5622                  !BooleanFlagOn( NameArray->CurrentEntry->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT))
5623             {
5624
5625                 pDirectoryCB = AFSBackupEntry( NameArray);
5626             }
5627         }
5628
5629
5630 try_exit:
5631
5632         NOTHING;
5633     }
5634
5635     return pDirectoryCB;
5636 }
5637
5638 AFSDirectoryCB *
5639 AFSGetParentEntry( IN AFSNameArrayHdr *NameArray)
5640 {
5641
5642     AFSDirectoryCB *pDirEntry = NULL;
5643     AFSNameArrayCB *pElement = NULL;
5644
5645     __Enter
5646     {
5647
5648         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5649                       AFS_TRACE_LEVEL_VERBOSE,
5650                       "AFSGetParentEntry [NA:%p]\n",
5651                       NameArray));
5652
5653         if( NameArray->Count == 0 ||
5654             NameArray->Count == 1)
5655         {
5656
5657             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5658                           AFS_TRACE_LEVEL_ERROR,
5659                           "AFSGetParentEntry [NA:%p] No more entries\n",
5660                           NameArray));
5661
5662             try_return( pDirEntry = NULL);
5663         }
5664
5665         pElement = &NameArray->ElementArray[ NameArray->Count - 2];
5666
5667         pDirEntry = pElement->DirectoryCB;
5668
5669         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5670                       AFS_TRACE_LEVEL_VERBOSE,
5671                       "AFSGetParentEntry [NA:%p] Returning Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5672                       NameArray,
5673                       NameArray->Count - 2,
5674                       pElement->DirectoryCB,
5675                       pElement->FileId.Cell,
5676                       pElement->FileId.Volume,
5677                       pElement->FileId.Vnode,
5678                       pElement->FileId.Unique,
5679                       &pElement->DirectoryCB->NameInformation.FileName,
5680                       pElement->DirectoryCB->ObjectInformation->FileType));
5681
5682 try_exit:
5683
5684         NOTHING;
5685     }
5686
5687     return pDirEntry;
5688 }
5689
5690 void
5691 AFSResetNameArray( IN AFSNameArrayHdr *NameArray,
5692                    IN AFSDirectoryCB *DirectoryCB)
5693 {
5694
5695     AFSNameArrayCB *pCurrentElement = NULL;
5696     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
5697     LONG lCount, lElement;
5698
5699     __Enter
5700     {
5701
5702         AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5703                       AFS_TRACE_LEVEL_VERBOSE,
5704                       "AFSResetNameArray [NA:%p] passed DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5705                       NameArray,
5706                       DirectoryCB,
5707                       DirectoryCB->ObjectInformation->FileId.Cell,
5708                       DirectoryCB->ObjectInformation->FileId.Volume,
5709                       DirectoryCB->ObjectInformation->FileId.Vnode,
5710                       DirectoryCB->ObjectInformation->FileId.Unique,
5711                       &DirectoryCB->NameInformation.FileName,
5712                       DirectoryCB->ObjectInformation->FileType));
5713
5714         //
5715         // Dereference previous name array contents
5716         //
5717
5718         for ( lElement = 0; lElement < NameArray->Count; lElement++)
5719         {
5720
5721             pCurrentElement = &NameArray->ElementArray[ lElement];
5722
5723             lCount = InterlockedDecrement( &pCurrentElement->DirectoryCB->NameArrayReferenceCount);
5724
5725             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_REF_COUNTING,
5726                           AFS_TRACE_LEVEL_VERBOSE,
5727                           "AFSResetNameArray [NA:%p] Decrement count on %wZ DE %p Cnt %d\n",
5728                           NameArray,
5729                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
5730                           pCurrentElement->DirectoryCB,
5731                           lCount));
5732
5733             ASSERT( lCount >= 0);
5734         }
5735
5736         RtlZeroMemory( NameArray,
5737                        sizeof( AFSNameArrayHdr) +
5738                           ((pDevExt->Specific.RDR.NameArrayLength - 1) * sizeof( AFSNameArrayCB)));
5739
5740         NameArray->MaxElementCount = pDevExt->Specific.RDR.NameArrayLength;
5741
5742         if( DirectoryCB != NULL)
5743         {
5744
5745             pCurrentElement = &NameArray->ElementArray[ 0];
5746
5747             NameArray->CurrentEntry = pCurrentElement;
5748
5749             NameArray->Count = 1;
5750
5751             NameArray->LinkCount = 0;
5752
5753             lCount = InterlockedIncrement( &DirectoryCB->NameArrayReferenceCount);
5754
5755             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_REF_COUNTING,
5756                           AFS_TRACE_LEVEL_VERBOSE,
5757                           "AFSResetNameArray [NA:%p] Increment count on %wZ DE %p Cnt %d\n",
5758                           NameArray,
5759                           &DirectoryCB->NameInformation.FileName,
5760                           DirectoryCB,
5761                           lCount));
5762
5763             pCurrentElement->DirectoryCB = DirectoryCB;
5764
5765             pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
5766
5767             pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
5768
5769             pCurrentElement->Flags  = 0;
5770
5771             if( pCurrentElement->FileId.Vnode == 1)
5772             {
5773
5774                 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5775             }
5776
5777             AFSDbgTrace(( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5778                           AFS_TRACE_LEVEL_VERBOSE,
5779                           "AFSResetNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5780                           NameArray,
5781                           pCurrentElement->DirectoryCB,
5782                           pCurrentElement->FileId.Cell,
5783                           pCurrentElement->FileId.Volume,
5784                           pCurrentElement->FileId.Vnode,
5785                           pCurrentElement->FileId.Unique,
5786                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
5787                           pCurrentElement->DirectoryCB->ObjectInformation->FileType));
5788         }
5789     }
5790
5791     return;
5792 }
5793
5794 void
5795 AFSDumpNameArray( IN AFSNameArrayHdr *NameArray)
5796 {
5797
5798     AFSNameArrayCB *pCurrentElement = NULL;
5799
5800     pCurrentElement = &NameArray->ElementArray[ 0];
5801
5802     AFSPrint("AFSDumpNameArray Start (%d)\n", NameArray->Count);
5803
5804     while( pCurrentElement->DirectoryCB != NULL)
5805     {
5806
5807         AFSPrint("FID %08lX-%08lX-%08lX-%08lX %wZ\n",
5808                   pCurrentElement->FileId.Cell,
5809                   pCurrentElement->FileId.Volume,
5810                   pCurrentElement->FileId.Vnode,
5811                   pCurrentElement->FileId.Unique,
5812                   &pCurrentElement->DirectoryCB->NameInformation.FileName);
5813
5814         pCurrentElement++;
5815     }
5816
5817     AFSPrint("AFSDumpNameArray End\n\n");
5818
5819     return;
5820 }
5821
5822 void
5823 AFSSetEnumerationEvent( IN AFSFcb *Fcb)
5824 {
5825     LONG lCount;
5826
5827     //
5828     // Depending on the type of node, set the event
5829     //
5830
5831     switch( Fcb->Header.NodeTypeCode)
5832     {
5833
5834         case AFS_DIRECTORY_FCB:
5835         case AFS_ROOT_FCB:
5836         case AFS_ROOT_ALL:
5837         {
5838
5839             lCount = InterlockedIncrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
5840
5841             break;
5842         }
5843     }
5844
5845     return;
5846 }
5847
5848 void
5849 AFSClearEnumerationEvent( IN AFSFcb *Fcb)
5850 {
5851
5852     LONG lCount;
5853
5854     //
5855     // Depending on the type of node, set the event
5856     //
5857
5858     switch( Fcb->Header.NodeTypeCode)
5859     {
5860
5861         case AFS_DIRECTORY_FCB:
5862         case AFS_ROOT_FCB:
5863         case AFS_ROOT_ALL:
5864         {
5865
5866             ASSERT( Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0);
5867
5868             lCount = InterlockedDecrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
5869
5870             break;
5871         }
5872     }
5873
5874     return;
5875 }
5876
5877 BOOLEAN
5878 AFSIsEnumerationInProcess( IN AFSObjectInfoCB *ObjectInfo)
5879 {
5880
5881     BOOLEAN bIsInProcess = FALSE;
5882
5883     __Enter
5884     {
5885
5886         if( ObjectInfo->Fcb == NULL)
5887         {
5888
5889             try_return( bIsInProcess);
5890         }
5891
5892         switch( ObjectInfo->Fcb->Header.NodeTypeCode)
5893         {
5894
5895             case AFS_DIRECTORY_FCB:
5896             case AFS_ROOT_FCB:
5897             case AFS_ROOT_ALL:
5898             {
5899
5900                 if( ObjectInfo->Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0)
5901                 {
5902
5903                     bIsInProcess = TRUE;
5904                 }
5905
5906                 break;
5907             }
5908         }
5909
5910 try_exit:
5911
5912         NOTHING;
5913     }
5914
5915     return bIsInProcess;
5916 }
5917
5918 NTSTATUS
5919 AFSVerifyVolume( IN ULONGLONG ProcessId,
5920                  IN AFSVolumeCB *VolumeCB)
5921 {
5922
5923     UNREFERENCED_PARAMETER(ProcessId);
5924     UNREFERENCED_PARAMETER(VolumeCB);
5925     NTSTATUS ntStatus = STATUS_SUCCESS;
5926
5927
5928     return ntStatus;
5929 }
5930
5931 NTSTATUS
5932 AFSInitPIOCtlDirectoryCB( IN AFSObjectInfoCB *ParentObjectInfo)
5933 {
5934
5935     NTSTATUS ntStatus = STATUS_SUCCESS;
5936     AFSObjectInfoCB *pObjectInfoCB = NULL;
5937     AFSDirectoryCB *pDirNode = NULL;
5938     ULONG ulEntryLength = 0;
5939     AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
5940     LONG lCount;
5941
5942     __Enter
5943     {
5944
5945         pObjectInfoCB = AFSAllocateObjectInfo( ParentObjectInfo,
5946                                                0);
5947
5948         if( pObjectInfoCB == NULL)
5949         {
5950
5951             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5952         }
5953
5954         lCount = AFSObjectInfoIncrement( pObjectInfoCB,
5955                                          AFS_OBJECT_REFERENCE_DIRENTRY);
5956
5957         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
5958                       AFS_TRACE_LEVEL_VERBOSE,
5959                       "AFSInitPIOCtlDirectoryCB Increment count on object %p Cnt %d\n",
5960                       pObjectInfoCB,
5961                       lCount));
5962
5963         pObjectInfoCB->FileType = (ULONG) AFS_FILE_TYPE_PIOCTL;
5964
5965         pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
5966
5967         ulEntryLength = sizeof( AFSDirectoryCB) + AFSPIOCtlName.Length;
5968
5969         pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
5970                                                                ulEntryLength,
5971                                                                AFS_DIR_ENTRY_TAG);
5972
5973         if( pDirNode == NULL)
5974         {
5975
5976             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5977         }
5978
5979         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
5980                       AFS_TRACE_LEVEL_VERBOSE,
5981                       "AFSInitPIOCtlDirectoryCB AFS_DIR_ENTRY_TAG allocated %p\n",
5982                       pDirNode));
5983
5984         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
5985                                                                                 sizeof( AFSNonPagedDirectoryCB),
5986                                                                                 AFS_DIR_ENTRY_NP_TAG);
5987
5988         if( pNonPagedDirEntry == NULL)
5989         {
5990
5991             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5992         }
5993
5994         RtlZeroMemory( pDirNode,
5995                        ulEntryLength);
5996
5997         RtlZeroMemory( pNonPagedDirEntry,
5998                        sizeof( AFSNonPagedDirectoryCB));
5999
6000         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
6001
6002         pDirNode->NonPaged = pNonPagedDirEntry;
6003
6004         pDirNode->ObjectInformation = pObjectInfoCB;
6005
6006         pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_PIOCTL_INDEX;
6007
6008         //
6009         // Set valid entry
6010         //
6011
6012         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_FAKE);
6013
6014         pDirNode->NameInformation.FileName.Length = AFSPIOCtlName.Length;
6015
6016         pDirNode->NameInformation.FileName.MaximumLength = AFSPIOCtlName.Length;
6017
6018         pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
6019
6020         RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
6021                        AFSPIOCtlName.Buffer,
6022                        pDirNode->NameInformation.FileName.Length);
6023
6024         pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
6025                                                                        TRUE);
6026
6027         if ( InterlockedCompareExchangePointer( (PVOID *)&ParentObjectInfo->Specific.Directory.PIOCtlDirectoryCB, pDirNode, NULL) != NULL)
6028         {
6029
6030             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
6031                           AFS_TRACE_LEVEL_WARNING,
6032                           "AFSInitPIOCtlDirectoryCB Raced PIOCtlDirectoryCB %p pFcb %p\n",
6033                           ParentObjectInfo->Specific.Directory.PIOCtlDirectoryCB,
6034                           pDirNode));
6035
6036             try_return( ntStatus = STATUS_REPARSE);
6037         }
6038
6039 try_exit:
6040
6041         if ( ntStatus != STATUS_SUCCESS)
6042         {
6043
6044             if ( pDirNode != NULL)
6045             {
6046
6047                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
6048                               AFS_TRACE_LEVEL_VERBOSE,
6049                               "AFSInitPIOCtlDirectoryCB AFS_DIR_ENTRY_TAG deallocating %p\n",
6050                               pDirNode));
6051
6052                 AFSExFreePoolWithTag( pDirNode, AFS_DIR_ENTRY_TAG);
6053             }
6054
6055             if( pNonPagedDirEntry != NULL)
6056             {
6057
6058                 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
6059
6060                 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
6061             }
6062
6063             if ( pObjectInfoCB != NULL)
6064             {
6065
6066                 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
6067                                                  AFS_OBJECT_REFERENCE_DIRENTRY);
6068
6069                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
6070                               AFS_TRACE_LEVEL_VERBOSE,
6071                               "AFSInitPIOCtlDirectoryCB Decrement count on object %p Cnt %d\n",
6072                               pObjectInfoCB,
6073                               lCount));
6074
6075                 AFSDeleteObjectInfo( &pObjectInfoCB);
6076             }
6077         }
6078     }
6079
6080     return ntStatus;
6081 }
6082
6083 NTSTATUS
6084 AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB,
6085                            IN AFSDirectoryCB *DirectoryCB,
6086                            IN UNICODE_STRING *ParentPathName,
6087                            IN AFSNameArrayHdr *RelatedNameArray,
6088                            IN GUID           *AuthGroup,
6089                            OUT AFSFileInfoCB *FileInfo)
6090 {
6091
6092     NTSTATUS ntStatus = STATUS_SUCCESS;
6093     AFSDirEnumEntry *pDirEntry = NULL;
6094     UNICODE_STRING uniFullPathName = {0};
6095     AFSNameArrayHdr    *pNameArray = NULL;
6096     AFSVolumeCB *pVolumeCB = NULL;
6097     LONG VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
6098     AFSVolumeCB *pNewVolumeCB = NULL;
6099     LONG NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
6100     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
6101     AFSDirectoryCB *pNewParentDirEntry = NULL;
6102     WCHAR *pwchBuffer = NULL;
6103     UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
6104     ULONG ulNameDifference = 0;
6105     LONG lCount;
6106
6107     __Enter
6108     {
6109
6110         //
6111         // Retrieve a target name for the entry
6112         //
6113
6114         AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
6115                           TRUE);
6116
6117         if( DirectoryCB->NameInformation.TargetName.Length == 0)
6118         {
6119
6120             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6121
6122             ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
6123                                               AuthGroup,
6124                                               FALSE,
6125                                               &pDirEntry);
6126
6127             if( !NT_SUCCESS( ntStatus) ||
6128                 pDirEntry->TargetNameLength == 0)
6129             {
6130
6131                 if( pDirEntry != NULL)
6132                 {
6133
6134                     ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
6135                 }
6136
6137                 try_return( ntStatus);
6138             }
6139
6140             AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
6141                             TRUE);
6142
6143             if( DirectoryCB->NameInformation.TargetName.Length == 0)
6144             {
6145
6146                 //
6147                 // Update the target name
6148                 //
6149
6150                 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
6151                                                 &DirectoryCB->Flags,
6152                                                 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
6153                                                 (USHORT)pDirEntry->TargetNameLength);
6154
6155                 if( !NT_SUCCESS( ntStatus))
6156                 {
6157
6158                     AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6159
6160                     try_return( ntStatus);
6161                 }
6162             }
6163
6164             AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
6165         }
6166
6167         //
6168         // Need to pass the full path in for parsing.
6169         //
6170
6171         if( AFSIsRelativeName( &DirectoryCB->NameInformation.TargetName))
6172         {
6173
6174             uniFullPathName.Length = 0;
6175             uniFullPathName.MaximumLength = ParentPathName->Length +
6176                                                     sizeof( WCHAR) +
6177                                                     DirectoryCB->NameInformation.TargetName.Length;
6178
6179             uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6180                                                                         uniFullPathName.MaximumLength,
6181                                                                         AFS_NAME_BUFFER_SIX_TAG);
6182
6183             if( uniFullPathName.Buffer == NULL)
6184             {
6185
6186                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6187
6188                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6189             }
6190
6191             pwchBuffer = uniFullPathName.Buffer;
6192
6193             RtlZeroMemory( uniFullPathName.Buffer,
6194                            uniFullPathName.MaximumLength);
6195
6196             RtlCopyMemory( uniFullPathName.Buffer,
6197                            ParentPathName->Buffer,
6198                            ParentPathName->Length);
6199
6200             uniFullPathName.Length = ParentPathName->Length;
6201
6202             if( uniFullPathName.Buffer[ (uniFullPathName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
6203                 DirectoryCB->NameInformation.TargetName.Buffer[ 0] != L'\\')
6204             {
6205
6206                 uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)] = L'\\';
6207
6208                 uniFullPathName.Length += sizeof( WCHAR);
6209             }
6210
6211             RtlCopyMemory( &uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)],
6212                            DirectoryCB->NameInformation.TargetName.Buffer,
6213                            DirectoryCB->NameInformation.TargetName.Length);
6214
6215             uniFullPathName.Length += DirectoryCB->NameInformation.TargetName.Length;
6216
6217             uniParsedName.Length = uniFullPathName.Length - ParentPathName->Length;
6218             uniParsedName.MaximumLength = uniParsedName.Length;
6219
6220             uniParsedName.Buffer = &uniFullPathName.Buffer[ ParentPathName->Length/sizeof( WCHAR)];
6221
6222             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6223
6224             //
6225             // We populate up to the current parent
6226             //
6227
6228             if( RelatedNameArray != NULL)
6229             {
6230
6231                 pNameArray = AFSInitNameArray( NULL,
6232                                                RelatedNameArray->MaxElementCount);
6233
6234                 if( pNameArray == NULL)
6235                 {
6236
6237                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6238                 }
6239
6240                 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
6241                                                                  RelatedNameArray,
6242                                                                  ParentDirectoryCB);
6243             }
6244             else
6245             {
6246
6247                 pNameArray = AFSInitNameArray( NULL,
6248                                                0);
6249
6250                 if( pNameArray == NULL)
6251                 {
6252
6253                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6254                 }
6255
6256                 ntStatus = AFSPopulateNameArray( pNameArray,
6257                                                  NULL,
6258                                                  ParentDirectoryCB);
6259             }
6260
6261             if( !NT_SUCCESS( ntStatus))
6262             {
6263
6264                 try_return( ntStatus);
6265             }
6266
6267             pVolumeCB = ParentDirectoryCB->ObjectInformation->VolumeCB;
6268
6269             pParentDirEntry = ParentDirectoryCB;
6270         }
6271         else
6272         {
6273
6274             uniFullPathName.Length = 0;
6275             uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
6276
6277             uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6278                                                                         uniFullPathName.MaximumLength,
6279                                                                         AFS_NAME_BUFFER_SEVEN_TAG);
6280
6281             if( uniFullPathName.Buffer == NULL)
6282             {
6283
6284                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6285
6286                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6287             }
6288
6289             pwchBuffer = uniFullPathName.Buffer;
6290
6291             RtlZeroMemory( uniFullPathName.Buffer,
6292                            uniFullPathName.MaximumLength);
6293
6294             RtlCopyMemory( uniFullPathName.Buffer,
6295                            DirectoryCB->NameInformation.TargetName.Buffer,
6296                            DirectoryCB->NameInformation.TargetName.Length);
6297
6298             uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6299
6300             //
6301             // This name should begin with the \afs server so parse it off and check it
6302             //
6303
6304             FsRtlDissectName( uniFullPathName,
6305                               &uniComponentName,
6306                               &uniRemainingPath);
6307
6308             if( RtlCompareUnicodeString( &uniComponentName,
6309                                          &AFSServerName,
6310                                          TRUE) != 0)
6311             {
6312
6313                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6314
6315                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
6316                               AFS_TRACE_LEVEL_ERROR,
6317                               "AFSRetrieveFileAttributes Name %wZ contains invalid server name\n",
6318                               &uniFullPathName));
6319
6320                 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
6321             }
6322
6323             uniFullPathName = uniRemainingPath;
6324
6325             uniParsedName = uniFullPathName;
6326
6327             ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
6328
6329             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6330
6331             //
6332             // Our name array
6333             //
6334
6335             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
6336                                            0);
6337
6338             if( pNameArray == NULL)
6339             {
6340
6341                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6342             }
6343
6344             pVolumeCB = AFSGlobalRoot;
6345
6346             pParentDirEntry = AFSGlobalRoot->DirectoryCB;
6347         }
6348
6349         //
6350         // Increment the ref count on the volume and dir entry for correct processing below
6351         //
6352
6353         VolumeReferenceReason = AFS_VOLUME_REFERENCE_FILE_ATTRS;
6354
6355         lCount = AFSVolumeIncrement( pVolumeCB,
6356                                      VolumeReferenceReason);
6357
6358         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6359                       AFS_TRACE_LEVEL_VERBOSE,
6360                       "AFSRetrieveFileAttributes Increment count on volume %p Reason %u Cnt %d\n",
6361                       pVolumeCB,
6362                       VolumeReferenceReason,
6363                       lCount));
6364
6365         lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
6366
6367         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6368                       AFS_TRACE_LEVEL_VERBOSE,
6369                       "AFSRetrieveFileAttributes Increment count on %wZ DE %p Ccb %p Cnt %d\n",
6370                       &pParentDirEntry->NameInformation.FileName,
6371                       pParentDirEntry,
6372                       NULL,
6373                       lCount));
6374
6375         ntStatus = AFSLocateNameEntry( NULL,
6376                                        NULL,
6377                                        &uniFullPathName,
6378                                        &uniParsedName,
6379                                        pNameArray,
6380                                        AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL,
6381                                        pVolumeCB,
6382                                        pParentDirEntry,
6383                                        &pNewVolumeCB,
6384                                        &NewVolumeReferenceReason,
6385                                        &pNewParentDirEntry,
6386                                        &pDirectoryEntry,
6387                                        NULL);
6388
6389         if ( pNewVolumeCB != NULL)
6390         {
6391             //
6392             // AFSLocateNameEntry returns pNewVolumeCB with a reference held
6393             // even if pVolumeCB == pNewVolumeCB.  It is always safe to release
6394             // the reference on pVolumeCB that was held prior to the call.
6395             // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
6396             // will be released second.
6397             //
6398
6399             lCount = AFSVolumeDecrement( pVolumeCB,
6400                                          VolumeReferenceReason);
6401
6402             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6403                           AFS_TRACE_LEVEL_VERBOSE,
6404                           "AFSRetrieveFileAttributes Decrement count on volume %p Reason %u Cnt %d\n",
6405                           pVolumeCB,
6406                           VolumeReferenceReason,
6407                           lCount));
6408
6409             pVolumeCB = pNewVolumeCB;
6410
6411             pNewVolumeCB = NULL;
6412
6413             VolumeReferenceReason = NewVolumeReferenceReason;
6414
6415             NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
6416         }
6417
6418         //
6419         // AFSLocateNameEntry does not alter the reference count of
6420         // pParentDirectoryCB and it returns pNewParentDirectoryCB with
6421         // a reference held.
6422         //
6423
6424         lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
6425
6426         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6427                       AFS_TRACE_LEVEL_VERBOSE,
6428                       "AFSRetrieveFileAttributes DecrementX count on %wZ DE %p Cnt %d\n",
6429                       &pParentDirEntry->NameInformation.FileName,
6430                       pParentDirEntry,
6431                       lCount));
6432
6433         pParentDirEntry = pNewParentDirEntry;
6434
6435         pNewParentDirEntry = NULL;
6436
6437         if( !NT_SUCCESS( ntStatus) ||
6438             ntStatus == STATUS_REPARSE)
6439         {
6440
6441             try_return( ntStatus);
6442         }
6443
6444         //
6445         // Store off the information
6446         //
6447
6448         FileInfo->FileAttributes = pDirectoryEntry->ObjectInformation->FileAttributes;
6449
6450         //
6451         // Check for the mount point being returned
6452         //
6453
6454         if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
6455             pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DFSLINK)
6456         {
6457
6458             FileInfo->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
6459         }
6460         else if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
6461         {
6462
6463             if ( FileInfo->FileAttributes == FILE_ATTRIBUTE_NORMAL)
6464             {
6465
6466                 FileInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
6467             }
6468             else
6469             {
6470
6471                 FileInfo->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
6472             }
6473         }
6474
6475         FileInfo->AllocationSize = pDirectoryEntry->ObjectInformation->AllocationSize;
6476
6477         FileInfo->EndOfFile = pDirectoryEntry->ObjectInformation->EndOfFile;
6478
6479         FileInfo->CreationTime = pDirectoryEntry->ObjectInformation->CreationTime;
6480
6481         FileInfo->LastAccessTime = pDirectoryEntry->ObjectInformation->LastAccessTime;
6482
6483         FileInfo->LastWriteTime = pDirectoryEntry->ObjectInformation->LastWriteTime;
6484
6485         FileInfo->ChangeTime = pDirectoryEntry->ObjectInformation->ChangeTime;
6486
6487 try_exit:
6488
6489         if( pDirEntry != NULL)
6490         {
6491
6492             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
6493         }
6494
6495         if( pDirectoryEntry != NULL)
6496         {
6497
6498             lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
6499
6500             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6501                           AFS_TRACE_LEVEL_VERBOSE,
6502                           "AFSRetrieveFileAttributes Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6503                           &pDirectoryEntry->NameInformation.FileName,
6504                           pDirectoryEntry,
6505                           NULL,
6506                           lCount));
6507
6508             ASSERT( lCount >= 0);
6509         }
6510
6511         if ( pParentDirEntry != NULL)
6512         {
6513
6514             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
6515
6516             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6517                           AFS_TRACE_LEVEL_VERBOSE,
6518                           "AFSRetrieveFileAttributes Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
6519                           &pParentDirEntry->NameInformation.FileName,
6520                           pParentDirEntry,
6521                           NULL,
6522                           lCount));
6523
6524             ASSERT( lCount >= 0);
6525         }
6526
6527         if( pVolumeCB != NULL)
6528         {
6529
6530             lCount = AFSVolumeDecrement( pVolumeCB,
6531                                          VolumeReferenceReason);
6532
6533             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6534                           AFS_TRACE_LEVEL_VERBOSE,
6535                           "AFSRetrieveFileAttributes Decrement2 count on volume %p Reason %u Cnt %d\n",
6536                           pVolumeCB,
6537                           VolumeReferenceReason,
6538                           lCount));
6539         }
6540
6541         if( pNameArray != NULL)
6542         {
6543
6544             AFSFreeNameArray( pNameArray);
6545         }
6546
6547         if( pwchBuffer != NULL)
6548         {
6549
6550             //
6551             // Always free the buffer that we allocated as AFSLocateNameEntry
6552             // will not free it.  If uniFullPathName.Buffer was allocated by
6553             // AFSLocateNameEntry, then we must free that as well.
6554             // Check that the uniFullPathName.Buffer in the string is not the same
6555             // offset by the length of the server name
6556             //
6557
6558             if( uniFullPathName.Length > 0 &&
6559                 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
6560             {
6561
6562                 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
6563             }
6564
6565             AFSExFreePoolWithTag( pwchBuffer, 0);
6566         }
6567     }
6568
6569     return ntStatus;
6570 }
6571
6572 AFSObjectInfoCB *
6573 AFSAllocateObjectInfo( IN AFSObjectInfoCB *ParentObjectInfo,
6574                        IN ULONGLONG HashIndex)
6575 {
6576
6577     NTSTATUS ntStatus = STATUS_SUCCESS;
6578     AFSObjectInfoCB *pObjectInfo = NULL;
6579     LONG lCount;
6580
6581     __Enter
6582     {
6583
6584         pObjectInfo = (AFSObjectInfoCB *)AFSExAllocatePoolWithTag( PagedPool,
6585                                                                    sizeof( AFSObjectInfoCB),
6586                                                                    AFS_OBJECT_INFO_TAG);
6587
6588         if( pObjectInfo == NULL)
6589         {
6590
6591             try_return( pObjectInfo);
6592         }
6593
6594         RtlZeroMemory( pObjectInfo,
6595                        sizeof( AFSObjectInfoCB));
6596
6597         pObjectInfo->NonPagedInfo = (AFSNonPagedObjectInfoCB *)AFSExAllocatePoolWithTag( NonPagedPool,
6598                                                                                          sizeof( AFSNonPagedObjectInfoCB),
6599                                                                                          AFS_NP_OBJECT_INFO_TAG);
6600
6601         if( pObjectInfo->NonPagedInfo == NULL)
6602         {
6603
6604             AFSExFreePoolWithTag( pObjectInfo, AFS_OBJECT_INFO_TAG);
6605
6606             try_return( pObjectInfo = NULL);
6607         }
6608
6609         ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6610
6611         ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
6612
6613         pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock = &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock;
6614
6615         if( ParentObjectInfo != NULL)
6616         {
6617
6618             pObjectInfo->VolumeCB = ParentObjectInfo->VolumeCB;
6619
6620             pObjectInfo->ParentFileId = ParentObjectInfo->FileId;
6621
6622             SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID);
6623
6624             lCount = AFSObjectInfoIncrement( ParentObjectInfo,
6625                                              AFS_OBJECT_REFERENCE_CHILD);
6626
6627             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
6628                           AFS_TRACE_LEVEL_VERBOSE,
6629                           "AFSAllocateObjectInfo Increment count on parent object %p Cnt %d\n",
6630                           ParentObjectInfo,
6631                           lCount));
6632         }
6633
6634         //
6635         // Initialize the access time
6636         //
6637
6638         KeQueryTickCount( &pObjectInfo->LastAccessCount);
6639
6640         if( HashIndex != 0)
6641         {
6642
6643             ASSERT( ParentObjectInfo);
6644
6645             //
6646             // Insert the entry into the object tree and list
6647             //
6648
6649             pObjectInfo->TreeEntry.HashIndex = HashIndex;
6650
6651             if( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead == NULL)
6652             {
6653
6654                 ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead = &pObjectInfo->TreeEntry;
6655             }
6656             else
6657             {
6658
6659                 ntStatus = AFSInsertHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
6660                                                &pObjectInfo->TreeEntry);
6661
6662                 ASSERT( NT_SUCCESS( ntStatus));
6663             }
6664
6665             //
6666             // And the object list in the volume
6667             //
6668
6669             if( ParentObjectInfo->VolumeCB->ObjectInfoListHead == NULL)
6670             {
6671
6672                 ParentObjectInfo->VolumeCB->ObjectInfoListHead = pObjectInfo;
6673             }
6674             else
6675             {
6676
6677                 ParentObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = (void *)pObjectInfo;
6678
6679                 pObjectInfo->ListEntry.bLink = (void *)ParentObjectInfo->VolumeCB->ObjectInfoListTail;
6680             }
6681
6682             ParentObjectInfo->VolumeCB->ObjectInfoListTail = pObjectInfo;
6683
6684             //
6685             // Indicate the object is in the hash tree and linked list in the volume
6686             //
6687
6688             SetFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE | AFS_OBJECT_INSERTED_VOLUME_LIST);
6689         }
6690
6691 try_exit:
6692
6693         NOTHING;
6694     }
6695
6696     return pObjectInfo;
6697 }
6698
6699 LONG
6700 AFSObjectInfoIncrement( IN AFSObjectInfoCB *ObjectInfo,
6701                         IN LONG Reason)
6702 {
6703
6704     LONG lCount;
6705
6706     if ( ObjectInfo->ObjectReferenceCount == 0)
6707     {
6708
6709         AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6710                         TRUE);
6711
6712         lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6713     }
6714     else
6715     {
6716
6717         AFSAcquireShared( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6718                           TRUE);
6719
6720         lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6721
6722         if ( lCount == 1)
6723         {
6724
6725             AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6726
6727             AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6728                             TRUE);
6729         }
6730     }
6731
6732     InterlockedIncrement( &ObjectInfo->ObjectReferences[ Reason]);
6733
6734     AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6735
6736     return lCount;
6737 }
6738
6739 LONG
6740 AFSObjectInfoDecrement( IN AFSObjectInfoCB *ObjectInfo,
6741                         IN LONG Reason)
6742 {
6743
6744     LONG lCount, lCount2;
6745
6746     AFSAcquireShared( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6747                       TRUE);
6748
6749     lCount = InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);
6750
6751     if ( lCount == 0)
6752     {
6753
6754         lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6755
6756         AFSReleaseResource(&ObjectInfo->NonPagedInfo->ObjectInfoLock);
6757
6758         AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6759                         TRUE);
6760
6761         lCount = InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);
6762     }
6763
6764     lCount2 = InterlockedDecrement( &ObjectInfo->ObjectReferences[ Reason]);
6765
6766     ASSERT( lCount2 >= 0);
6767
6768     AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6769
6770     return lCount;
6771 }
6772
6773 AFSObjectInfoCB *
6774 AFSFindObjectInfo( IN AFSVolumeCB *VolumeCB,
6775                    IN AFSFileID   *FileId)
6776 {
6777     DWORD            ntStatus = STATUS_SUCCESS;
6778     ULONGLONG        ullIndex;
6779     AFSObjectInfoCB *pObjectInfo = NULL;
6780
6781     if ( AFSIsEqualFID( &VolumeCB->ObjectInformation.FileId, FileId))
6782     {
6783
6784         pObjectInfo = &VolumeCB->ObjectInformation;
6785     }
6786     else
6787     {
6788
6789         AFSAcquireExcl( VolumeCB->ObjectInfoTree.TreeLock,
6790                         TRUE);
6791
6792         ullIndex = AFSCreateLowIndex( FileId);
6793
6794         ntStatus = AFSLocateHashEntry( VolumeCB->ObjectInfoTree.TreeHead,
6795                                        ullIndex,
6796                                        (AFSBTreeEntry **)&pObjectInfo);
6797
6798         AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
6799     }
6800
6801     if ( NT_SUCCESS( ntStatus)) {
6802
6803         AFSObjectInfoIncrement( pObjectInfo,
6804                                 AFS_OBJECT_REFERENCE_FIND);
6805     }
6806
6807     return pObjectInfo;
6808 }
6809
6810 void
6811 AFSReleaseObjectInfo( IN AFSObjectInfoCB **ppObjectInfo)
6812 {
6813
6814     AFSObjectInfoDecrement( *ppObjectInfo,
6815                             AFS_OBJECT_REFERENCE_FIND);
6816
6817     *ppObjectInfo = NULL;
6818 }
6819
6820 void
6821 AFSDeleteObjectInfo( IN AFSObjectInfoCB **ppObjectInfo)
6822 {
6823
6824     BOOLEAN bAcquiredTreeLock = FALSE;
6825     AFSObjectInfoCB *pObjectInfo = NULL;
6826     BOOLEAN bHeldInService;
6827     AFSObjectInfoCB * pParentObjectInfo = NULL;
6828     AFSFileID FileId;
6829     LONG lCount;
6830
6831     if ( BooleanFlagOn( (*ppObjectInfo)->Flags, AFS_OBJECT_ROOT_VOLUME))
6832     {
6833
6834         //
6835         // AFSDeleteObjectInfo should never be called on the ObjectInformationCB
6836         // embedded in the VolumeCB.
6837         //
6838
6839         ASSERT( TRUE);
6840
6841         return;
6842     }
6843
6844     pObjectInfo = (AFSObjectInfoCB *) InterlockedCompareExchangePointer( (PVOID *)ppObjectInfo,
6845                                                                          NULL,
6846                                                                          (PVOID *)ppObjectInfo);
6847
6848     if ( pObjectInfo == NULL)
6849     {
6850
6851         return;
6852     }
6853
6854     ASSERT( pObjectInfo->ObjectReferenceCount == 0);
6855
6856     bHeldInService = BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_HELD_IN_SERVICE);
6857
6858     if( !ExIsResourceAcquiredExclusiveLite( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock))
6859     {
6860
6861         ASSERT( !ExIsResourceAcquiredLite( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock));
6862
6863         AFSAcquireExcl( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
6864                         TRUE);
6865
6866         bAcquiredTreeLock = TRUE;
6867     }
6868
6869     if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
6870     {
6871
6872         pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
6873                                                &pObjectInfo->ParentFileId);
6874     }
6875
6876     //
6877     // Remove it from the tree and list if it was inserted
6878     //
6879
6880     if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
6881     {
6882
6883         AFSRemoveHashEntry( &pObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
6884                             &pObjectInfo->TreeEntry);
6885     }
6886
6887     if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_VOLUME_LIST))
6888     {
6889
6890         if( pObjectInfo->ListEntry.fLink == NULL)
6891         {
6892
6893             pObjectInfo->VolumeCB->ObjectInfoListTail = (AFSObjectInfoCB *)pObjectInfo->ListEntry.bLink;
6894
6895             if( pObjectInfo->VolumeCB->ObjectInfoListTail != NULL)
6896             {
6897
6898                 pObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = NULL;
6899             }
6900         }
6901         else
6902         {
6903
6904             ((AFSObjectInfoCB *)(pObjectInfo->ListEntry.fLink))->ListEntry.bLink = pObjectInfo->ListEntry.bLink;
6905         }
6906
6907         if( pObjectInfo->ListEntry.bLink == NULL)
6908         {
6909
6910             pObjectInfo->VolumeCB->ObjectInfoListHead = (AFSObjectInfoCB *)pObjectInfo->ListEntry.fLink;
6911
6912             if( pObjectInfo->VolumeCB->ObjectInfoListHead != NULL)
6913             {
6914
6915                 pObjectInfo->VolumeCB->ObjectInfoListHead->ListEntry.bLink = NULL;
6916             }
6917         }
6918         else
6919         {
6920
6921             ((AFSObjectInfoCB *)(pObjectInfo->ListEntry.bLink))->ListEntry.fLink = pObjectInfo->ListEntry.fLink;
6922         }
6923     }
6924
6925     if( pParentObjectInfo != NULL)
6926     {
6927
6928         ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID);
6929
6930         lCount = AFSObjectInfoDecrement( pParentObjectInfo,
6931                                          AFS_OBJECT_REFERENCE_CHILD);
6932
6933         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
6934                       AFS_TRACE_LEVEL_VERBOSE,
6935                       "AFSDeleteObjectInfo Decrement count on parent object %p Cnt %d\n",
6936                       pParentObjectInfo,
6937                       lCount));
6938
6939         AFSReleaseObjectInfo( &pParentObjectInfo);
6940     }
6941
6942     if( bAcquiredTreeLock)
6943     {
6944
6945         AFSReleaseResource( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
6946     }
6947
6948     if( bHeldInService)
6949     {
6950
6951         FileId = pObjectInfo->FileId;
6952     }
6953
6954     ExDeleteResourceLite( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
6955
6956     ExDeleteResourceLite( &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6957
6958     AFSExFreePoolWithTag( pObjectInfo->NonPagedInfo, AFS_NP_OBJECT_INFO_TAG);
6959
6960     AFSExFreePoolWithTag( pObjectInfo, AFS_OBJECT_INFO_TAG);
6961
6962     //
6963     // Release the fid in the service
6964     //
6965
6966     if( bHeldInService)
6967     {
6968
6969         AFSReleaseFid( &FileId);
6970     }
6971
6972     return;
6973 }
6974
6975 NTSTATUS
6976 AFSEvaluateRootEntry( IN AFSDirectoryCB *DirectoryCB,
6977                       OUT AFSDirectoryCB **TargetDirEntry)
6978 {
6979
6980     NTSTATUS ntStatus = STATUS_SUCCESS;
6981     AFSDirEnumEntry *pDirEntry = NULL;
6982     UNICODE_STRING uniFullPathName = {0};
6983     AFSNameArrayHdr    *pNameArray = NULL;
6984     AFSVolumeCB *pVolumeCB = NULL;
6985     LONG VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
6986     AFSVolumeCB *pNewVolumeCB = NULL;
6987     LONG NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
6988     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
6989     AFSDirectoryCB *pNewParentDirEntry = NULL;
6990     WCHAR *pwchBuffer = NULL;
6991     UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
6992     ULONG ulNameDifference = 0;
6993     GUID    stAuthGroup;
6994     LONG lCount;
6995
6996     __Enter
6997     {
6998
6999         ntStatus = AFSRetrieveValidAuthGroup( NULL,
7000                                               DirectoryCB->ObjectInformation,
7001                                               FALSE,
7002                                               &stAuthGroup);
7003
7004         if( !NT_SUCCESS( ntStatus))
7005         {
7006             try_return( ntStatus);
7007         }
7008
7009         //
7010         // Retrieve a target name for the entry
7011         //
7012
7013         AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
7014                           TRUE);
7015
7016         if( DirectoryCB->NameInformation.TargetName.Length == 0)
7017         {
7018
7019             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
7020
7021             ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
7022                                               &stAuthGroup,
7023                                               FALSE,
7024                                               &pDirEntry);
7025
7026             if( !NT_SUCCESS( ntStatus) ||
7027                 pDirEntry->TargetNameLength == 0)
7028             {
7029
7030                 if( pDirEntry != NULL)
7031                 {
7032
7033                     ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
7034                 }
7035
7036                 try_return( ntStatus);
7037             }
7038
7039             AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
7040                             TRUE);
7041
7042             if( DirectoryCB->NameInformation.TargetName.Length == 0)
7043             {
7044
7045                 //
7046                 // Update the target name
7047                 //
7048
7049                 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
7050                                                 &DirectoryCB->Flags,
7051                                                 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
7052                                                 (USHORT)pDirEntry->TargetNameLength);
7053
7054                 if( !NT_SUCCESS( ntStatus))
7055                 {
7056
7057                     AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
7058
7059                     try_return( ntStatus);
7060                 }
7061             }
7062
7063             AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
7064         }
7065
7066         //
7067         // Need to pass the full path in for parsing.
7068         //
7069
7070         uniFullPathName.Length = 0;
7071         uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
7072
7073         uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
7074                                                                     uniFullPathName.MaximumLength,
7075                                                                     AFS_NAME_BUFFER_EIGHT_TAG);
7076
7077         if( uniFullPathName.Buffer == NULL)
7078         {
7079
7080             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
7081
7082             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7083         }
7084
7085         pwchBuffer = uniFullPathName.Buffer;
7086
7087         RtlZeroMemory( uniFullPathName.Buffer,
7088                        uniFullPathName.MaximumLength);
7089
7090         RtlCopyMemory( uniFullPathName.Buffer,
7091                        DirectoryCB->NameInformation.TargetName.Buffer,
7092                        DirectoryCB->NameInformation.TargetName.Length);
7093
7094         uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
7095
7096         //
7097         // This name should begin with the \afs server so parse it off and chech it
7098         //
7099
7100         FsRtlDissectName( uniFullPathName,
7101                           &uniComponentName,
7102                           &uniRemainingPath);
7103
7104         if( RtlCompareUnicodeString( &uniComponentName,
7105                                      &AFSServerName,
7106                                      TRUE) != 0)
7107         {
7108
7109             //
7110             // Try evaluating the full path
7111             //
7112
7113             uniFullPathName.Buffer = pwchBuffer;
7114
7115             uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
7116
7117             uniFullPathName.MaximumLength = uniFullPathName.Length;
7118         }
7119         else
7120         {
7121
7122             uniFullPathName = uniRemainingPath;
7123         }
7124
7125         uniParsedName = uniFullPathName;
7126
7127         ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
7128
7129         AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
7130
7131         //
7132         // Our name array
7133         //
7134
7135         pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
7136                                        0);
7137
7138         if( pNameArray == NULL)
7139         {
7140
7141             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7142         }
7143
7144         pVolumeCB = AFSGlobalRoot;
7145
7146         pParentDirEntry = AFSGlobalRoot->DirectoryCB;
7147
7148         VolumeReferenceReason = AFS_VOLUME_REFERENCE_EVAL_ROOT;
7149
7150         lCount = AFSVolumeIncrement( pVolumeCB,
7151                                      VolumeReferenceReason);
7152
7153         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7154                       AFS_TRACE_LEVEL_VERBOSE,
7155                       "AFSEvaluateRootEntry Increment count on volume %p Reason %u Cnt %d\n",
7156                       pVolumeCB,
7157                       VolumeReferenceReason,
7158                       lCount));
7159
7160         lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
7161
7162         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
7163                       AFS_TRACE_LEVEL_VERBOSE,
7164                       "AFSEvaluateRootEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
7165                       &pParentDirEntry->NameInformation.FileName,
7166                       pParentDirEntry,
7167                       NULL,
7168                       lCount));
7169
7170         ntStatus = AFSLocateNameEntry( NULL,
7171                                        NULL,
7172                                        &uniFullPathName,
7173                                        &uniParsedName,
7174                                        pNameArray,
7175                                        0,
7176                                        pVolumeCB,
7177                                        pParentDirEntry,
7178                                        &pNewVolumeCB,
7179                                        &VolumeReferenceReason,
7180                                        &pNewParentDirEntry,
7181                                        &pDirectoryEntry,
7182                                        NULL);
7183
7184         if ( pNewVolumeCB != NULL)
7185         {
7186             //
7187             // AFSLocateNameEntry returns pNewVolumeCB with a reference held
7188             // even if pVolumeCB == pNewVolumeCB.  It is always safe to release
7189             // the reference on pVolumeCB that was held prior to the call.
7190             // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
7191             // will be released second.
7192             //
7193
7194             lCount = AFSVolumeDecrement( pVolumeCB,
7195                                          VolumeReferenceReason);
7196
7197             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7198                           AFS_TRACE_LEVEL_VERBOSE,
7199                           "AFSEvaluateRootEntry Decrement count on volume %p Reason %u Cnt %d\n",
7200                           pVolumeCB,
7201                           VolumeReferenceReason,
7202                           lCount));
7203
7204             pVolumeCB = pNewVolumeCB;
7205
7206             pNewVolumeCB = NULL;
7207
7208             VolumeReferenceReason = NewVolumeReferenceReason;
7209
7210             NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
7211         }
7212
7213         //
7214         // AFSLocateNameEntry does not alter the reference count of
7215         // pParentDirectoryCB and it returns pNewParentDirectoryCB with
7216         // a reference held.
7217         //
7218
7219         lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
7220
7221         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
7222                       AFS_TRACE_LEVEL_VERBOSE,
7223                       "AFSEvaluateRootEntry DecrementX count on %wZ DE %p Cnt %d\n",
7224                       &pParentDirEntry->NameInformation.FileName,
7225                       pParentDirEntry,
7226                       lCount));
7227
7228         pParentDirEntry = pNewParentDirEntry;
7229
7230         pNewParentDirEntry = NULL;
7231
7232         if( !NT_SUCCESS( ntStatus) ||
7233             ntStatus == STATUS_REPARSE)
7234         {
7235
7236             pVolumeCB = NULL;
7237
7238             try_return( ntStatus);
7239         }
7240
7241         //
7242         // Pass back the target dir entry for this request
7243         // The caller must release the DirOpenReferenceCount
7244         //
7245
7246         *TargetDirEntry = pDirectoryEntry;
7247
7248         pDirectoryEntry = NULL;
7249
7250 try_exit:
7251
7252         if( pDirectoryEntry != NULL)
7253         {
7254
7255             lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
7256
7257             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
7258                           AFS_TRACE_LEVEL_VERBOSE,
7259                           "AFSEvaluateRootEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
7260                           &pDirectoryEntry->NameInformation.FileName,
7261                           pDirectoryEntry,
7262                           NULL,
7263                           lCount));
7264
7265             ASSERT( lCount >= 0);
7266         }
7267
7268         if ( pParentDirEntry != NULL)
7269         {
7270
7271             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
7272
7273             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
7274                           AFS_TRACE_LEVEL_VERBOSE,
7275                           "AFSEvaluateRootEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
7276                           &pParentDirEntry->NameInformation.FileName,
7277                           pParentDirEntry,
7278                           NULL,
7279                           lCount));
7280
7281             ASSERT( lCount >= 0);
7282         }
7283
7284         if( pDirEntry != NULL)
7285         {
7286
7287             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
7288         }
7289
7290         if( pVolumeCB != NULL)
7291         {
7292
7293             lCount = AFSVolumeDecrement( pVolumeCB,
7294                                          VolumeReferenceReason);
7295
7296             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7297                           AFS_TRACE_LEVEL_VERBOSE,
7298                           "AFSEvaluateRootEntry Decrement2 count on volume %p Reason %u Cnt %d\n",
7299                           pVolumeCB,
7300                           VolumeReferenceReason,
7301                           lCount));
7302         }
7303
7304         if( pNameArray != NULL)
7305         {
7306
7307             AFSFreeNameArray( pNameArray);
7308         }
7309
7310         if( pwchBuffer != NULL)
7311         {
7312
7313             //
7314             // Always free the buffer that we allocated as AFSLocateNameEntry
7315             // will not free it.  If uniFullPathName.Buffer was allocated by
7316             // AFSLocateNameEntry, then we must free that as well.
7317             // Check that the uniFullPathName.Buffer in the string is not the same
7318             // offset by the length of the server name
7319             //
7320
7321             if( uniFullPathName.Length > 0 &&
7322                 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
7323             {
7324
7325                 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
7326             }
7327
7328             AFSExFreePoolWithTag( pwchBuffer, 0);
7329         }
7330     }
7331
7332     return ntStatus;
7333 }
7334
7335 NTSTATUS
7336 AFSCleanupFcb( IN AFSFcb *Fcb,
7337                IN BOOLEAN ForceFlush)
7338 {
7339
7340     NTSTATUS ntStatus = STATUS_SUCCESS;
7341     AFSDeviceExt *pRDRDeviceExt = NULL, *pControlDeviceExt = NULL;
7342     LARGE_INTEGER liTime;
7343     IO_STATUS_BLOCK stIoStatus;
7344
7345     __Enter
7346     {
7347
7348         pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
7349
7350         pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
7351
7352         if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
7353         {
7354
7355             if( !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) &&
7356                 !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
7357             {
7358
7359                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
7360                               AFS_TRACE_LEVEL_VERBOSE,
7361                               "AFSCleanupEntry Acquiring Fcb lock %p SHARED %08lX\n",
7362                               &Fcb->NPFcb->Resource,
7363                               PsGetCurrentThread()));
7364
7365                 AFSAcquireShared( &Fcb->NPFcb->Resource,
7366                                   TRUE);
7367
7368                 if( Fcb->OpenReferenceCount > 0)
7369                 {
7370
7371                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
7372                                   AFS_TRACE_LEVEL_VERBOSE,
7373                                   "AFSCleanupEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
7374                                   &Fcb->NPFcb->SectionObjectResource,
7375                                   PsGetCurrentThread()));
7376
7377                     AFSAcquireExcl( &Fcb->NPFcb->SectionObjectResource,
7378                                     TRUE);
7379
7380                     __try
7381                     {
7382
7383                         CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
7384                                       NULL,
7385                                       0,
7386                                       &stIoStatus);
7387
7388                         if( !NT_SUCCESS( stIoStatus.Status))
7389                         {
7390
7391                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
7392                                           AFS_TRACE_LEVEL_ERROR,
7393                                           "AFSCleanupFcb CcFlushCache [1] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
7394                                           Fcb->ObjectInformation->FileId.Cell,
7395                                           Fcb->ObjectInformation->FileId.Volume,
7396                                           Fcb->ObjectInformation->FileId.Vnode,
7397                                           Fcb->ObjectInformation->FileId.Unique,
7398                                           stIoStatus.Status,
7399                                           stIoStatus.Information));
7400
7401                             ntStatus = stIoStatus.Status;
7402                         }
7403
7404                         if (  Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
7405                         {
7406
7407                             if ( !CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
7408                                                        NULL,
7409                                                        0,
7410                                                        FALSE))
7411                             {
7412
7413                                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
7414                                               AFS_TRACE_LEVEL_WARNING,
7415                                               "AFSCleanupFcb CcPurgeCacheSection [1] failure FID %08lX-%08lX-%08lX-%08lX\n",
7416                                               Fcb->ObjectInformation->FileId.Cell,
7417                                               Fcb->ObjectInformation->FileId.Volume,
7418                                               Fcb->ObjectInformation->FileId.Vnode,
7419                                               Fcb->ObjectInformation->FileId.Unique));
7420
7421                                 SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
7422                             }
7423                         }
7424                     }
7425                     __except( EXCEPTION_EXECUTE_HANDLER)
7426                     {
7427
7428                         ntStatus = GetExceptionCode();
7429
7430                         AFSDbgTrace(( 0,
7431                                       0,
7432                                       "EXCEPTION - AFSCleanupFcb Cc [1] FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
7433                                       Fcb->ObjectInformation->FileId.Cell,
7434                                       Fcb->ObjectInformation->FileId.Volume,
7435                                       Fcb->ObjectInformation->FileId.Vnode,
7436                                       Fcb->ObjectInformation->FileId.Unique,
7437                                       ntStatus));
7438
7439                         SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
7440                     }
7441
7442                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
7443                                   AFS_TRACE_LEVEL_VERBOSE,
7444                                   "AFSCleanupFcb Releasing Fcb SectionObject lock %p EXCL %08lX\n",
7445                                   &Fcb->NPFcb->SectionObjectResource,
7446                                   PsGetCurrentThread()));
7447
7448                     AFSReleaseResource( &Fcb->NPFcb->SectionObjectResource);
7449                 }
7450
7451                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
7452                               AFS_TRACE_LEVEL_VERBOSE,
7453                               "AFSCleanupEntry Releasing Fcb lock %p SHARED %08lX\n",
7454                               &Fcb->NPFcb->Resource,
7455                               PsGetCurrentThread()));
7456
7457                 AFSReleaseResource( &Fcb->NPFcb->Resource);
7458
7459                 //
7460                 // Wait for any currently running flush or release requests to complete
7461                 //
7462
7463                 AFSWaitOnQueuedFlushes( Fcb);
7464
7465                 //
7466                 // Now perform another flush on the file
7467                 //
7468
7469                 if( !NT_SUCCESS( AFSFlushExtents( Fcb,
7470                                                   NULL)))
7471                 {
7472
7473                     AFSReleaseExtentsWithFlush( Fcb,
7474                                                 NULL,
7475                                                 TRUE);
7476                 }
7477             }
7478
7479             if( Fcb->OpenReferenceCount == 0 ||
7480                 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
7481                 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
7482             {
7483
7484                 AFSTearDownFcbExtents( Fcb,
7485                                        NULL);
7486             }
7487
7488             try_return( ntStatus);
7489         }
7490
7491         KeQueryTickCount( &liTime);
7492
7493         //
7494         // First up are there dirty extents in the cache to flush?
7495         //
7496
7497         if( BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
7498             BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
7499         {
7500
7501             //
7502             // The file has been marked as invalid.  Dump it
7503             //
7504
7505             AFSTearDownFcbExtents( Fcb,
7506                                    NULL);
7507         }
7508         else if( ForceFlush ||
7509             ( ( Fcb->Specific.File.ExtentsDirtyCount ||
7510                 Fcb->Specific.File.ExtentCount) &&
7511               (liTime.QuadPart - Fcb->Specific.File.LastServerFlush.QuadPart)
7512                                                     >= pControlDeviceExt->Specific.Control.FcbFlushTimeCount.QuadPart))
7513         {
7514             if( !NT_SUCCESS( AFSFlushExtents( Fcb,
7515                                               NULL)) &&
7516                 Fcb->OpenReferenceCount == 0)
7517             {
7518
7519                 AFSReleaseExtentsWithFlush( Fcb,
7520                                             NULL,
7521                                             TRUE);
7522             }
7523         }
7524
7525         //
7526         // If there are extents and they haven't been used recently *and*
7527         // are not being used
7528         //
7529
7530         if( ( ForceFlush ||
7531               ( 0 != Fcb->Specific.File.ExtentCount &&
7532                 0 != Fcb->Specific.File.LastExtentAccess.QuadPart &&
7533                 (liTime.QuadPart - Fcb->Specific.File.LastExtentAccess.QuadPart) >=
7534                                         (AFS_SERVER_PURGE_SLEEP * pControlDeviceExt->Specific.Control.FcbPurgeTimeCount.QuadPart))))
7535         {
7536
7537             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
7538                           AFS_TRACE_LEVEL_VERBOSE,
7539                           "AFSCleanupFcb Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
7540                           &Fcb->NPFcb->SectionObjectResource,
7541                           PsGetCurrentThread()));
7542
7543             if ( AFSAcquireExcl( &Fcb->NPFcb->SectionObjectResource, ForceFlush))
7544             {
7545
7546                 __try
7547                 {
7548
7549                     CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
7550                                   NULL,
7551                                   0,
7552                                   &stIoStatus);
7553
7554                     if( !NT_SUCCESS( stIoStatus.Status))
7555                     {
7556
7557                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
7558                                       AFS_TRACE_LEVEL_ERROR,
7559                                       "AFSCleanupFcb CcFlushCache [2] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
7560                                       Fcb->ObjectInformation->FileId.Cell,
7561                                       Fcb->ObjectInformation->FileId.Volume,
7562                                       Fcb->ObjectInformation->FileId.Vnode,
7563                                       Fcb->ObjectInformation->FileId.Unique,
7564                                       stIoStatus.Status,
7565                                       stIoStatus.Information));
7566
7567                         ntStatus = stIoStatus.Status;
7568                     }
7569
7570                     if( ForceFlush &&
7571                         Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
7572                     {
7573
7574                         if ( !CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
7575                                                    NULL,
7576                                                    0,
7577                                                    FALSE))
7578                         {
7579
7580                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
7581                                           AFS_TRACE_LEVEL_WARNING,
7582                                           "AFSCleanupFcb CcPurgeCacheSection [2] failure FID %08lX-%08lX-%08lX-%08lX\n",
7583                                           Fcb->ObjectInformation->FileId.Cell,
7584                                           Fcb->ObjectInformation->FileId.Volume,
7585                                           Fcb->ObjectInformation->FileId.Vnode,
7586                                           Fcb->ObjectInformation->FileId.Unique));
7587
7588                             SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
7589                         }
7590                     }
7591                 }
7592                 __except( EXCEPTION_EXECUTE_HANDLER)
7593                 {
7594
7595                     ntStatus = GetExceptionCode();
7596
7597                     AFSDbgTrace(( 0,
7598                                   0,
7599                                   "EXCEPTION - AFSCleanupFcb Cc [2] FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
7600                                   Fcb->ObjectInformation->FileId.Cell,
7601                                   Fcb->ObjectInformation->FileId.Volume,
7602                                   Fcb->ObjectInformation->FileId.Vnode,
7603                                   Fcb->ObjectInformation->FileId.Unique,
7604                                   ntStatus));
7605                 }
7606
7607                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
7608                               AFS_TRACE_LEVEL_VERBOSE,
7609                               "AFSCleanupFcb Releasing Fcb SectionObject lock %p EXCL %08lX\n",
7610                               &Fcb->NPFcb->SectionObjectResource,
7611                               PsGetCurrentThread()));
7612
7613                 AFSReleaseResource( &Fcb->NPFcb->SectionObjectResource);
7614
7615                 if( Fcb->OpenReferenceCount <= 0)
7616                 {
7617
7618                     //
7619                     // Tear em down we'll not be needing them again
7620                     //
7621
7622                     AFSTearDownFcbExtents( Fcb,
7623                                            NULL);
7624                 }
7625             }
7626             else
7627             {
7628
7629                 ntStatus = STATUS_RETRY;
7630             }
7631         }
7632
7633 try_exit:
7634
7635         NOTHING;
7636     }
7637
7638     return ntStatus;
7639 }
7640
7641 NTSTATUS
7642 AFSUpdateDirEntryName( IN AFSDirectoryCB *DirectoryCB,
7643                        IN UNICODE_STRING *NewFileName)
7644 {
7645
7646     NTSTATUS ntStatus = STATUS_SUCCESS;
7647     WCHAR *pTmpBuffer = NULL;
7648
7649     __Enter
7650     {
7651
7652         if( NewFileName->Length > DirectoryCB->NameInformation.FileName.Length)
7653         {
7654
7655             if( BooleanFlagOn( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
7656             {
7657
7658                 AFSExFreePoolWithTag( DirectoryCB->NameInformation.FileName.Buffer, 0);
7659
7660                 ClearFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
7661
7662                 DirectoryCB->NameInformation.FileName.Buffer = NULL;
7663             }
7664
7665             //
7666             // OK, we need to allocate a new name buffer
7667             //
7668
7669             pTmpBuffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
7670                                                             NewFileName->Length,
7671                                                             AFS_NAME_BUFFER_NINE_TAG);
7672
7673             if( pTmpBuffer == NULL)
7674             {
7675
7676                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7677             }
7678
7679             DirectoryCB->NameInformation.FileName.Buffer = pTmpBuffer;
7680
7681             DirectoryCB->NameInformation.FileName.MaximumLength = NewFileName->Length;
7682
7683             SetFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
7684         }
7685
7686         DirectoryCB->NameInformation.FileName.Length = NewFileName->Length;
7687
7688         RtlCopyMemory( DirectoryCB->NameInformation.FileName.Buffer,
7689                        NewFileName->Buffer,
7690                        NewFileName->Length);
7691
7692 try_exit:
7693
7694         NOTHING;
7695     }
7696
7697     return ntStatus;
7698 }
7699
7700 NTSTATUS
7701 AFSReadCacheFile( IN void *ReadBuffer,
7702                   IN LARGE_INTEGER *ReadOffset,
7703                   IN ULONG RequestedDataLength,
7704                   IN OUT PULONG BytesRead)
7705 {
7706
7707     NTSTATUS            ntStatus = STATUS_SUCCESS;
7708     PIRP                pIrp = NULL;
7709     KEVENT              kEvent;
7710     PIO_STACK_LOCATION  pIoStackLocation = NULL;
7711     DEVICE_OBJECT      *pTargetDeviceObject = NULL;
7712     FILE_OBJECT        *pCacheFileObject = NULL;
7713
7714     __Enter
7715     {
7716
7717         pCacheFileObject = AFSReferenceCacheFileObject();
7718
7719         if( pCacheFileObject == NULL)
7720         {
7721             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
7722         }
7723
7724         pTargetDeviceObject = IoGetRelatedDeviceObject( pCacheFileObject);
7725
7726         //
7727         // Initialize the event
7728         //
7729
7730         KeInitializeEvent( &kEvent,
7731                            SynchronizationEvent,
7732                            FALSE);
7733
7734         //
7735         // Allocate an irp for this request.  This could also come from a
7736         // private pool, for instance.
7737         //
7738
7739         pIrp = IoAllocateIrp( pTargetDeviceObject->StackSize,
7740                               FALSE);
7741
7742         if( pIrp == NULL)
7743         {
7744
7745             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7746         }
7747
7748         //
7749         // Build the IRP's main body
7750         //
7751
7752         pIrp->UserBuffer = ReadBuffer;
7753
7754         pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
7755         pIrp->RequestorMode = KernelMode;
7756         pIrp->Flags |= IRP_READ_OPERATION;
7757
7758         //
7759         // Set up the I/O stack location.
7760         //
7761
7762         pIoStackLocation = IoGetNextIrpStackLocation( pIrp);
7763         pIoStackLocation->MajorFunction = IRP_MJ_READ;
7764         pIoStackLocation->DeviceObject = pTargetDeviceObject;
7765         pIoStackLocation->FileObject = pCacheFileObject;
7766         pIoStackLocation->Parameters.Read.Length = RequestedDataLength;
7767
7768         pIoStackLocation->Parameters.Read.ByteOffset.QuadPart = ReadOffset->QuadPart;
7769
7770         //
7771         // Set the completion routine.
7772         //
7773
7774         IoSetCompletionRoutine( pIrp,
7775                                 AFSIrpComplete,
7776                                 &kEvent,
7777                                 TRUE,
7778                                 TRUE,
7779                                 TRUE);
7780
7781         //
7782         // Send it to the FSD
7783         //
7784
7785         ntStatus = IoCallDriver( pTargetDeviceObject,
7786                                  pIrp);
7787
7788         if( NT_SUCCESS( ntStatus))
7789         {
7790
7791             //
7792             // Wait for the I/O
7793             //
7794
7795             ntStatus = KeWaitForSingleObject( &kEvent,
7796                                               Executive,
7797                                               KernelMode,
7798                                               FALSE,
7799                                               0);
7800
7801             if( NT_SUCCESS( ntStatus))
7802             {
7803
7804                 ntStatus = pIrp->IoStatus.Status;
7805
7806                 *BytesRead = (ULONG)pIrp->IoStatus.Information;
7807             }
7808         }
7809
7810 try_exit:
7811
7812         if( pCacheFileObject != NULL)
7813         {
7814             AFSReleaseCacheFileObject( pCacheFileObject);
7815         }
7816
7817         if( pIrp != NULL)
7818         {
7819
7820             if( pIrp->MdlAddress != NULL)
7821             {
7822
7823                 if( FlagOn( pIrp->MdlAddress->MdlFlags, MDL_PAGES_LOCKED))
7824                 {
7825
7826                     MmUnlockPages( pIrp->MdlAddress);
7827                 }
7828
7829                 IoFreeMdl( pIrp->MdlAddress);
7830             }
7831
7832             pIrp->MdlAddress = NULL;
7833
7834             //
7835             // Free the Irp
7836             //
7837
7838             IoFreeIrp( pIrp);
7839         }
7840     }
7841
7842     return ntStatus;
7843 }
7844
7845 NTSTATUS
7846 AFSIrpComplete( IN PDEVICE_OBJECT DeviceObject,
7847                 IN PIRP           Irp,
7848                 IN PVOID          Context)
7849 {
7850
7851     UNREFERENCED_PARAMETER(Irp);
7852     UNREFERENCED_PARAMETER(DeviceObject);
7853     KEVENT *pEvent = (KEVENT *)Context;
7854
7855     KeSetEvent( pEvent,
7856                 0,
7857                 FALSE);
7858
7859     return STATUS_MORE_PROCESSING_REQUIRED;
7860 }
7861
7862 BOOLEAN
7863 AFSIsDirectoryEmptyForDelete( IN AFSFcb *Fcb)
7864 {
7865
7866     BOOLEAN bIsEmpty = FALSE;
7867     AFSDirectoryCB *pDirEntry = NULL;
7868
7869     __Enter
7870     {
7871
7872         AFSAcquireShared( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
7873                           TRUE);
7874
7875         bIsEmpty = TRUE;
7876
7877         if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
7878         {
7879
7880             pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
7881
7882             while( pDirEntry != NULL)
7883             {
7884
7885                 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
7886                     !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
7887                 {
7888
7889                     bIsEmpty = FALSE;
7890
7891                     break;
7892                 }
7893
7894                 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
7895             }
7896
7897         }
7898
7899         AFSReleaseResource( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
7900     }
7901
7902     return bIsEmpty;
7903 }
7904
7905 void
7906 AFSRemoveNameEntry( IN AFSObjectInfoCB *ParentObjectInfo,
7907                     IN AFSDirectoryCB *DirEntry)
7908 {
7909
7910     NTSTATUS ntStatus = STATUS_SUCCESS;
7911
7912     __Enter
7913     {
7914
7915         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7916         {
7917
7918             AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7919                           AFS_TRACE_LEVEL_VERBOSE,
7920                           "AFSRemoveNameEntry DE %p for %wZ has NOT_IN flag set\n",
7921                           DirEntry,
7922                           &DirEntry->NameInformation.FileName));
7923
7924             try_return( ntStatus);
7925         }
7926
7927         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
7928
7929         //
7930         // Remove the entry from the parent tree
7931         //
7932
7933         AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7934                       AFS_TRACE_LEVEL_VERBOSE,
7935                       "AFSRemoveNameEntry DE %p for %wZ removing from case sensitive tree\n",
7936                       DirEntry,
7937                       &DirEntry->NameInformation.FileName));
7938
7939         AFSRemoveCaseSensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7940                                         DirEntry);
7941
7942         AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7943                       AFS_TRACE_LEVEL_VERBOSE,
7944                       "AFSRemoveNameEntry DE %p for %wZ removing from case insensitive tree\n",
7945                       DirEntry,
7946                       &DirEntry->NameInformation.FileName));
7947
7948         AFSRemoveCaseInsensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
7949                                           DirEntry);
7950
7951         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
7952         {
7953
7954             //
7955             // From the short name tree
7956             //
7957
7958             AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7959                           AFS_TRACE_LEVEL_VERBOSE,
7960                           "AFSRemoveNameEntry DE %p for %wZ removing from shortname tree\n",
7961                           DirEntry,
7962                           &DirEntry->NameInformation.FileName));
7963
7964             AFSRemoveShortNameDirEntry( &ParentObjectInfo->Specific.Directory.ShortNameTree,
7965                                         DirEntry);
7966
7967             ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
7968         }
7969
7970         AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7971                       AFS_TRACE_LEVEL_VERBOSE,
7972                       "AFSRemoveNameEntry DE %p for %wZ setting NOT_IN flag\n",
7973                       DirEntry,
7974                       &DirEntry->NameInformation.FileName));
7975
7976         SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
7977
7978         ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
7979
7980 try_exit:
7981
7982         NOTHING;
7983     }
7984
7985     return;
7986 }
7987
7988 LARGE_INTEGER
7989 AFSGetAuthenticationId()
7990 {
7991
7992     LARGE_INTEGER liAuthId = {0,0};
7993     NTSTATUS ntStatus = STATUS_SUCCESS;
7994     PACCESS_TOKEN hToken = NULL;
7995     PTOKEN_STATISTICS pTokenInfo = NULL;
7996     BOOLEAN bCopyOnOpen = FALSE;
7997     BOOLEAN bEffectiveOnly = FALSE;
7998     BOOLEAN bPrimaryToken = FALSE;
7999     SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
8000
8001     __Enter
8002     {
8003
8004         hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
8005                                                 &bCopyOnOpen,
8006                                                 &bEffectiveOnly,
8007                                                 &stImpersonationLevel);
8008
8009         if( hToken == NULL)
8010         {
8011
8012             hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
8013
8014             if( hToken == NULL)
8015             {
8016
8017                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
8018                               AFS_TRACE_LEVEL_ERROR,
8019                               "AFSGetAuthenticationId Failed to retrieve impersonation or primary token\n"));
8020
8021                 try_return( ntStatus);
8022             }
8023
8024             bPrimaryToken = TRUE;
8025         }
8026
8027         ntStatus = SeQueryInformationToken( hToken,
8028                                             TokenStatistics,
8029                                             (PVOID *)&pTokenInfo);
8030
8031         if( !NT_SUCCESS( ntStatus))
8032         {
8033
8034             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
8035                           AFS_TRACE_LEVEL_ERROR,
8036                           "AFSGetAuthenticationId Failed to retrieve information Status %08lX\n",
8037                           ntStatus));
8038
8039             try_return( ntStatus);
8040         }
8041
8042         liAuthId.HighPart = pTokenInfo->AuthenticationId.HighPart;
8043         liAuthId.LowPart = pTokenInfo->AuthenticationId.LowPart;
8044
8045         AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
8046                       AFS_TRACE_LEVEL_VERBOSE,
8047                       "AFSGetAuthenticationId Successfully retrieved authentication ID %I64X\n",
8048                       liAuthId.QuadPart));
8049
8050 try_exit:
8051
8052         if( hToken != NULL)
8053         {
8054
8055             if( !bPrimaryToken)
8056             {
8057
8058                 PsDereferenceImpersonationToken( hToken);
8059             }
8060             else
8061             {
8062
8063                 PsDereferencePrimaryToken( hToken);
8064             }
8065         }
8066
8067         if( pTokenInfo != NULL)
8068         {
8069
8070             ExFreePool( pTokenInfo);    // Allocated by SeQueryInformationToken
8071         }
8072     }
8073
8074     return liAuthId;
8075 }
8076
8077 void
8078 AFSUnwindFileInfo( IN AFSFcb *Fcb,
8079                    IN AFSCcb *Ccb)
8080 {
8081
8082     UNREFERENCED_PARAMETER(Fcb);
8083     if( Ccb->FileUnwindInfo.FileAttributes != (ULONG)-1)
8084     {
8085         Ccb->DirectoryCB->ObjectInformation->FileAttributes = Ccb->FileUnwindInfo.FileAttributes;
8086     }
8087
8088     if( Ccb->FileUnwindInfo.CreationTime.QuadPart != (ULONGLONG)-1)
8089     {
8090         Ccb->DirectoryCB->ObjectInformation->CreationTime.QuadPart = Ccb->FileUnwindInfo.CreationTime.QuadPart;
8091     }
8092
8093     if( Ccb->FileUnwindInfo.LastAccessTime.QuadPart != (ULONGLONG)-1)
8094     {
8095         Ccb->DirectoryCB->ObjectInformation->LastAccessTime.QuadPart = Ccb->FileUnwindInfo.LastAccessTime.QuadPart;
8096     }
8097
8098     if( Ccb->FileUnwindInfo.LastWriteTime.QuadPart != (ULONGLONG)-1)
8099     {
8100         Ccb->DirectoryCB->ObjectInformation->LastWriteTime.QuadPart = Ccb->FileUnwindInfo.LastWriteTime.QuadPart;
8101     }
8102
8103     if( Ccb->FileUnwindInfo.ChangeTime.QuadPart != (ULONGLONG)-1)
8104     {
8105         Ccb->DirectoryCB->ObjectInformation->ChangeTime.QuadPart = Ccb->FileUnwindInfo.ChangeTime.QuadPart;
8106     }
8107
8108     return;
8109 }
8110
8111 BOOLEAN
8112 AFSValidateDirList( IN AFSObjectInfoCB *ObjectInfo)
8113 {
8114
8115     BOOLEAN bIsValid = TRUE;
8116     ULONG ulCount = 0;
8117     AFSDirectoryCB *pCurrentDirEntry = NULL, *pDirEntry = NULL;
8118
8119     pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
8120
8121     while( pCurrentDirEntry != NULL)
8122     {
8123
8124         if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
8125         {
8126             ulCount++;
8127
8128             if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
8129             {
8130
8131                 pDirEntry = NULL;
8132
8133                 AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
8134                                                 (ULONG)pCurrentDirEntry->CaseSensitiveTreeEntry.HashIndex,
8135                                                 &pDirEntry);
8136
8137                 if( pDirEntry == NULL)
8138                 {
8139                     DbgBreakPoint();
8140                 }
8141             }
8142         }
8143
8144         pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
8145     }
8146
8147     if( ulCount != (ULONG) ObjectInfo->Specific.Directory.DirectoryNodeCount)
8148     {
8149
8150         AFSPrint("AFSValidateDirList Count off Calc: %d Stored: %d\n",
8151                   ulCount,
8152                   ObjectInfo->Specific.Directory.DirectoryNodeCount);
8153
8154         ObjectInfo->Specific.Directory.DirectoryNodeCount = ulCount;
8155
8156         bIsValid = FALSE;
8157     }
8158
8159     return bIsValid;
8160 }
8161
8162 PFILE_OBJECT
8163 AFSReferenceCacheFileObject()
8164 {
8165
8166     AFSDeviceExt       *pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
8167     FILE_OBJECT        *pCacheFileObject = NULL;
8168
8169     AFSAcquireShared( &pRdrDevExt->Specific.RDR.CacheFileLock,
8170                       TRUE);
8171
8172     pCacheFileObject = pRdrDevExt->Specific.RDR.CacheFileObject;
8173
8174     if( pCacheFileObject != NULL)
8175     {
8176         ObReferenceObject( pCacheFileObject);
8177     }
8178
8179     AFSReleaseResource( &pRdrDevExt->Specific.RDR.CacheFileLock);
8180
8181     return pCacheFileObject;
8182 }
8183
8184 void
8185 AFSReleaseCacheFileObject( IN PFILE_OBJECT CacheFileObject)
8186 {
8187
8188     ASSERT( CacheFileObject != NULL);
8189
8190     ObDereferenceObject( CacheFileObject);
8191
8192     return;
8193 }
8194
8195 NTSTATUS
8196 AFSInitializeLibrary( IN AFSLibraryInitCB *LibraryInit)
8197 {
8198
8199     NTSTATUS ntStatus = STATUS_SUCCESS;
8200     AFSDeviceExt *pControlDevExt = NULL;
8201     ULONG ulTimeIncrement = 0;
8202     LONG lCount;
8203
8204     __Enter
8205     {
8206
8207         AFSControlDeviceObject = LibraryInit->AFSControlDeviceObject;
8208
8209         AFSRDRDeviceObject = LibraryInit->AFSRDRDeviceObject;
8210
8211         AFSServerName = LibraryInit->AFSServerName;
8212
8213         AFSMountRootName = LibraryInit->AFSMountRootName;
8214
8215         AFSDebugFlags = LibraryInit->AFSDebugFlags;
8216
8217         //
8218         // Callbacks in the framework
8219         //
8220
8221         AFSProcessRequest = LibraryInit->AFSProcessRequest;
8222
8223         AFSDbgLogMsg = LibraryInit->AFSDbgLogMsg;
8224
8225         AFSDebugTraceFnc = AFSDbgLogMsg;
8226
8227         AFSAddConnectionEx = LibraryInit->AFSAddConnectionEx;
8228
8229         AFSExAllocatePoolWithTag = LibraryInit->AFSExAllocatePoolWithTag;
8230
8231         AFSExFreePoolWithTag = LibraryInit->AFSExFreePoolWithTag;
8232
8233         AFSDumpTraceFilesFnc = LibraryInit->AFSDumpTraceFiles;
8234
8235         AFSRetrieveAuthGroupFnc = LibraryInit->AFSRetrieveAuthGroup;
8236
8237         AFSLibCacheManagerCallbacks = LibraryInit->AFSCacheManagerCallbacks;
8238
8239         if( LibraryInit->AFSCacheBaseAddress != NULL)
8240         {
8241
8242             SetFlag( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE);
8243
8244             AFSLibCacheBaseAddress = LibraryInit->AFSCacheBaseAddress;
8245
8246             AFSLibCacheLength = LibraryInit->AFSCacheLength;
8247         }
8248
8249         //
8250         // Initialize some flush parameters
8251         //
8252
8253         pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
8254
8255         ulTimeIncrement = KeQueryTimeIncrement();
8256
8257         pControlDevExt->Specific.Control.ObjectLifeTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_OBJECT_LIFETIME / (ULONGLONG)ulTimeIncrement);
8258         pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart = AFS_SERVER_PURGE_DELAY;
8259         pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart /= ulTimeIncrement;
8260         pControlDevExt->Specific.Control.FcbFlushTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_SERVER_FLUSH_DELAY / (ULONGLONG)ulTimeIncrement);
8261         pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_EXTENT_REQUEST_TIME/(ULONGLONG)ulTimeIncrement);
8262
8263         //
8264         // Initialize the global root entry
8265         //
8266
8267         ntStatus = AFSInitVolume( NULL,
8268                                   &LibraryInit->GlobalRootFid,
8269                                   AFS_VOLUME_REFERENCE_GLOBAL_ROOT,
8270                                   &AFSGlobalRoot);
8271
8272         if( !NT_SUCCESS( ntStatus))
8273         {
8274
8275             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
8276                           AFS_TRACE_LEVEL_ERROR,
8277                           "AFSInitializeLibrary AFSInitVolume failure %08lX\n",
8278                           ntStatus));
8279
8280             try_return( ntStatus);
8281         }
8282
8283         ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
8284                                    AFSGlobalRoot);
8285
8286         if( !NT_SUCCESS( ntStatus))
8287         {
8288
8289             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
8290                           AFS_TRACE_LEVEL_ERROR,
8291                           "AFSInitializeLibrary AFSInitRootFcb failure %08lX\n",
8292                           ntStatus));
8293
8294             lCount = AFSVolumeDecrement( AFSGlobalRoot,
8295                                          AFS_VOLUME_REFERENCE_GLOBAL_ROOT);
8296
8297             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8298                           AFS_TRACE_LEVEL_VERBOSE,
8299                           "AFSInitializeLibrary Decrement count on volume %p Cnt %d\n",
8300                           AFSGlobalRoot,
8301                           lCount));
8302
8303             AFSReleaseResource( AFSGlobalRoot->VolumeLock);
8304
8305             try_return( ntStatus);
8306         }
8307
8308         //
8309         // Update the node type code to AFS_ROOT_ALL
8310         //
8311
8312         AFSGlobalRoot->ObjectInformation.Fcb->Header.NodeTypeCode = AFS_ROOT_ALL;
8313
8314         SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_ACTIVE_GLOBAL_ROOT);
8315
8316         //
8317         // Invalidate all known volumes since contact with the service and therefore
8318         // the file server was lost.
8319         //
8320
8321         AFSInvalidateAllVolumes();
8322
8323         //
8324         // Drop the locks acquired above
8325         //
8326
8327         AFSInitVolumeWorker( AFSGlobalRoot);
8328
8329         lCount = AFSVolumeDecrement( AFSGlobalRoot,
8330                                      AFS_VOLUME_REFERENCE_GLOBAL_ROOT);
8331
8332         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8333                       AFS_TRACE_LEVEL_VERBOSE,
8334                       "AFSInitializeLibrary Decrement count on volume %p Cnt %d\n",
8335                       AFSGlobalRoot,
8336                       lCount));
8337
8338         AFSReleaseResource( AFSGlobalRoot->VolumeLock);
8339
8340         AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Fcb->Header.Resource);
8341
8342 try_exit:
8343
8344         NOTHING;
8345     }
8346
8347     return ntStatus;
8348 }
8349
8350 NTSTATUS
8351 AFSCloseLibrary()
8352 {
8353
8354     NTSTATUS ntStatus = STATUS_SUCCESS;
8355     AFSDirectoryCB *pDirNode = NULL, *pLastDirNode = NULL;
8356     LONG lCount;
8357
8358     __Enter
8359     {
8360
8361         if( AFSGlobalDotDirEntry != NULL)
8362         {
8363
8364             lCount = AFSObjectInfoDecrement( AFSGlobalDotDirEntry->ObjectInformation,
8365                                              AFS_OBJECT_REFERENCE_GLOBAL);
8366
8367             AFSDeleteObjectInfo( &AFSGlobalDotDirEntry->ObjectInformation);
8368
8369             ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
8370
8371             ExFreePool( AFSGlobalDotDirEntry->NonPaged);
8372
8373             ExFreePool( AFSGlobalDotDirEntry);
8374
8375             AFSGlobalDotDirEntry = NULL;
8376         }
8377
8378         if( AFSGlobalDotDotDirEntry != NULL)
8379         {
8380
8381             lCount = AFSObjectInfoDecrement( AFSGlobalDotDotDirEntry->ObjectInformation,
8382                                              AFS_OBJECT_REFERENCE_GLOBAL);
8383
8384             AFSDeleteObjectInfo( &AFSGlobalDotDotDirEntry->ObjectInformation);
8385
8386             ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
8387
8388             ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
8389
8390             ExFreePool( AFSGlobalDotDotDirEntry);
8391
8392             AFSGlobalDotDotDirEntry = NULL;
8393         }
8394
8395         if( AFSSpecialShareNames != NULL)
8396         {
8397
8398             pDirNode = AFSSpecialShareNames;
8399
8400             while( pDirNode != NULL)
8401             {
8402
8403                 pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
8404
8405                 lCount = AFSObjectInfoDecrement( pDirNode->ObjectInformation,
8406                                                  AFS_OBJECT_REFERENCE_GLOBAL);
8407
8408                 AFSDeleteObjectInfo( &pDirNode->ObjectInformation);
8409
8410                 ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
8411
8412                 ExFreePool( pDirNode->NonPaged);
8413
8414                 ExFreePool( pDirNode);
8415
8416                 pDirNode = pLastDirNode;
8417             }
8418
8419             AFSSpecialShareNames = NULL;
8420         }
8421     }
8422
8423     return ntStatus;
8424 }
8425
8426 NTSTATUS
8427 AFSDefaultLogMsg( IN ULONG Subsystem,
8428                   IN ULONG Level,
8429                   IN PCCH Format,
8430                   ...)
8431 {
8432
8433     UNREFERENCED_PARAMETER(Subsystem);
8434     UNREFERENCED_PARAMETER(Level);
8435     NTSTATUS ntStatus = STATUS_SUCCESS;
8436     va_list va_args;
8437     char chDebugBuffer[ 256];
8438
8439     __Enter
8440     {
8441
8442         va_start( va_args, Format);
8443
8444         ntStatus = RtlStringCbVPrintfA( chDebugBuffer,
8445                                         256,
8446                                         Format,
8447                                         va_args);
8448
8449         if( NT_SUCCESS( ntStatus))
8450         {
8451             DbgPrint( chDebugBuffer);
8452         }
8453
8454         va_end( va_args);
8455     }
8456
8457     return ntStatus;
8458 }
8459
8460 NTSTATUS
8461 AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
8462                     IN ULONG InputBufferLength,
8463                     IN AFSStatusInfoCB *StatusInfo,
8464                     OUT ULONG *ReturnLength)
8465 {
8466
8467     NTSTATUS ntStatus = STATUS_SUCCESS;
8468     AFSVolumeCB *pVolumeCB = NULL;
8469     LONG VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
8470     AFSVolumeCB *pNewVolumeCB = NULL;
8471     LONG NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
8472     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
8473     AFSObjectInfoCB *pObjectInfo = NULL;
8474     ULONGLONG   ullIndex = 0;
8475     UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName, uniParsedName;
8476     AFSNameArrayHdr *pNameArray = NULL;
8477     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
8478     AFSDirectoryCB *pNewParentDirEntry = NULL;
8479     LONG lCount;
8480
8481     __Enter
8482     {
8483
8484         //
8485         // If we are given a FID then look up the entry by that, otherwise
8486         // do it by name
8487         //
8488
8489         if( GetStatusInfo->FileID.Cell != 0 &&
8490             GetStatusInfo->FileID.Volume != 0 &&
8491             GetStatusInfo->FileID.Vnode != 0 &&
8492             GetStatusInfo->FileID.Unique != 0)
8493         {
8494
8495             AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
8496
8497             //
8498             // Locate the volume node
8499             //
8500
8501             ullIndex = AFSCreateHighIndex( &GetStatusInfo->FileID);
8502
8503             ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
8504                                            ullIndex,
8505                                            (AFSBTreeEntry **)&pVolumeCB);
8506
8507             if( pVolumeCB != NULL)
8508             {
8509
8510                 VolumeReferenceReason = AFS_VOLUME_REFERENCE_GET_OBJECT;
8511
8512                 lCount = AFSVolumeIncrement( pVolumeCB,
8513                                              VolumeReferenceReason);
8514
8515                 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8516                               AFS_TRACE_LEVEL_VERBOSE,
8517                               "AFSGetObjectStatus Increment count on volume %p Reason %u Cnt %d\n",
8518                               pVolumeCB,
8519                               VolumeReferenceReason,
8520                               lCount));
8521             }
8522
8523             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
8524
8525             if( !NT_SUCCESS( ntStatus) ||
8526                 pVolumeCB == NULL)
8527             {
8528                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8529             }
8530
8531             if( AFSIsVolumeFID( &GetStatusInfo->FileID))
8532             {
8533
8534                 pObjectInfo = &pVolumeCB->ObjectInformation;
8535
8536                 lCount = AFSObjectInfoIncrement( pObjectInfo,
8537                                                  AFS_OBJECT_REFERENCE_STATUS);
8538
8539                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8540                               AFS_TRACE_LEVEL_VERBOSE,
8541                               "AFSGetObjectStatus Increment1 count on object %p Cnt %d\n",
8542                               pObjectInfo,
8543                               lCount));
8544             }
8545             else
8546             {
8547
8548                 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
8549                                   TRUE);
8550
8551                 ullIndex = AFSCreateLowIndex( &GetStatusInfo->FileID);
8552
8553                 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
8554                                                ullIndex,
8555                                                (AFSBTreeEntry **)&pObjectInfo);
8556
8557                 if( pObjectInfo != NULL)
8558                 {
8559
8560                     //
8561                     // Reference the node so it won't be torn down
8562                     //
8563
8564                     lCount = AFSObjectInfoIncrement( pObjectInfo,
8565                                                      AFS_OBJECT_REFERENCE_STATUS);
8566
8567                     AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8568                                   AFS_TRACE_LEVEL_VERBOSE,
8569                                   "AFSGetObjectStatus Increment2 count on object %p Cnt %d\n",
8570                                   pObjectInfo,
8571                                   lCount));
8572                 }
8573
8574                 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
8575
8576                 if( !NT_SUCCESS( ntStatus) ||
8577                     pObjectInfo == NULL)
8578                 {
8579                     try_return( ntStatus = STATUS_INVALID_PARAMETER);
8580                 }
8581             }
8582         }
8583         else
8584         {
8585
8586             if( GetStatusInfo->FileNameLength == 0 ||
8587                 InputBufferLength < (ULONG)(FIELD_OFFSET( AFSGetStatusInfoCB, FileName) + GetStatusInfo->FileNameLength))
8588             {
8589                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8590             }
8591
8592             uniFullPathName.Length = GetStatusInfo->FileNameLength;
8593             uniFullPathName.MaximumLength = uniFullPathName.Length;
8594
8595             uniFullPathName.Buffer = (WCHAR *)GetStatusInfo->FileName;
8596
8597             //
8598             // This name should begin with the \afs server so parse it off and check it
8599             //
8600
8601             FsRtlDissectName( uniFullPathName,
8602                               &uniComponentName,
8603                               &uniRemainingPath);
8604
8605             if( RtlCompareUnicodeString( &uniComponentName,
8606                                          &AFSServerName,
8607                                          TRUE) != 0)
8608             {
8609                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8610                               AFS_TRACE_LEVEL_ERROR,
8611                               "AFSGetObjectStatus Name %wZ contains invalid server name\n",
8612                               &uniFullPathName));
8613
8614                 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
8615             }
8616
8617             uniFullPathName = uniRemainingPath;
8618
8619             uniParsedName = uniFullPathName;
8620
8621             //
8622             // Our name array
8623             //
8624
8625             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
8626                                            0);
8627
8628             if( pNameArray == NULL)
8629             {
8630                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8631             }
8632
8633             pVolumeCB = AFSGlobalRoot;
8634
8635             pParentDirEntry = AFSGlobalRoot->DirectoryCB;
8636
8637             //
8638             // Increment the ref count on the volume and dir entry for correct processing below
8639             //
8640
8641             VolumeReferenceReason = AFS_VOLUME_REFERENCE_GET_OBJECT;
8642
8643             lCount = AFSVolumeIncrement( pVolumeCB,
8644                                          VolumeReferenceReason);
8645
8646             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8647                           AFS_TRACE_LEVEL_VERBOSE,
8648                           "AFSGetObjectStatus Increment2 count on volume %p Reason %u Cnt %d\n",
8649                           pVolumeCB,
8650                           VolumeReferenceReason,
8651                           lCount));
8652
8653             lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
8654
8655             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8656                           AFS_TRACE_LEVEL_VERBOSE,
8657                           "AFSGetObjectStatus Increment count on %wZ DE %p Ccb %p Cnt %d\n",
8658                           &pParentDirEntry->NameInformation.FileName,
8659                           pParentDirEntry,
8660                           NULL,
8661                           lCount));
8662
8663             ntStatus = AFSLocateNameEntry( NULL,
8664                                            NULL,
8665                                            &uniFullPathName,
8666                                            &uniParsedName,
8667                                            pNameArray,
8668                                            AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL |
8669                                                AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL,
8670                                            pVolumeCB,
8671                                            pParentDirEntry,
8672                                            &pNewVolumeCB,
8673                                            &NewVolumeReferenceReason,
8674                                            &pNewParentDirEntry,
8675                                            &pDirectoryEntry,
8676                                            NULL);
8677
8678             if ( pNewVolumeCB != NULL)
8679             {
8680
8681                 //
8682                 // AFSLocateNameEntry returns pNewVolumeCB with a reference held
8683                 // even if pVolumeCB == pNewVolumeCB.  It is always safe to release
8684                 // the reference on pVolumeCB that was held prior to the call.
8685                 // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
8686                 // will be released second.
8687                 //
8688
8689                 lCount = AFSVolumeDecrement( pVolumeCB,
8690                                              VolumeReferenceReason);
8691
8692                 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8693                               AFS_TRACE_LEVEL_VERBOSE,
8694                               "AFSGetObjectStatus Decrement count on volume %p Reason %u Cnt %d\n",
8695                               pVolumeCB,
8696                               VolumeReferenceReason,
8697                               lCount));
8698
8699                 pVolumeCB = pNewVolumeCB;
8700
8701                 pNewVolumeCB = NULL;
8702
8703                 VolumeReferenceReason = NewVolumeReferenceReason;
8704
8705                 NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
8706             }
8707
8708             //
8709             // AFSLocateNameEntry does not alter the reference count of
8710             // pParentDirectoryCB and it returns pNewParentDirectoryCB with
8711             // a reference held.
8712             //
8713
8714             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
8715
8716             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8717                           AFS_TRACE_LEVEL_VERBOSE,
8718                           "AFSGetObjectStatus DecrementX count on %wZ DE %p Cnt %d\n",
8719                           &pParentDirEntry->NameInformation.FileName,
8720                           pParentDirEntry,
8721                           lCount));
8722
8723             pParentDirEntry = pNewParentDirEntry;
8724
8725             pNewParentDirEntry = NULL;
8726
8727             if( !NT_SUCCESS( ntStatus) ||
8728                 ntStatus == STATUS_REPARSE)
8729             {
8730
8731                 pVolumeCB = NULL;
8732
8733                 try_return( ntStatus);
8734             }
8735
8736             pObjectInfo = pDirectoryEntry->ObjectInformation;
8737
8738             lCount = AFSObjectInfoIncrement( pObjectInfo,
8739                                              AFS_OBJECT_REFERENCE_STATUS);
8740
8741             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8742                           AFS_TRACE_LEVEL_VERBOSE,
8743                           "AFSGetObjectStatus Increment3 count on object %p Cnt %d\n",
8744                           pObjectInfo,
8745                           lCount));
8746         }
8747
8748         //
8749         // At this point we have an object info block, return the information
8750         //
8751
8752         StatusInfo->FileId = pObjectInfo->FileId;
8753
8754         StatusInfo->TargetFileId = pObjectInfo->TargetFileId;
8755
8756         StatusInfo->Expiration = pObjectInfo->Expiration;
8757
8758         StatusInfo->DataVersion = pObjectInfo->DataVersion;
8759
8760         StatusInfo->FileType = pObjectInfo->FileType;
8761
8762         StatusInfo->ObjectFlags = pObjectInfo->Flags;
8763
8764         StatusInfo->CreationTime = pObjectInfo->CreationTime;
8765
8766         StatusInfo->LastAccessTime = pObjectInfo->LastAccessTime;
8767
8768         StatusInfo->LastWriteTime = pObjectInfo->LastWriteTime;
8769
8770         StatusInfo->ChangeTime = pObjectInfo->ChangeTime;
8771
8772         StatusInfo->FileAttributes = pObjectInfo->FileAttributes;
8773
8774         StatusInfo->EndOfFile = pObjectInfo->EndOfFile;
8775
8776         StatusInfo->AllocationSize = pObjectInfo->AllocationSize;
8777
8778         StatusInfo->EaSize = pObjectInfo->EaSize;
8779
8780         StatusInfo->Links = pObjectInfo->Links;
8781
8782         //
8783         // Return the information length
8784         //
8785
8786         *ReturnLength = sizeof( AFSStatusInfoCB);
8787
8788 try_exit:
8789
8790         if( pDirectoryEntry != NULL)
8791         {
8792
8793             lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
8794
8795             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8796                           AFS_TRACE_LEVEL_VERBOSE,
8797                           "AFSGetObjectStatus Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
8798                           &pDirectoryEntry->NameInformation.FileName,
8799                           pDirectoryEntry,
8800                           NULL,
8801                           lCount));
8802
8803             ASSERT( lCount >= 0);
8804         }
8805
8806         if ( pParentDirEntry != NULL)
8807         {
8808
8809             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
8810
8811             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8812                           AFS_TRACE_LEVEL_VERBOSE,
8813                           "AFSGetObjectStatus Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
8814                           &pParentDirEntry->NameInformation.FileName,
8815                           pParentDirEntry,
8816                           NULL,
8817                           lCount));
8818
8819             ASSERT( lCount >= 0);
8820         }
8821
8822         if( pObjectInfo != NULL)
8823         {
8824
8825             lCount = AFSObjectInfoDecrement( pObjectInfo,
8826                                              AFS_OBJECT_REFERENCE_STATUS);
8827
8828             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8829                           AFS_TRACE_LEVEL_VERBOSE,
8830                           "AFSGetObjectStatus Decrement count on object %p Cnt %d\n",
8831                           pObjectInfo,
8832                           lCount));
8833         }
8834
8835         if( pVolumeCB != NULL)
8836         {
8837
8838             lCount = AFSVolumeDecrement( pVolumeCB,
8839                                          VolumeReferenceReason);
8840
8841             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8842                           AFS_TRACE_LEVEL_VERBOSE,
8843                           "AFSGetObjectStatus Decrement4 count on volume %p Reason %u Cnt %d\n",
8844                           pVolumeCB,
8845                           VolumeReferenceReason,
8846                           lCount));
8847         }
8848
8849         if( pNameArray != NULL)
8850         {
8851
8852             AFSFreeNameArray( pNameArray);
8853         }
8854     }
8855
8856     return ntStatus;
8857 }
8858
8859 NTSTATUS
8860 AFSCheckSymlinkAccess( IN AFSDirectoryCB *ParentDirectoryCB,
8861                        IN UNICODE_STRING *ComponentName)
8862 {
8863
8864     NTSTATUS ntStatus = STATUS_SUCCESS;
8865     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
8866     AFSDirectoryCB *pDirEntry = NULL;
8867     ULONG ulCRC = 0;
8868     LONG lCount;
8869
8870     __Enter
8871     {
8872
8873         //
8874         // Search for the entry in the parent
8875         //
8876
8877         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8878                       AFS_TRACE_LEVEL_VERBOSE_2,
8879                       "AFSCheckSymlinkAccess Searching for entry %wZ case sensitive\n",
8880                       ComponentName));
8881
8882         ulCRC = AFSGenerateCRC( ComponentName,
8883                                 FALSE);
8884
8885         AFSAcquireShared( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
8886                           TRUE);
8887
8888         AFSLocateCaseSensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
8889                                         ulCRC,
8890                                         &pDirEntry);
8891
8892         if( pDirEntry == NULL)
8893         {
8894
8895             //
8896             // Missed so perform a case insensitive lookup
8897             //
8898
8899             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8900                           AFS_TRACE_LEVEL_VERBOSE_2,
8901                           "AFSCheckSymlinkAccess Searching for entry %wZ case insensitive\n",
8902                           ComponentName));
8903
8904             ulCRC = AFSGenerateCRC( ComponentName,
8905                                     TRUE);
8906
8907             AFSLocateCaseInsensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
8908                                               ulCRC,
8909                                               &pDirEntry);
8910
8911             if( pDirEntry == NULL)
8912             {
8913
8914                 //
8915                 // OK, if this component is a valid short name then try
8916                 // a lookup in the short name tree
8917                 //
8918
8919                 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
8920                     RtlIsNameLegalDOS8Dot3( ComponentName,
8921                                             NULL,
8922                                             NULL))
8923                 {
8924
8925                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8926                                   AFS_TRACE_LEVEL_VERBOSE_2,
8927                                   "AFSCheckSymlinkAccess Searching for entry %wZ short name\n",
8928                                   ComponentName));
8929
8930                     AFSLocateShortNameDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.ShortNameTree,
8931                                                 ulCRC,
8932                                                 &pDirEntry);
8933                 }
8934             }
8935         }
8936
8937         if( pDirEntry != NULL)
8938         {
8939             lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
8940
8941             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8942                           AFS_TRACE_LEVEL_VERBOSE,
8943                           "AFSCheckSymlinkAccess Increment count on %wZ DE %p Ccb %p Cnt %d\n",
8944                           &pDirEntry->NameInformation.FileName,
8945                           pDirEntry,
8946                           NULL,
8947                           lCount));
8948
8949             ASSERT( lCount >= 0);
8950         }
8951
8952         AFSReleaseResource( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
8953
8954         if( pDirEntry == NULL)
8955         {
8956
8957             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8958                           AFS_TRACE_LEVEL_VERBOSE_2,
8959                           "AFSCheckSymlinkAccess Failed to locate entry %wZ ntStatus %08X\n",
8960                           ComponentName,
8961                           STATUS_OBJECT_NAME_NOT_FOUND));
8962
8963             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
8964         }
8965
8966         //
8967         // We have the symlink object but previously failed to process it so return access
8968         // denied.
8969         //
8970
8971         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8972                       AFS_TRACE_LEVEL_VERBOSE_2,
8973                       "AFSCheckSymlinkAccess Failing symlink access to entry %wZ REPARSE_POINT_NOT_RESOLVED\n",
8974                       ComponentName));
8975
8976         ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
8977
8978         lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
8979
8980         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8981                       AFS_TRACE_LEVEL_VERBOSE,
8982                       "AFSCheckSymlinkAccess Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
8983                       &pDirEntry->NameInformation.FileName,
8984                       pDirEntry,
8985                       NULL,
8986                       lCount));
8987
8988         ASSERT( lCount >= 0);
8989
8990 try_exit:
8991
8992         NOTHING;
8993     }
8994
8995     return ntStatus;
8996 }
8997
8998 NTSTATUS
8999 AFSRetrieveFinalComponent( IN UNICODE_STRING *FullPathName,
9000                            OUT UNICODE_STRING *ComponentName)
9001 {
9002
9003     NTSTATUS ntStatus = STATUS_SUCCESS;
9004     UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName;
9005
9006     uniFullPathName = *FullPathName;
9007
9008     while( TRUE)
9009     {
9010
9011         FsRtlDissectName( uniFullPathName,
9012                           &uniComponentName,
9013                           &uniRemainingPath);
9014
9015         if( uniRemainingPath.Length == 0)
9016         {
9017             break;
9018         }
9019
9020         uniFullPathName = uniRemainingPath;
9021     }
9022
9023     if( uniComponentName.Length > 0)
9024     {
9025         *ComponentName = uniComponentName;
9026     }
9027
9028     return ntStatus;
9029 }
9030
9031 void
9032 AFSDumpTraceFiles_Default()
9033 {
9034     return;
9035 }
9036
9037 BOOLEAN
9038 AFSValidNameFormat( IN UNICODE_STRING *FileName)
9039 {
9040
9041     BOOLEAN bIsValidName = TRUE;
9042     USHORT usIndex = 0;
9043
9044     __Enter
9045     {
9046
9047         while( usIndex < FileName->Length/sizeof( WCHAR))
9048         {
9049
9050             if( FileName->Buffer[ usIndex] == L':' ||
9051                 FileName->Buffer[ usIndex] == L'*' ||
9052                 FileName->Buffer[ usIndex] == L'?' ||
9053                 FileName->Buffer[ usIndex] == L'"' ||
9054                 FileName->Buffer[ usIndex] == L'<' ||
9055                 FileName->Buffer[ usIndex] == L'>')
9056             {
9057                 bIsValidName = FALSE;
9058                 break;
9059             }
9060
9061             usIndex++;
9062         }
9063     }
9064
9065     return bIsValidName;
9066 }
9067
9068 NTSTATUS
9069 AFSCreateDefaultSecurityDescriptor()
9070 {
9071
9072     NTSTATUS ntStatus = STATUS_SUCCESS;
9073     PACL pSACL = NULL;
9074     ULONG ulSACLSize = 0;
9075     SYSTEM_MANDATORY_LABEL_ACE* pACE = NULL;
9076     ULONG ulACESize = 0;
9077     SECURITY_DESCRIPTOR *pSecurityDescr = NULL;
9078     ULONG ulSDLength = 0;
9079     SECURITY_DESCRIPTOR *pRelativeSecurityDescr = NULL;
9080     PSID pWorldSID = NULL;
9081     ULONG *pulSubAuthority = NULL;
9082     ULONG ulWorldSIDLEngth = 0;
9083
9084     __Enter
9085     {
9086
9087         ulWorldSIDLEngth = RtlLengthRequiredSid( 1);
9088
9089         pWorldSID = (PSID)ExAllocatePoolWithTag( PagedPool,
9090                                                  ulWorldSIDLEngth,
9091                                                  AFS_GENERIC_MEMORY_29_TAG);
9092
9093         if( pWorldSID == NULL)
9094         {
9095             AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate World SID\n");
9096
9097             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
9098         }
9099
9100         RtlZeroMemory( pWorldSID,
9101                        ulWorldSIDLEngth);
9102
9103         RtlInitializeSid( pWorldSID,
9104                           &SeWorldSidAuthority,
9105                           1);
9106
9107         pulSubAuthority = RtlSubAuthoritySid(pWorldSID, 0);
9108         *pulSubAuthority = SECURITY_WORLD_RID;
9109
9110         if( AFSRtlSetSaclSecurityDescriptor == NULL)
9111         {
9112
9113             AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor == NULL\n");
9114         }
9115         else
9116         {
9117
9118             ulACESize = sizeof( SYSTEM_MANDATORY_LABEL_ACE) + 128;
9119
9120             pACE = (SYSTEM_MANDATORY_LABEL_ACE *)ExAllocatePoolWithTag( PagedPool,
9121                                                                         ulACESize,
9122                                                                         AFS_GENERIC_MEMORY_29_TAG);
9123
9124             if( pACE == NULL)
9125             {
9126
9127                 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
9128
9129                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
9130             }
9131
9132             RtlZeroMemory( pACE,
9133                            ulACESize);
9134
9135             pACE->Header.AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
9136             pACE->Header.AceType = SYSTEM_MANDATORY_LABEL_ACE_TYPE;
9137             pACE->Header.AceSize = FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + (USHORT)RtlLengthSid( SeExports->SeLowMandatorySid);
9138             pACE->Mask = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP;
9139
9140             RtlCopySid( RtlLengthSid( SeExports->SeLowMandatorySid),
9141                         &pACE->SidStart,
9142                         SeExports->SeLowMandatorySid);
9143
9144             ulSACLSize = sizeof(ACL) + RtlLengthSid( SeExports->SeLowMandatorySid) +
9145                 FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + ulACESize;
9146
9147             pSACL = (PACL)ExAllocatePoolWithTag( PagedPool,
9148                                                  ulSACLSize,
9149                                                  AFS_GENERIC_MEMORY_29_TAG);
9150
9151             if( pSACL == NULL)
9152             {
9153
9154                 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
9155
9156                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
9157             }
9158
9159             ntStatus = RtlCreateAcl( pSACL,
9160                                      ulSACLSize,
9161                                      ACL_REVISION);
9162
9163             if( !NT_SUCCESS( ntStatus))
9164             {
9165
9166                 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateAcl ntStatus %08lX\n",
9167                           ntStatus);
9168
9169                 try_return( ntStatus);
9170             }
9171
9172             ntStatus = RtlAddAce( pSACL,
9173                                   ACL_REVISION,
9174                                   0,
9175                                   pACE,
9176                                   pACE->Header.AceSize);
9177
9178             if( !NT_SUCCESS( ntStatus))
9179             {
9180
9181                 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAddAce ntStatus %08lX\n",
9182                           ntStatus);
9183
9184                 try_return( ntStatus);
9185             }
9186         }
9187
9188         pSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
9189                                                                        sizeof( SECURITY_DESCRIPTOR),
9190                                                                        AFS_GENERIC_MEMORY_27_TAG);
9191
9192         if( pSecurityDescr == NULL)
9193         {
9194
9195             AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
9196
9197             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
9198         }
9199
9200         ntStatus = RtlCreateSecurityDescriptor( pSecurityDescr,
9201                                                 SECURITY_DESCRIPTOR_REVISION);
9202
9203         if( !NT_SUCCESS( ntStatus))
9204         {
9205
9206             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateSecurityDescriptor ntStatus %08lX\n",
9207                       ntStatus);
9208
9209             try_return( ntStatus);
9210         }
9211
9212         if( AFSRtlSetSaclSecurityDescriptor != NULL)
9213         {
9214             ntStatus = AFSRtlSetSaclSecurityDescriptor( pSecurityDescr,
9215                                                         TRUE,
9216                                                         pSACL,
9217                                                         FALSE);
9218
9219             if( !NT_SUCCESS( ntStatus))
9220             {
9221
9222                 AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor ntStatus %08lX\n",
9223                           ntStatus);
9224
9225                 try_return( ntStatus);
9226             }
9227         }
9228
9229         //
9230         // Add in the group and owner to the SD
9231         //
9232
9233         if( AFSRtlSetGroupSecurityDescriptor != NULL)
9234         {
9235             ntStatus = AFSRtlSetGroupSecurityDescriptor( pSecurityDescr,
9236                                                          pWorldSID,
9237                                                          FALSE);
9238
9239             if( !NT_SUCCESS( ntStatus))
9240             {
9241
9242                 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetGroupSecurityDescriptor failed ntStatus %08lX\n",
9243                           ntStatus);
9244
9245                 try_return( ntStatus);
9246             }
9247         }
9248
9249         ntStatus = RtlSetOwnerSecurityDescriptor( pSecurityDescr,
9250                                                   pWorldSID,
9251                                                   FALSE);
9252
9253         if( !NT_SUCCESS( ntStatus))
9254         {
9255
9256             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetOwnerSecurityDescriptor failed ntStatus %08lX\n",
9257                       ntStatus);
9258
9259             try_return( ntStatus);
9260         }
9261
9262         if( !RtlValidSecurityDescriptor( pSecurityDescr))
9263         {
9264
9265             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlValidSecurityDescriptor NOT\n");
9266
9267             try_return( ntStatus = STATUS_INVALID_PARAMETER);
9268         }
9269
9270         pRelativeSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
9271                                                                                PAGE_SIZE,
9272                                                                                AFS_GENERIC_MEMORY_27_TAG);
9273
9274         if( pRelativeSecurityDescr == NULL)
9275         {
9276
9277             AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
9278
9279             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
9280         }
9281
9282         ulSDLength = PAGE_SIZE;
9283
9284         ntStatus = RtlAbsoluteToSelfRelativeSD( pSecurityDescr,
9285                                                 pRelativeSecurityDescr,
9286                                                 &ulSDLength);
9287
9288         if( !NT_SUCCESS( ntStatus))
9289         {
9290
9291             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAbsoluteToSelfRelativeSD ntStatus %08lX\n",
9292                       ntStatus);
9293
9294             try_return( ntStatus);
9295         }
9296
9297         AFSDefaultSD = pRelativeSecurityDescr;
9298
9299 try_exit:
9300
9301         if( !NT_SUCCESS( ntStatus))
9302         {
9303
9304             if( pRelativeSecurityDescr != NULL)
9305             {
9306                 ExFreePool( pRelativeSecurityDescr);
9307             }
9308         }
9309
9310         if( pSecurityDescr != NULL)
9311         {
9312             ExFreePool( pSecurityDescr);
9313         }
9314
9315         if( pSACL != NULL)
9316         {
9317             ExFreePool( pSACL);
9318         }
9319
9320         if( pACE != NULL)
9321         {
9322             ExFreePool( pACE);
9323         }
9324
9325         if( pWorldSID != NULL)
9326         {
9327             ExFreePool( pWorldSID);
9328         }
9329     }
9330
9331     return ntStatus;
9332 }
9333
9334 void
9335 AFSRetrieveParentPath( IN UNICODE_STRING *FullFileName,
9336                        OUT UNICODE_STRING *ParentPath)
9337 {
9338
9339     *ParentPath = *FullFileName;
9340
9341     //
9342     // If the final character is a \, jump over it
9343     //
9344
9345     if( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] == L'\\')
9346     {
9347         ParentPath->Length -= sizeof( WCHAR);
9348     }
9349
9350     while( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] != L'\\')
9351     {
9352         ParentPath->Length -= sizeof( WCHAR);
9353     }
9354
9355     //
9356     // And the separator
9357     //
9358
9359     ParentPath->Length -= sizeof( WCHAR);
9360
9361     return;
9362 }
9363
9364 NTSTATUS
9365 AFSRetrieveValidAuthGroup( IN AFSFcb *Fcb,
9366                            IN AFSObjectInfoCB *ObjectInfo,
9367                            IN BOOLEAN WriteAccess,
9368                            OUT GUID *AuthGroup)
9369 {
9370
9371     NTSTATUS ntStatus = STATUS_SUCCESS;
9372     GUID     stAuthGroup, stZeroAuthGroup;
9373     BOOLEAN  bFoundAuthGroup = FALSE;
9374     AFSCcb  *pCcb = NULL;
9375     AFSFcb *pFcb = Fcb;
9376
9377     __Enter
9378     {
9379
9380         RtlZeroMemory( &stAuthGroup,
9381                        sizeof( GUID));
9382
9383         RtlZeroMemory( &stZeroAuthGroup,
9384                        sizeof( GUID));
9385
9386         if( Fcb == NULL)
9387         {
9388
9389             if( ObjectInfo != NULL &&
9390                 ObjectInfo->Fcb != NULL)
9391             {
9392                 pFcb = ObjectInfo->Fcb;
9393             }
9394         }
9395
9396         if( pFcb != NULL)
9397         {
9398
9399             AFSAcquireShared( &Fcb->NPFcb->CcbListLock,
9400                               TRUE);
9401
9402             pCcb = Fcb->CcbListHead;
9403
9404             while( pCcb != NULL)
9405             {
9406
9407                 if( WriteAccess &&
9408                     pCcb->GrantedAccess & FILE_WRITE_DATA)
9409                 {
9410                     RtlCopyMemory( &stAuthGroup,
9411                                    &pCcb->AuthGroup,
9412                                    sizeof( GUID));
9413
9414                     bFoundAuthGroup = TRUE;
9415
9416                     break;
9417                 }
9418                 else if( pCcb->GrantedAccess & FILE_READ_DATA)
9419                 {
9420                     //
9421                     // At least get the read-only access
9422                     //
9423
9424                     RtlCopyMemory( &stAuthGroup,
9425                                    &pCcb->AuthGroup,
9426                                    sizeof( GUID));
9427
9428                     bFoundAuthGroup = TRUE;
9429                 }
9430
9431                 pCcb = (AFSCcb *)pCcb->ListEntry.fLink;
9432             }
9433
9434             AFSReleaseResource( &Fcb->NPFcb->CcbListLock);
9435         }
9436
9437         if( !bFoundAuthGroup)
9438         {
9439
9440             AFSRetrieveAuthGroupFnc( (ULONGLONG)PsGetCurrentProcessId(),
9441                                      (ULONGLONG)PsGetCurrentThreadId(),
9442                                       &stAuthGroup);
9443
9444             if( RtlCompareMemory( &stZeroAuthGroup,
9445                                   &stAuthGroup,
9446                                   sizeof( GUID)) == sizeof( GUID))
9447             {
9448
9449                 DbgPrint("AFSRetrieveValidAuthGroup Failed to locate PAG\n");
9450
9451                 try_return( ntStatus = STATUS_ACCESS_DENIED);
9452             }
9453         }
9454
9455         RtlCopyMemory( AuthGroup,
9456                        &stAuthGroup,
9457                        sizeof( GUID));
9458
9459 try_exit:
9460
9461         NOTHING;
9462     }
9463
9464     return ntStatus;
9465 }
9466
9467 NTSTATUS
9468 AFSPerformObjectInvalidate( IN AFSObjectInfoCB *ObjectInfo,
9469                             IN ULONG InvalidateReason)
9470 {
9471
9472     NTSTATUS            ntStatus = STATUS_SUCCESS;
9473     LIST_ENTRY         *le;
9474     AFSExtent          *pEntry;
9475     ULONG               ulProcessCount = 0;
9476     ULONG               ulCount = 0;
9477     LONG                lCount;
9478
9479     __Enter
9480     {
9481
9482         switch( InvalidateReason)
9483         {
9484
9485             case AFS_INVALIDATE_DELETED:
9486             {
9487
9488                 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
9489                     ObjectInfo->Fcb != NULL)
9490                 {
9491
9492                     AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9493                                     TRUE);
9494
9495                     ObjectInfo->Links = 0;
9496
9497                     ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
9498
9499                     KeSetEvent( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
9500                                 0,
9501                                 FALSE);
9502
9503                     //
9504                     // Clear out the extents
9505                     // And get rid of them (note this involves waiting
9506                     // for any writes or reads to the cache to complete)
9507                     //
9508
9509                     AFSTearDownFcbExtents( ObjectInfo->Fcb,
9510                                            NULL);
9511
9512                     AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
9513                 }
9514
9515                 break;
9516             }
9517
9518             case AFS_INVALIDATE_DATA_VERSION:
9519             {
9520
9521                 LARGE_INTEGER liCurrentOffset = {0,0};
9522                 LARGE_INTEGER liFlushLength = {0,0};
9523                 ULONG ulFlushLength = 0;
9524                 BOOLEAN bLocked = FALSE;
9525                 BOOLEAN bExtentsLocked = FALSE;
9526                 BOOLEAN bCleanExtents = FALSE;
9527
9528                 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
9529                     ObjectInfo->Fcb != NULL)
9530                 {
9531
9532                     AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Resource,
9533                                     TRUE);
9534
9535                     bLocked = TRUE;
9536
9537                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9538                                   AFS_TRACE_LEVEL_VERBOSE,
9539                                   "AFSPerformObjectInvalidate Acquiring Fcb extents lock %p SHARED %08lX\n",
9540                                   &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9541                                   PsGetCurrentThread()));
9542
9543                     AFSAcquireShared( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9544                                       TRUE);
9545
9546                     bExtentsLocked = TRUE;
9547
9548                     //
9549                     // There are several possibilities here:
9550                     //
9551                     // 0. If there are no extents or all of the extents are dirty, do nothing.
9552                     //
9553                     // 1. There could be nothing dirty and an open reference count of zero
9554                     //    in which case we can just tear down all of the extents without
9555                     //    holding any resources.
9556                     //
9557                     // 2. There could be nothing dirty and a non-zero open reference count
9558                     //    in which case we can issue a CcPurge against the entire file
9559                     //    while holding just the Fcb Resource.
9560                     //
9561                     // 3. There can be dirty extents in which case we need to identify
9562                     //    the non-dirty ranges and then perform a CcPurge on just the
9563                     //    non-dirty ranges while holding just the Fcb Resource.
9564                     //
9565
9566                     if ( ObjectInfo->Fcb->Specific.File.ExtentCount != ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount)
9567                     {
9568
9569                         if ( ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount == 0)
9570                         {
9571
9572                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9573
9574                             bExtentsLocked = FALSE;
9575
9576                             if ( ObjectInfo->Fcb->OpenReferenceCount == 0)
9577                             {
9578
9579                                 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9580
9581                                 bLocked = FALSE;
9582
9583                                 AFSTearDownFcbExtents( ObjectInfo->Fcb,
9584                                                        NULL);
9585                             }
9586                             else
9587                             {
9588
9589                                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9590                                               AFS_TRACE_LEVEL_VERBOSE,
9591                                               "AFSPerformObjectInvalidation Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
9592                                               &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9593                                               PsGetCurrentThread()));
9594
9595                                 AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9596                                                 TRUE);
9597
9598                                 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9599
9600                                 bLocked = FALSE;
9601
9602                                 __try
9603                                 {
9604
9605                                     if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
9606                                         !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9607                                                               NULL,
9608                                                               0,
9609                                                               FALSE))
9610                                     {
9611
9612                                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9613                                                       AFS_TRACE_LEVEL_WARNING,
9614                                                       "AFSPerformObjectInvalidation CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9615                                                       ObjectInfo->FileId.Cell,
9616                                                       ObjectInfo->FileId.Volume,
9617                                                       ObjectInfo->FileId.Vnode,
9618                                                       ObjectInfo->FileId.Unique));
9619
9620                                         SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9621                                     }
9622                                     else
9623                                     {
9624
9625                                         bCleanExtents = TRUE;
9626                                     }
9627                                 }
9628                                 __except( EXCEPTION_EXECUTE_HANDLER)
9629                                 {
9630
9631                                     ntStatus = GetExceptionCode();
9632
9633                                     AFSDbgTrace(( 0,
9634                                                   0,
9635                                                   "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
9636                                                   ObjectInfo->FileId.Cell,
9637                                                   ObjectInfo->FileId.Volume,
9638                                                   ObjectInfo->FileId.Vnode,
9639                                                   ObjectInfo->FileId.Unique,
9640                                                   ntStatus));
9641
9642                                     SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9643                                 }
9644
9645                                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9646                                               AFS_TRACE_LEVEL_VERBOSE,
9647                                               "AFSPerformObjectInvalidation Releasing Fcb SectionObject lock %p EXCL %08lX\n",
9648                                               &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9649                                               PsGetCurrentThread()));
9650
9651                                 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
9652                             }
9653                         }
9654                         else
9655                         {
9656
9657                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9658
9659                             bExtentsLocked = FALSE;
9660
9661                             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9662                                           AFS_TRACE_LEVEL_VERBOSE,
9663                                           "AFSPerformObjectInvalidation Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
9664                                           &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9665                                           PsGetCurrentThread()));
9666
9667                             AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9668                                             TRUE);
9669
9670                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9671
9672                             bLocked = FALSE;
9673
9674                             //
9675                             // Must build a list of non-dirty ranges from the beginning of the file
9676                             // to the end.  There can be at most (Fcb->Specific.File.ExtentsDirtyCount + 1)
9677                             // ranges.  In all but the most extreme random data write scenario there will
9678                             // be significantly fewer.
9679                             //
9680                             // For each range we need offset and size.
9681                             //
9682
9683                             AFSByteRange * ByteRangeList = NULL;
9684                             ULONG          ulByteRangeCount = 0;
9685                             ULONG          ulIndex;
9686                             BOOLEAN        bPurgeOnClose = FALSE;
9687
9688                             __try
9689                             {
9690
9691                                 ulByteRangeCount = AFSConstructCleanByteRangeList( ObjectInfo->Fcb,
9692                                                                                    &ByteRangeList);
9693
9694                                 if ( ByteRangeList != NULL ||
9695                                      ulByteRangeCount == 0)
9696                                 {
9697
9698                                     for ( ulIndex = 0; ulIndex < ulByteRangeCount; ulIndex++)
9699                                     {
9700
9701                                         ULONG ulSize;
9702
9703                                         do {
9704
9705                                             ulSize = ByteRangeList[ulIndex].Length.QuadPart > DWORD_MAX ? DWORD_MAX : ByteRangeList[ulIndex].Length.LowPart;
9706
9707                                             if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
9708                                                 !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9709                                                                       &ByteRangeList[ulIndex].FileOffset,
9710                                                                       ulSize,
9711                                                                       FALSE))
9712                                             {
9713
9714                                                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9715                                                               AFS_TRACE_LEVEL_WARNING,
9716                                                               "AFSPerformObjectInvalidation [1] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9717                                                               ObjectInfo->FileId.Cell,
9718                                                               ObjectInfo->FileId.Volume,
9719                                                               ObjectInfo->FileId.Vnode,
9720                                                               ObjectInfo->FileId.Unique));
9721
9722                                                 bPurgeOnClose = TRUE;
9723                                             }
9724                                             else
9725                                             {
9726
9727                                                 bCleanExtents = TRUE;
9728                                             }
9729
9730                                             ByteRangeList[ulIndex].Length.QuadPart -= ulSize;
9731
9732                                             ByteRangeList[ulIndex].FileOffset.QuadPart += ulSize;
9733
9734                                         } while ( ByteRangeList[ulIndex].Length.QuadPart > 0);
9735                                     }
9736                                 }
9737                                 else
9738                                 {
9739
9740                                     //
9741                                     // We couldn't allocate the memory to build the purge list
9742                                     // so just walk the extent list while holding the ExtentsList Resource.
9743                                     // This could deadlock but we do not have much choice.
9744                                     //
9745
9746                                     AFSAcquireExcl(  &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9747                                                     TRUE);
9748                                     bExtentsLocked = TRUE;
9749
9750                                     le = ObjectInfo->Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
9751
9752                                     ulProcessCount = 0;
9753
9754                                     ulCount = (ULONG)ObjectInfo->Fcb->Specific.File.ExtentCount;
9755
9756                                     if( ulCount > 0)
9757                                     {
9758                                         pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
9759
9760                                         while( ulProcessCount < ulCount)
9761                                         {
9762                                             pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
9763
9764                                             if( !BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
9765                                             {
9766                                                 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9767                                                                           &pEntry->FileOffset,
9768                                                                           pEntry->Size,
9769                                                                           FALSE))
9770                                                 {
9771
9772                                                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9773                                                                   AFS_TRACE_LEVEL_WARNING,
9774                                                                   "AFSPerformObjectInvalidation [2] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9775                                                                   ObjectInfo->FileId.Cell,
9776                                                                   ObjectInfo->FileId.Volume,
9777                                                                   ObjectInfo->FileId.Vnode,
9778                                                                   ObjectInfo->FileId.Unique));
9779
9780                                                     bPurgeOnClose = TRUE;
9781                                                 }
9782                                                 else
9783                                                 {
9784
9785                                                     bCleanExtents = TRUE;
9786                                                 }
9787                                             }
9788
9789                                             if( liCurrentOffset.QuadPart < pEntry->FileOffset.QuadPart)
9790                                             {
9791
9792                                                 liFlushLength.QuadPart = pEntry->FileOffset.QuadPart - liCurrentOffset.QuadPart;
9793
9794                                                 while( liFlushLength.QuadPart > 0)
9795                                                 {
9796
9797                                                     if( liFlushLength.QuadPart > 512 * 1024000)
9798                                                     {
9799                                                         ulFlushLength = 512 * 1024000;
9800                                                     }
9801                                                     else
9802                                                     {
9803                                                         ulFlushLength = liFlushLength.LowPart;
9804                                                     }
9805
9806                                                     if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9807                                                                               &liCurrentOffset,
9808                                                                               ulFlushLength,
9809                                                                               FALSE))
9810                                                     {
9811
9812                                                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9813                                                                       AFS_TRACE_LEVEL_WARNING,
9814                                                                       "AFSPerformObjectInvalidation [3] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9815                                                                       ObjectInfo->FileId.Cell,
9816                                                                       ObjectInfo->FileId.Volume,
9817                                                                       ObjectInfo->FileId.Vnode,
9818                                                                       ObjectInfo->FileId.Unique));
9819
9820                                                         bPurgeOnClose = TRUE;
9821                                                     }
9822                                                     else
9823                                                     {
9824
9825                                                         bCleanExtents = TRUE;
9826                                                     }
9827
9828                                                     liFlushLength.QuadPart -= ulFlushLength;
9829                                                 }
9830                                             }
9831
9832                                             liCurrentOffset.QuadPart = pEntry->FileOffset.QuadPart + pEntry->Size;
9833
9834                                             ulProcessCount++;
9835                                             le = le->Flink;
9836                                         }
9837                                     }
9838                                     else
9839                                     {
9840                                         if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9841                                                                   NULL,
9842                                                                   0,
9843                                                                   FALSE))
9844                                         {
9845
9846                                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9847                                                           AFS_TRACE_LEVEL_WARNING,
9848                                                           "AFSPerformObjectInvalidation [4] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9849                                                           ObjectInfo->FileId.Cell,
9850                                                           ObjectInfo->FileId.Volume,
9851                                                           ObjectInfo->FileId.Vnode,
9852                                                           ObjectInfo->FileId.Unique));
9853
9854                                             bPurgeOnClose = TRUE;
9855                                         }
9856                                         else
9857                                         {
9858
9859                                             bCleanExtents = TRUE;
9860                                         }
9861                                     }
9862
9863                                     if ( bPurgeOnClose)
9864                                     {
9865
9866                                         SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9867                                     }
9868                                 }
9869                             }
9870                             __except( EXCEPTION_EXECUTE_HANDLER)
9871                             {
9872
9873                                 ntStatus = GetExceptionCode();
9874
9875                                 AFSDbgTrace(( 0,
9876                                               0,
9877                                               "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
9878                                               ObjectInfo->FileId.Cell,
9879                                               ObjectInfo->FileId.Volume,
9880                                               ObjectInfo->FileId.Vnode,
9881                                               ObjectInfo->FileId.Unique,
9882                                               ntStatus));
9883                             }
9884
9885                             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9886                                           AFS_TRACE_LEVEL_VERBOSE,
9887                                           "AFSPerformObjectInvalidation Releasing Fcb SectionObject lock %p EXCL %08lX\n",
9888                                           &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9889                                           PsGetCurrentThread()));
9890
9891                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
9892                         }
9893                     }
9894
9895                     if ( bExtentsLocked)
9896                     {
9897
9898                         AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9899                     }
9900
9901                     if ( bLocked)
9902                     {
9903
9904                         AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9905                     }
9906
9907                     if ( bCleanExtents)
9908                     {
9909
9910                         AFSReleaseCleanExtents( ObjectInfo->Fcb,
9911                                                 NULL);
9912                     }
9913                 }
9914
9915                 break;
9916             }
9917         }
9918
9919         //
9920         // Destroy the reference passed in by the caller to AFSInvalidateObject
9921         // or AFSQueueInvalidateObject
9922         //
9923
9924         lCount = AFSObjectInfoDecrement( ObjectInfo,
9925                                          AFS_OBJECT_REFERENCE_INVALIDATION);
9926
9927         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
9928                       AFS_TRACE_LEVEL_VERBOSE,
9929                       "AFSPerformObjectInvalidation Decrement count on object %p Cnt %d\n",
9930                       ObjectInfo,
9931                       lCount));
9932     }
9933
9934     return ntStatus;
9935 }