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