e6533975ec74fef652c5a0f4346e4a86790fad60
[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&