5bf3ef2c991e9c06a94fe4bf25b97b8d0a61f77b
[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, 2012, 2013 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, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
16  *   nor the names of their contributors may be used to endorse or promote
17  *   products derived from this software without specific prior written
18  *   permission from Kernel Drivers, LLC and Your File System, Inc.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
24  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 //
34 // File: AFSGeneric.cpp
35 //
36
37 #include "AFSCommon.h"
38
39 //
40 // Function: AFSExceptionFilter
41 //
42 // Description:
43 //
44 //      This function is the exception handler
45 //
46 // Return:
47 //
48 //      A status is returned for the function
49 //
50
51 ULONG
52 AFSExceptionFilter( IN CHAR *FunctionString,
53                     IN ULONG Code,
54                     IN PEXCEPTION_POINTERS ExceptPtrs)
55 {
56
57     UNREFERENCED_PARAMETER(Code);
58     PEXCEPTION_RECORD ExceptRec;
59     PCONTEXT Context;
60
61     __try
62     {
63
64         ExceptRec = ExceptPtrs->ExceptionRecord;
65
66         Context = ExceptPtrs->ContextRecord;
67
68         AFSDbgTrace(( 0,
69                       0,
70                       "AFSExceptionFilter (Library) - EXR %p CXR %p Function %s Code %08lX Address %p Routine %p\n",
71                       ExceptRec,
72                       Context,
73                       FunctionString,
74                       ExceptRec->ExceptionCode,
75                       ExceptRec->ExceptionAddress,
76                       (void *)AFSExceptionFilter));
77
78         DbgPrint("**** Exception Caught in AFS Redirector Library ****\n");
79
80         DbgPrint("\n\nPerform the following WnDbg Cmds:\n");
81         DbgPrint("\n\t.exr %p ;  .cxr %p\n\n", ExceptRec, Context);
82
83         DbgPrint("**** Exception Complete from AFS Redirector Library ****\n");
84
85         if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION))
86         {
87
88             KeBugCheck( (ULONG)-2);
89         }
90         else
91         {
92
93             AFSBreakPoint();
94         }
95     }
96     __except( EXCEPTION_EXECUTE_HANDLER)
97     {
98
99         NOTHING;
100     }
101
102     return EXCEPTION_EXECUTE_HANDLER;
103 }
104
105 //
106 // Function: AFSLibExAllocatePoolWithTag()
107 //
108 // Purpose: Allocate Pool Memory.  If BugCheck Exception flag
109 //          is configured on, then bugcheck the system if
110 //          a memory allocation fails.  The routine should be
111 //          used for all memory allocations that are to be freed
112 //          when the library is unloaded.  Memory allocations that
113 //          are to survive library unload and reload should be
114 //          performed using AFSExAllocatePoolWithTag() which is
115 //          provided by the AFS Framework.
116 //
117 // Parameters:
118 //                POOL_TYPE PoolType - Paged or NonPaged
119 //                SIZE_T NumberOfBytes - requested allocation size
120 //                ULONG  Tag - Pool Allocation Tag to be applied for tracking
121 //
122 // Return:
123 //                void * - the memory allocation
124 //
125
126 void *
127 AFSLibExAllocatePoolWithTag( IN POOL_TYPE  PoolType,
128                              IN SIZE_T  NumberOfBytes,
129                              IN ULONG  Tag)
130 {
131
132     void *pBuffer = NULL;
133
134     pBuffer = ExAllocatePoolWithTag( PoolType,
135                                      NumberOfBytes,
136                                      Tag);
137
138     if( pBuffer == NULL)
139     {
140
141         if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION))
142         {
143
144             KeBugCheck( (ULONG)-2);
145         }
146         else
147         {
148
149             AFSDbgTrace(( 0,
150                           0,
151                           "AFSLibExAllocatePoolWithTag failure Type %08lX Size %08lX Tag %08lX %08lX\n",
152                           PoolType,
153                           NumberOfBytes,
154                           Tag,
155                           PsGetCurrentThread()));
156
157             AFSBreakPoint();
158         }
159     }
160
161     return pBuffer;
162 }
163
164 //
165 // Function: AFSAcquireExcl()
166 //
167 // Purpose: Called to acquire a resource exclusive with optional wait
168 //
169 // Parameters:
170 //                PERESOURCE Resource - Resource to acquire
171 //                BOOLEAN Wait - Whether to block
172 //
173 // Return:
174 //                BOOLEAN - Whether the mask was acquired
175 //
176
177 BOOLEAN
178 AFSAcquireExcl( IN PERESOURCE Resource,
179                 IN BOOLEAN wait)
180 {
181
182     BOOLEAN bStatus = FALSE;
183
184     //
185     // Normal kernel APCs must be disabled before calling
186     // ExAcquireResourceExclusiveLite. Otherwise a bugcheck occurs.
187     //
188
189     KeEnterCriticalRegion();
190
191     bStatus = ExAcquireResourceExclusiveLite( Resource,
192                                               wait);
193
194     if( !bStatus)
195     {
196
197         KeLeaveCriticalRegion();
198     }
199
200     return bStatus;
201 }
202
203 BOOLEAN
204 AFSAcquireSharedStarveExclusive( IN PERESOURCE Resource,
205                                  IN BOOLEAN Wait)
206 {
207
208     BOOLEAN bStatus = FALSE;
209
210     KeEnterCriticalRegion();
211
212     bStatus = ExAcquireSharedStarveExclusive( Resource,
213                                               Wait);
214
215     if( !bStatus)
216     {
217
218         KeLeaveCriticalRegion();
219     }
220
221     return bStatus;
222 }
223
224 //
225 // Function: AFSAcquireShared()
226 //
227 // Purpose: Called to acquire a resource shared with optional wait
228 //
229 // Parameters:
230 //                PERESOURCE Resource - Resource to acquire
231 //                BOOLEAN Wait - Whether to block
232 //
233 // Return:
234 //                BOOLEAN - Whether the mask was acquired
235 //
236
237 BOOLEAN
238 AFSAcquireShared( IN PERESOURCE Resource,
239                   IN BOOLEAN wait)
240 {
241
242     BOOLEAN bStatus = FALSE;
243
244     KeEnterCriticalRegion();
245
246     bStatus = ExAcquireResourceSharedLite( Resource,
247                                            wait);
248
249     if( !bStatus)
250     {
251
252         KeLeaveCriticalRegion();
253     }
254
255     return bStatus;
256 }
257
258 //
259 // Function: AFSReleaseResource()
260 //
261 // Purpose: Called to release a resource
262 //
263 // Parameters:
264 //                PERESOURCE Resource - Resource to release
265 //
266 // Return:
267 //                None
268 //
269
270 void
271 AFSReleaseResource( IN PERESOURCE Resource)
272 {
273
274     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
275                   AFS_TRACE_LEVEL_VERBOSE,
276                   "AFSReleaseResource Releasing lock %p Thread %08lX\n",
277                   Resource,
278                   PsGetCurrentThread()));
279
280     ExReleaseResourceLite( Resource);
281
282     KeLeaveCriticalRegion();
283
284     return;
285 }
286
287 void
288 AFSConvertToShared( IN PERESOURCE Resource)
289 {
290
291     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
292                   AFS_TRACE_LEVEL_VERBOSE,
293                   "AFSConvertToShared Converting lock %p Thread %08lX\n",
294                   Resource,
295                   PsGetCurrentThread()));
296
297     ExConvertExclusiveToSharedLite( Resource);
298
299     return;
300 }
301
302 //
303 // Function: AFSCompleteRequest
304 //
305 // Description:
306 //
307 //      This function completes irps
308 //
309 // Return:
310 //
311 //      A status is returned for the function
312 //
313
314 void
315 AFSCompleteRequest( IN PIRP Irp,
316                     IN ULONG Status)
317 {
318
319     Irp->IoStatus.Status = Status;
320
321     IoCompleteRequest( Irp,
322                        IO_NO_INCREMENT);
323
324     return;
325 }
326
327 //
328 // Function: AFSGenerateCRC
329 //
330 // Description:
331 //
332 //      Given a device and filename this function generates a CRC
333 //
334 // Return:
335 //
336 //      A status is returned for the function
337 //
338
339 ULONG
340 AFSGenerateCRC( IN PUNICODE_STRING FileName,
341                 IN BOOLEAN UpperCaseName)
342 {
343
344     ULONG ulCRC = 0;
345     NTSTATUS ntStatus = STATUS_SUCCESS;
346
347     ntStatus = RtlHashUnicodeString( FileName,
348                                      UpperCaseName,
349                                      HASH_STRING_ALGORITHM_DEFAULT,
350                                      &ulCRC);
351
352     if( !NT_SUCCESS( ntStatus))
353     {
354         ulCRC = 0;
355     }
356
357     return ulCRC;
358 }
359
360 void *
361 AFSLockSystemBuffer( IN PIRP Irp,
362                      IN ULONG Length)
363 {
364
365     void *pAddress = NULL;
366
367     if( Irp->MdlAddress != NULL)
368     {
369
370         pAddress = MmGetSystemAddressForMdlSafe( Irp->MdlAddress,
371                                                  NormalPagePriority);
372     }
373     else if( Irp->AssociatedIrp.SystemBuffer != NULL)
374     {
375
376         pAddress = Irp->AssociatedIrp.SystemBuffer;
377     }
378     else if( Irp->UserBuffer != NULL)
379     {
380
381         Irp->MdlAddress = IoAllocateMdl( Irp->UserBuffer,
382                                          Length,
383                                          FALSE,
384                                          FALSE,
385                                          Irp);
386
387         if( Irp->MdlAddress != NULL)
388         {
389
390             //
391             //  Lock the new Mdl in memory.
392             //
393
394             __try
395             {
396                 PIO_STACK_LOCATION pIoStack;
397                 pIoStack = IoGetCurrentIrpStackLocation( Irp);
398
399
400                 MmProbeAndLockPages( Irp->MdlAddress, KernelMode,
401                                      (pIoStack->MajorFunction == IRP_MJ_READ) ? IoWriteAccess : IoReadAccess);
402
403                 pAddress = MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority );
404
405             }
406             __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
407             {
408
409                 AFSDumpTraceFilesFnc();
410
411                 IoFreeMdl( Irp->MdlAddress );
412                 Irp->MdlAddress = NULL;
413                 pAddress = NULL;
414             }
415         }
416     }
417
418     return pAddress;
419 }
420
421 void *
422 AFSLockUserBuffer( IN void *UserBuffer,
423                    IN ULONG BufferLength,
424                    OUT MDL ** Mdl)
425 {
426
427     NTSTATUS ntStatus = STATUS_SUCCESS;
428     void *pAddress = NULL;
429     MDL *pMdl = NULL;
430
431     __Enter
432     {
433
434         pMdl = IoAllocateMdl( UserBuffer,
435                               BufferLength,
436                               FALSE,
437                               FALSE,
438                               NULL);
439
440             if( pMdl == NULL)
441             {
442
443                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
444             }
445
446         //
447         //  Lock the new Mdl in memory.
448         //
449
450         __try
451         {
452
453             MmProbeAndLockPages( pMdl,
454                                  KernelMode,
455                                  IoWriteAccess);
456
457             pAddress = MmGetSystemAddressForMdlSafe( pMdl,
458                                                      NormalPagePriority);
459         }
460         __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
461         {
462
463             AFSDumpTraceFilesFnc();
464
465             IoFreeMdl( pMdl);
466             pMdl = NULL;
467             pAddress = NULL;
468         }
469
470         if( pMdl != NULL)
471         {
472
473             *Mdl = pMdl;
474         }
475
476 try_exit:
477
478         NOTHING;
479     }
480
481     return pAddress;
482 }
483
484 void *
485 AFSMapToService( IN PIRP Irp,
486                  IN ULONG ByteCount)
487 {
488
489     NTSTATUS ntStatus = STATUS_SUCCESS;
490     void *pMappedBuffer = NULL;
491     AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
492     KAPC stApcState;
493
494     __Enter
495     {
496
497         if( pDevExt->Specific.Control.ServiceProcess == NULL)
498         {
499
500             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
501         }
502
503         if( Irp->MdlAddress == NULL)
504         {
505
506             if( AFSLockSystemBuffer( Irp,
507                                      ByteCount) == NULL)
508             {
509
510                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
511             }
512         }
513
514         //
515         // Attach to the service process for mapping
516         //
517
518         KeStackAttachProcess( pDevExt->Specific.Control.ServiceProcess,
519                               (PRKAPC_STATE)&stApcState);
520
521         pMappedBuffer = MmMapLockedPagesSpecifyCache( Irp->MdlAddress,
522                                                       UserMode,
523                                                       MmCached,
524                                                       NULL,
525                                                       FALSE,
526                                                       NormalPagePriority);
527
528         KeUnstackDetachProcess( (PRKAPC_STATE)&stApcState);
529
530 try_exit:
531
532         NOTHING;
533     }
534
535     return pMappedBuffer;
536 }
537
538 NTSTATUS
539 AFSUnmapServiceMappedBuffer( IN void *MappedBuffer,
540                              IN PMDL Mdl)
541 {
542
543     NTSTATUS ntStatus = STATUS_SUCCESS;
544     AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
545     KAPC stApcState;
546
547     __Enter
548     {
549
550         if( pDevExt->Specific.Control.ServiceProcess == NULL)
551         {
552
553             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
554         }
555
556         if( Mdl != NULL)
557         {
558
559             //
560             // Attach to the service process for mapping
561             //
562
563             KeStackAttachProcess( pDevExt->Specific.Control.ServiceProcess,
564                                   (PRKAPC_STATE)&stApcState);
565
566             MmUnmapLockedPages( MappedBuffer,
567                                 Mdl);
568
569             KeUnstackDetachProcess( (PRKAPC_STATE)&stApcState);
570         }
571
572 try_exit:
573
574         NOTHING;
575     }
576
577     return ntStatus;
578 }
579
580 NTSTATUS
581 AFSInitializeLibraryDevice()
582 {
583
584     NTSTATUS ntStatus = STATUS_SUCCESS;
585     AFSDeviceExt *pDeviceExt = NULL;
586
587     __Enter
588     {
589
590         pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
591
592         //
593         // The PIOCtl file name
594         //
595
596         RtlInitUnicodeString( &AFSPIOCtlName,
597                               AFS_PIOCTL_FILE_INTERFACE_NAME);
598
599         //
600         // And the global root share name
601         //
602
603         RtlInitUnicodeString( &AFSGlobalRootName,
604                               AFS_GLOBAL_ROOT_SHARE_NAME);
605
606     }
607
608     return ntStatus;
609 }
610
611 NTSTATUS
612 AFSRemoveLibraryDevice()
613 {
614
615     NTSTATUS ntStatus = STATUS_SUCCESS;
616
617     __Enter
618     {
619
620     }
621
622     return ntStatus;
623 }
624
625 NTSTATUS
626 AFSDefaultDispatch( IN PDEVICE_OBJECT DeviceObject,
627                     IN PIRP Irp)
628 {
629
630     UNREFERENCED_PARAMETER(DeviceObject);
631     NTSTATUS            ntStatus = STATUS_INVALID_DEVICE_REQUEST;
632
633     AFSCompleteRequest( Irp,
634                         ntStatus);
635
636     return ntStatus;
637 }
638
639 NTSTATUS
640 AFSInitializeGlobalDirectoryEntries()
641 {
642
643     NTSTATUS ntStatus = STATUS_SUCCESS;
644     AFSDirectoryCB *pDirNode = NULL;
645     ULONG ulEntryLength = 0;
646     AFSObjectInfoCB *pObjectInfoCB = NULL;
647     AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
648     LONG lCount;
649
650     __Enter
651     {
652
653         //
654         // Initialize the global . entry
655         //
656
657         pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
658                                                0);
659
660         if( pObjectInfoCB == NULL)
661         {
662
663             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
664                           AFS_TRACE_LEVEL_ERROR,
665                           "AFSInitializeGlobalDirectory AFSAllocateObjectInfo failure %08lX\n",
666                           ntStatus));
667
668             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
669         }
670
671         lCount = AFSObjectInfoIncrement( pObjectInfoCB,
672                                          AFS_OBJECT_REFERENCE_GLOBAL);
673
674         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
675                       AFS_TRACE_LEVEL_VERBOSE,
676                       "AFSInitializeGlobalDirectoryEntries Increment count on object %p Cnt %d\n",
677                       pObjectInfoCB,
678                       lCount));
679
680         ntStatus = STATUS_SUCCESS;
681
682         ulEntryLength = sizeof( AFSDirectoryCB) +
683                                      sizeof( WCHAR);
684
685         pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
686                                                                   ulEntryLength,
687                                                                   AFS_DIR_ENTRY_TAG);
688
689         if( pDirNode == NULL)
690         {
691
692             lCount = AFSObjectInfoDecrement( pObjectInfoCB,
693                                              AFS_OBJECT_REFERENCE_GLOBAL);
694
695             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
696                           AFS_TRACE_LEVEL_VERBOSE,
697                           "AFSInitializeGlobalDirectoryEntries Decrement count on object %p Cnt %d\n",
698                           pObjectInfoCB,
699                           lCount));
700
701             if ( lCount == 0)
702             {
703
704                 AFSDeleteObjectInfo( &pObjectInfoCB);
705             }
706
707             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
708                           AFS_TRACE_LEVEL_ERROR,
709                           "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_TAG allocation failure\n"));
710
711             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
712         }
713
714         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
715                       AFS_TRACE_LEVEL_VERBOSE,
716                       "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_TAG allocated %p\n",
717                       pDirNode));
718
719         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
720                                                                                    sizeof( AFSNonPagedDirectoryCB),
721                                                                                    AFS_DIR_ENTRY_NP_TAG);
722
723         if( pNonPagedDirEntry == NULL)
724         {
725
726             ExFreePool( pDirNode);
727
728             lCount = AFSObjectInfoDecrement( pObjectInfoCB,
729                                              AFS_OBJECT_REFERENCE_GLOBAL);
730
731             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
732                           AFS_TRACE_LEVEL_VERBOSE,
733                           "AFSInitializeGlobalDirectoryEntries Decrement count on object %p Cnt %d\n",
734                           pObjectInfoCB,
735                           lCount));
736
737             if ( lCount == 0)
738             {
739
740                 AFSDeleteObjectInfo( &pObjectInfoCB);
741             }
742
743             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
744                           AFS_TRACE_LEVEL_ERROR,
745                           "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_NP_TAG allocation failure\n"));
746
747             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
748         }
749
750         RtlZeroMemory( pDirNode,
751                        ulEntryLength);
752
753         RtlZeroMemory( pNonPagedDirEntry,
754                        sizeof( AFSNonPagedDirectoryCB));
755
756         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
757
758         pDirNode->NonPaged = pNonPagedDirEntry;
759
760         pDirNode->ObjectInformation = pObjectInfoCB;
761
762         //
763         // Set valid entry
764         //
765
766         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE | AFS_DIR_ENTRY_FAKE | AFS_DIR_ENTRY_VALID);
767
768         pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_DOT_INDEX;
769
770         //
771         // Setup the names in the entry
772         //
773
774         pDirNode->NameInformation.FileName.Length = sizeof( WCHAR);
775
776         pDirNode->NameInformation.FileName.MaximumLength = sizeof( WCHAR);
777
778         pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
779
780         pDirNode->NameInformation.FileName.Buffer[ 0] = L'.';
781
782         //
783         // Populate the rest of the data
784         //
785
786         pObjectInfoCB->FileType = AFS_FILE_TYPE_DIRECTORY;
787
788         pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
789
790         AFSGlobalDotDirEntry = pDirNode;
791
792         //
793         // Now the .. entry
794         //
795
796         pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
797                                                0);
798
799         if( pObjectInfoCB == NULL)
800         {
801
802             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
803                           AFS_TRACE_LEVEL_ERROR,
804                           "AFSInitializeGlobalDirectory AFSAllocateObjectInfo (2) failure %08lX\n",
805                           ntStatus));
806
807             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
808         }
809
810         lCount = AFSObjectInfoIncrement( pObjectInfoCB,
811                                          AFS_OBJECT_REFERENCE_GLOBAL);
812
813         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
814                       AFS_TRACE_LEVEL_VERBOSE,
815                       "AFSInitializeGlobalDirectoryEntries Increment count on object %p Cnt %d\n",
816                       pObjectInfoCB,
817                       lCount));
818
819         ntStatus = STATUS_SUCCESS;
820
821         ulEntryLength = sizeof( AFSDirectoryCB) +
822                                      ( 2 * sizeof( WCHAR));
823
824         pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
825                                                                   ulEntryLength,
826                                                                   AFS_DIR_ENTRY_TAG);
827
828         if( pDirNode == NULL)
829         {
830
831             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
832                           AFS_TRACE_LEVEL_ERROR,
833                           "AFSInitializeGlobalDirectoryEntries AFS_DIR_ENTRY_TAG allocation failure\n"));
834
835             lCount = AFSObjectInfoDecrement( pObjectInfoCB,
836                                              AFS_OBJECT_REFERENCE_GLOBAL);
837
838             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
839                           AFS_TRACE_LEVEL_VERBOSE,
840                           "AFSInitializeGlobalDirectoryEntries Decrement count on object %p Cnt %d\n",
841                           pObjectInfoCB,
842                           lCount));
843
844             if ( lCount == 0)
845             {
846
847                 AFSDeleteObjectInfo( &pObjectInfoCB);
848             }
849
850             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
851         }
852
853         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
854                       AFS_TRACE_LEVEL_VERBOSE,
855                       "AFSInitializeGlobalDirectoryEntries AFS_DIR_ENTRY_TAG allocated %p\n",
856                       pDirNode));
857
858         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
859                                                                                    sizeof( AFSNonPagedDirectoryCB),
860                                                                                    AFS_DIR_ENTRY_NP_TAG);
861
862         if( pNonPagedDirEntry == NULL)
863         {
864
865             ExFreePool( pDirNode);
866
867             lCount = AFSObjectInfoDecrement( pObjectInfoCB,
868                                              AFS_OBJECT_REFERENCE_GLOBAL);
869
870             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
871                           AFS_TRACE_LEVEL_VERBOSE,
872                           "AFSInitializeGlobalDirectoryEntries Decrement count on object %p Cnt %d\n",
873                           pObjectInfoCB,
874                           lCount));
875
876             if ( lCount == 0)
877             {
878
879                 AFSDeleteObjectInfo( &pObjectInfoCB);
880             }
881
882             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
883         }
884
885         RtlZeroMemory( pDirNode,
886                        ulEntryLength);
887
888         RtlZeroMemory( pNonPagedDirEntry,
889                        sizeof( AFSNonPagedDirectoryCB));
890
891         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
892
893         pDirNode->NonPaged = pNonPagedDirEntry;
894
895         pDirNode->ObjectInformation = pObjectInfoCB;
896
897         //
898         // Set valid entry
899         //
900
901         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE | AFS_DIR_ENTRY_FAKE | AFS_DIR_ENTRY_VALID);
902
903         pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX;
904
905         //
906         // Setup the names in the entry
907         //
908
909         pDirNode->NameInformation.FileName.Length = 2 * sizeof( WCHAR);
910
911         pDirNode->NameInformation.FileName.MaximumLength = 2 * sizeof( WCHAR);
912
913         pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
914
915         pDirNode->NameInformation.FileName.Buffer[ 0] = L'.';
916
917         pDirNode->NameInformation.FileName.Buffer[ 1] = L'.';
918
919         //
920         // Populate the rest of the data
921         //
922
923         pObjectInfoCB->FileType = AFS_FILE_TYPE_DIRECTORY;
924
925         pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
926
927         AFSGlobalDotDotDirEntry = pDirNode;
928
929 try_exit:
930
931         if( !NT_SUCCESS( ntStatus))
932         {
933
934             if( AFSGlobalDotDirEntry != NULL)
935             {
936
937                 lCount = AFSObjectInfoDecrement( AFSGlobalDotDirEntry->ObjectInformation,
938                                                  AFS_OBJECT_REFERENCE_GLOBAL);
939
940                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
941                               AFS_TRACE_LEVEL_VERBOSE,
942                               "AFSInitializeGlobalDirectoryEntries Decrement count on object %p Cnt %d\n",
943                               AFSGlobalDotDirEntry->ObjectInformation,
944                               lCount));
945
946                 if ( lCount == 0)
947                 {
948
949                     AFSDeleteObjectInfo( &AFSGlobalDotDirEntry->ObjectInformation);
950                 }
951
952                 ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
953
954                 ExFreePool( AFSGlobalDotDirEntry->NonPaged);
955
956                 ExFreePool( AFSGlobalDotDirEntry);
957
958                 AFSGlobalDotDirEntry = NULL;
959             }
960
961             if( AFSGlobalDotDotDirEntry != NULL)
962             {
963
964                 lCount = AFSObjectInfoDecrement( AFSGlobalDotDotDirEntry->ObjectInformation,
965                                                  AFS_OBJECT_REFERENCE_GLOBAL);
966
967                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
968                               AFS_TRACE_LEVEL_VERBOSE,
969                               "AFSInitializeGlobalDirectoryEntries Decrement count on object %p Cnt %d\n",
970                               AFSGlobalDotDotDirEntry->ObjectInformation,
971                               lCount));
972
973                 if ( lCount == 0)
974                 {
975
976                     AFSDeleteObjectInfo( &AFSGlobalDotDotDirEntry->ObjectInformation);
977                 }
978
979                 ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
980
981                 ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
982
983                 ExFreePool( AFSGlobalDotDotDirEntry);
984
985                 AFSGlobalDotDotDirEntry = NULL;
986             }
987         }
988     }
989
990     return ntStatus;
991 }
992
993 AFSDirectoryCB *
994 AFSInitDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
995                  IN PUNICODE_STRING FileName,
996                  IN PUNICODE_STRING TargetName,
997                  IN AFSDirEnumEntry *DirEnumEntry,
998                  IN ULONG FileIndex)
999 {
1000
1001     AFSDirectoryCB *pDirNode = NULL;
1002     NTSTATUS ntStatus = STATUS_SUCCESS;
1003     ULONG ulEntryLength = 0;
1004     AFSObjectInfoCB *pObjectInfoCB = NULL;
1005     ULONGLONG ullIndex = 0;
1006     AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
1007     LONG lCount;
1008
1009     __Enter
1010     {
1011
1012         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1013                       AFS_TRACE_LEVEL_VERBOSE,
1014                       "AFSInitDirEntry Initializing entry %wZ parent FID %08lX-%08lX-%08lX-%08lX\n",
1015                       FileName,
1016                       ParentObjectInfo->FileId.Cell,
1017                       ParentObjectInfo->FileId.Volume,
1018                       ParentObjectInfo->FileId.Vnode,
1019                       ParentObjectInfo->FileId.Unique));
1020
1021         //
1022         // First thing is to locate/create our object information block
1023         // for this entry
1024         //
1025
1026         AFSAcquireExcl( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
1027                         TRUE);
1028
1029         ullIndex = AFSCreateLowIndex( &DirEnumEntry->FileId);
1030
1031         ntStatus = AFSLocateHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
1032                                        ullIndex,
1033                                        (AFSBTreeEntry **)&pObjectInfoCB);
1034
1035         if( !NT_SUCCESS( ntStatus))
1036         {
1037
1038             //
1039             // Allocate our object info cb
1040             //
1041
1042             pObjectInfoCB = AFSAllocateObjectInfo( ParentObjectInfo,
1043                                                    ullIndex);
1044
1045             if( pObjectInfoCB == NULL)
1046             {
1047
1048                 AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
1049
1050                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1051             }
1052
1053             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1054                           AFS_TRACE_LEVEL_VERBOSE,
1055                           "AFSInitDirEntry initialized object %p Parent Object %p for %wZ\n",
1056                           pObjectInfoCB,
1057                           ParentObjectInfo,
1058                           FileName));
1059
1060             //
1061             // If we allocated the object information cb then set the information
1062             //
1063
1064             pObjectInfoCB->FileId = DirEnumEntry->FileId;
1065
1066             pObjectInfoCB->TargetFileId = DirEnumEntry->TargetFileId;
1067
1068             pObjectInfoCB->FileType = DirEnumEntry->FileType;
1069
1070             pObjectInfoCB->FileAttributes = DirEnumEntry->FileAttributes;
1071
1072             if( pObjectInfoCB->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1073                 pObjectInfoCB->FileType == AFS_FILE_TYPE_DFSLINK)
1074             {
1075
1076                 pObjectInfoCB->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1077             }
1078
1079             if (pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK)
1080             {
1081
1082                 if ( pObjectInfoCB->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1083                 {
1084
1085                     pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1086                 }
1087                 else
1088                 {
1089
1090                     pObjectInfoCB->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1091                 }
1092             }
1093
1094             //
1095             // Check for the case where we have a filetype of SymLink but both the TargetFid and the
1096             // TargetName are empty. In this case set the filetype to zero so we evaluate it later in
1097             // the code
1098             //
1099
1100             if( pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK &&
1101                 pObjectInfoCB->TargetFileId.Vnode == 0 &&
1102                 pObjectInfoCB->TargetFileId.Unique == 0 &&
1103                 (TargetName == NULL || TargetName->Length == 0))
1104             {
1105
1106                 //
1107                 // This will ensure we perform a validation on the node
1108                 //
1109
1110                 pObjectInfoCB->FileType = AFS_FILE_TYPE_UNKNOWN;
1111             }
1112
1113             if( pObjectInfoCB->FileType == AFS_FILE_TYPE_UNKNOWN)
1114             {
1115
1116                 SetFlag( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
1117             }
1118
1119             SetFlag( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
1120         }
1121
1122         if ( BooleanFlagOn( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY))
1123         {
1124
1125             pObjectInfoCB->CreationTime = DirEnumEntry->CreationTime;
1126
1127             pObjectInfoCB->LastAccessTime = DirEnumEntry->LastAccessTime;
1128
1129             pObjectInfoCB->LastWriteTime = DirEnumEntry->LastWriteTime;
1130
1131             pObjectInfoCB->ChangeTime = DirEnumEntry->ChangeTime;
1132
1133             pObjectInfoCB->EndOfFile = DirEnumEntry->EndOfFile;
1134
1135             pObjectInfoCB->AllocationSize = DirEnumEntry->AllocationSize;
1136
1137             pObjectInfoCB->EaSize = DirEnumEntry->EaSize;
1138
1139             pObjectInfoCB->Links = DirEnumEntry->Links;
1140
1141             pObjectInfoCB->Expiration = DirEnumEntry->Expiration;
1142
1143             pObjectInfoCB->DataVersion = DirEnumEntry->DataVersion;
1144
1145             ClearFlag( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_VERIFY);
1146         }
1147
1148         //
1149         // This reference count is either stored into the return DirectoryCB
1150         // or released before function exit.
1151         //
1152
1153         lCount = AFSObjectInfoIncrement( pObjectInfoCB,
1154                                          AFS_OBJECT_REFERENCE_DIRENTRY);
1155
1156         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1157                       AFS_TRACE_LEVEL_VERBOSE,
1158                       "AFSInitDirEntry Increment count on object %p Cnt %d\n",
1159                       pObjectInfoCB,
1160                       lCount));
1161
1162         KeQueryTickCount( &pObjectInfoCB->LastAccessCount);
1163
1164         AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
1165
1166         ntStatus = STATUS_SUCCESS;
1167
1168         ulEntryLength = sizeof( AFSDirectoryCB) +
1169                                      FileName->Length;
1170
1171         if( TargetName != NULL)
1172         {
1173
1174             ulEntryLength += TargetName->Length;
1175         }
1176
1177         pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
1178                                                                ulEntryLength,
1179                                                                AFS_DIR_ENTRY_TAG);
1180
1181         if( pDirNode == NULL)
1182         {
1183
1184             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1185         }
1186
1187         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1188                       AFS_TRACE_LEVEL_VERBOSE,
1189                       "AFSInitDirEntry AFS_DIR_ENTRY_TAG allocated %p\n",
1190                       pDirNode));
1191
1192         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
1193                                                                                 sizeof( AFSNonPagedDirectoryCB),
1194                                                                                 AFS_DIR_ENTRY_NP_TAG);
1195
1196         if( pNonPagedDirEntry == NULL)
1197         {
1198
1199             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1200         }
1201
1202         RtlZeroMemory( pDirNode,
1203                        ulEntryLength);
1204
1205         RtlZeroMemory( pNonPagedDirEntry,
1206                        sizeof( AFSNonPagedDirectoryCB));
1207
1208         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
1209
1210         pDirNode->NonPaged = pNonPagedDirEntry;
1211
1212         pDirNode->ObjectInformation = pObjectInfoCB;
1213
1214         //
1215         // Set valid entry and NOT_IN_PARENT flag
1216         //
1217
1218         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1219
1220         pDirNode->FileIndex = FileIndex;
1221
1222         //
1223         // Setup the names in the entry
1224         //
1225
1226         if( FileName->Length > 0)
1227         {
1228
1229             pDirNode->NameInformation.FileName.Length = FileName->Length;
1230
1231             pDirNode->NameInformation.FileName.MaximumLength = FileName->Length;
1232
1233             pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
1234
1235             RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
1236                            FileName->Buffer,
1237                            pDirNode->NameInformation.FileName.Length);
1238
1239             //
1240             // Create a CRC for the file
1241             //
1242
1243             pDirNode->CaseSensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1244                                                                          FALSE);
1245
1246             pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1247                                                                            TRUE);
1248         }
1249
1250         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1251                       AFS_TRACE_LEVEL_VERBOSE,
1252                       "AFSInitDirEntry Initialized DE %p for %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1253                       pDirNode,
1254                       FileName,
1255                       ParentObjectInfo->FileId.Cell,
1256                       ParentObjectInfo->FileId.Volume,
1257                       ParentObjectInfo->FileId.Vnode,
1258                       ParentObjectInfo->FileId.Unique));
1259
1260         if( TargetName != NULL &&
1261             TargetName->Length > 0)
1262         {
1263
1264             pDirNode->NameInformation.TargetName.Length = TargetName->Length;
1265
1266             pDirNode->NameInformation.TargetName.MaximumLength = pDirNode->NameInformation.TargetName.Length;
1267
1268             pDirNode->NameInformation.TargetName.Buffer = (WCHAR *)((char *)pDirNode +
1269                                                                             sizeof( AFSDirectoryCB) +
1270                                                                             pDirNode->NameInformation.FileName.Length);
1271
1272             RtlCopyMemory( pDirNode->NameInformation.TargetName.Buffer,
1273                            TargetName->Buffer,
1274                            pDirNode->NameInformation.TargetName.Length);
1275         }
1276
1277
1278 try_exit:
1279
1280         if( !NT_SUCCESS( ntStatus))
1281         {
1282
1283             if( pNonPagedDirEntry != NULL)
1284             {
1285
1286                 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
1287
1288                 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
1289             }
1290
1291             if( pDirNode != NULL)
1292             {
1293
1294                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1295                               AFS_TRACE_LEVEL_VERBOSE,
1296                               "AFSInitDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
1297                               pDirNode));
1298
1299                 AFSExFreePoolWithTag( pDirNode, AFS_DIR_ENTRY_TAG);
1300
1301                 pDirNode = NULL;
1302             }
1303
1304             //
1305             // Dereference our object info block if we have one
1306             //
1307
1308             if( pObjectInfoCB != NULL)
1309             {
1310
1311                 AFSAcquireShared( pObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock,
1312                                   TRUE);
1313
1314                 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
1315                                                  AFS_OBJECT_REFERENCE_DIRENTRY);
1316
1317                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1318                               AFS_TRACE_LEVEL_VERBOSE,
1319                               "AFSInitDirEntry Decrement count on object %p Cnt %d\n",
1320                               pObjectInfoCB,
1321                               lCount));
1322
1323                 AFSReleaseResource( pObjectInfoCB->VolumeCB->ObjectInfoTree.TreeLock);
1324             }
1325         }
1326     }
1327
1328     return pDirNode;
1329 }
1330
1331 BOOLEAN
1332 AFSCheckForReadOnlyAccess( IN ACCESS_MASK DesiredAccess,
1333                            IN BOOLEAN DirectoryEntry)
1334 {
1335
1336     BOOLEAN bReturn = TRUE;
1337     ACCESS_MASK stAccessMask = 0;
1338
1339     //
1340     // Get rid of anything we don't know about
1341     //
1342
1343     DesiredAccess = (DesiredAccess   &
1344                           ( DELETE |
1345                             READ_CONTROL |
1346                             WRITE_OWNER |
1347                             WRITE_DAC |
1348                             SYNCHRONIZE |
1349                             ACCESS_SYSTEM_SECURITY |
1350                             FILE_WRITE_DATA |
1351                             FILE_READ_EA |
1352                             FILE_WRITE_EA |
1353                             FILE_READ_ATTRIBUTES |
1354                             FILE_WRITE_ATTRIBUTES |
1355                             FILE_LIST_DIRECTORY |
1356                             FILE_TRAVERSE |
1357                             FILE_DELETE_CHILD |
1358                             FILE_APPEND_DATA));
1359
1360     //
1361     // Our 'read only' access mask. These are the accesses we will
1362     // allow for a read only file
1363     //
1364
1365     stAccessMask = DELETE |
1366                         READ_CONTROL |
1367                         WRITE_OWNER |
1368                         WRITE_DAC |
1369                         SYNCHRONIZE |
1370                         ACCESS_SYSTEM_SECURITY |
1371                         FILE_READ_DATA |
1372                         FILE_READ_EA |
1373                         FILE_WRITE_EA |
1374                         FILE_READ_ATTRIBUTES |
1375                         FILE_WRITE_ATTRIBUTES |
1376                         FILE_EXECUTE |
1377                         FILE_LIST_DIRECTORY |
1378                         FILE_TRAVERSE;
1379
1380     //
1381     // For a directory, add in the directory specific accesses
1382     //
1383
1384     if( DirectoryEntry)
1385     {
1386
1387         stAccessMask |= FILE_ADD_SUBDIRECTORY |
1388                                 FILE_ADD_FILE |
1389                                 FILE_DELETE_CHILD;
1390     }
1391
1392     if( FlagOn( DesiredAccess, ~stAccessMask))
1393     {
1394
1395         //
1396         // A write access is set ...
1397         //
1398
1399         bReturn = FALSE;
1400     }
1401
1402     return bReturn;
1403 }
1404
1405 NTSTATUS
1406 AFSEvaluateNode( IN GUID *AuthGroup,
1407                  IN AFSDirectoryCB *DirEntry)
1408 {
1409
1410     NTSTATUS ntStatus = STATUS_SUCCESS;
1411     AFSDirEnumEntry *pDirEntry = NULL;
1412     UNICODE_STRING uniTargetName;
1413
1414     __Enter
1415     {
1416
1417         ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1418                                           AuthGroup,
1419                                           FALSE,
1420                                           &pDirEntry);
1421
1422         if( !NT_SUCCESS( ntStatus))
1423         {
1424
1425             try_return( ntStatus);
1426         }
1427
1428         DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1429
1430         DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1431
1432         DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1433
1434         DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1435
1436         DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1437
1438         DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1439
1440         DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1441
1442         DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1443
1444         DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1445
1446         DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1447
1448         DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1449
1450         if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1451             pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1452         {
1453
1454             DirEntry->ObjectInformation->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1455         }
1456
1457         if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK)
1458         {
1459
1460             if ( DirEntry->ObjectInformation->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1461             {
1462
1463                 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1464             }
1465             else
1466             {
1467
1468                 DirEntry->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1469             }
1470         }
1471
1472         DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1473
1474         DirEntry->ObjectInformation->Links = pDirEntry->Links;
1475
1476         //
1477         // If we have a target name then see if it needs updating ...
1478         //
1479
1480         if( pDirEntry->TargetNameLength > 0)
1481         {
1482
1483             //
1484             // Update the target name information if needed
1485             //
1486
1487             uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1488
1489             uniTargetName.MaximumLength = uniTargetName.Length;
1490
1491             uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1492
1493             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1494                             TRUE);
1495
1496             if( DirEntry->NameInformation.TargetName.Length == 0 ||
1497                 RtlCompareUnicodeString( &uniTargetName,
1498                                          &DirEntry->NameInformation.TargetName,
1499                                          TRUE) != 0)
1500             {
1501
1502                 //
1503                 // Update the target name
1504                 //
1505
1506                 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1507                                                 &DirEntry->Flags,
1508                                                 uniTargetName.Buffer,
1509                                                 uniTargetName.Length);
1510
1511                 if( !NT_SUCCESS( ntStatus))
1512                 {
1513
1514                     AFSReleaseResource( &DirEntry->NonPaged->Lock);
1515
1516                     try_return( ntStatus);
1517                 }
1518             }
1519
1520             AFSReleaseResource( &DirEntry->NonPaged->Lock);
1521         }
1522
1523 try_exit:
1524
1525         if( pDirEntry != NULL)
1526         {
1527
1528             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
1529         }
1530     }
1531
1532     return ntStatus;
1533 }
1534
1535 NTSTATUS
1536 AFSValidateSymLink( IN GUID *AuthGroup,
1537                     IN AFSDirectoryCB *DirEntry)
1538 {
1539
1540     NTSTATUS ntStatus = STATUS_SUCCESS;
1541     AFSDirEnumEntry *pDirEntry = NULL;
1542     UNICODE_STRING uniTargetName;
1543
1544     __Enter
1545     {
1546
1547         ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1548                                           AuthGroup,
1549                                           FALSE,
1550                                           &pDirEntry);
1551
1552         if( !NT_SUCCESS( ntStatus))
1553         {
1554
1555             try_return( ntStatus);
1556         }
1557
1558         if( pDirEntry->FileType == AFS_FILE_TYPE_UNKNOWN ||
1559             pDirEntry->FileType == AFS_FILE_TYPE_INVALID)
1560         {
1561
1562             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1563                           AFS_TRACE_LEVEL_VERBOSE_2,
1564                           "AFSValidateSymLink Invalid type Status %08lX\n",
1565                           STATUS_OBJECT_NAME_NOT_FOUND));
1566
1567             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
1568         }
1569
1570         DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1571
1572         DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1573
1574         DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1575
1576         //
1577         // Update the target name information if needed
1578         //
1579
1580         uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1581
1582         uniTargetName.MaximumLength = uniTargetName.Length;
1583
1584         uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1585
1586         if( uniTargetName.Length > 0)
1587         {
1588
1589             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1590                             TRUE);
1591
1592             if( DirEntry->NameInformation.TargetName.Length == 0 ||
1593                 RtlCompareUnicodeString( &uniTargetName,
1594                                          &DirEntry->NameInformation.TargetName,
1595                                          TRUE) != 0)
1596             {
1597
1598                 //
1599                 // Update the target name
1600                 //
1601
1602                 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1603                                                 &DirEntry->Flags,
1604                                                 uniTargetName.Buffer,
1605                                                 uniTargetName.Length);
1606
1607                 if( !NT_SUCCESS( ntStatus))
1608                 {
1609
1610                     AFSReleaseResource( &DirEntry->NonPaged->Lock);
1611
1612                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1613                 }
1614             }
1615
1616             AFSReleaseResource( &DirEntry->NonPaged->Lock);
1617         }
1618
1619         //
1620         // If the FileType is the same then nothing to do since it IS
1621         // a SymLink
1622         //
1623
1624         if( pDirEntry->FileType == DirEntry->ObjectInformation->FileType)
1625         {
1626
1627             ASSERT( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK);
1628
1629             try_return( ntStatus = STATUS_SUCCESS);
1630         }
1631
1632         DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1633
1634         DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1635
1636         DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1637
1638         DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1639
1640         DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1641
1642         DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1643
1644         DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1645
1646         DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1647
1648         if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1649             pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1650         {
1651
1652             DirEntry->ObjectInformation->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1653         }
1654
1655         if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK)
1656         {
1657
1658             if ( DirEntry->ObjectInformation->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1659             {
1660
1661                 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1662             }
1663             else
1664             {
1665
1666                 DirEntry->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1667             }
1668         }
1669
1670         DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1671
1672         DirEntry->ObjectInformation->Links = pDirEntry->Links;
1673
1674 try_exit:
1675
1676         if( pDirEntry != NULL)
1677         {
1678
1679             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
1680         }
1681     }
1682
1683     return ntStatus;
1684 }
1685
1686 NTSTATUS
1687 AFSInvalidateObject( IN OUT AFSObjectInfoCB **ppObjectInfo,
1688                      IN     ULONG Reason)
1689 {
1690
1691     NTSTATUS ntStatus = STATUS_SUCCESS;
1692     IO_STATUS_BLOCK stIoStatus;
1693     ULONG ulFilter = 0;
1694     AFSObjectInfoCB * pParentObjectInfo = NULL;
1695
1696     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1697                   AFS_TRACE_LEVEL_VERBOSE,
1698                   "AFSInvalidateObject Invalidation on node type %d for fid %08lX-%08lX-%08lX-%08lX Reason %d\n",
1699                   (*ppObjectInfo)->FileType,
1700                   (*ppObjectInfo)->FileId.Cell,
1701                   (*ppObjectInfo)->FileId.Volume,
1702                   (*ppObjectInfo)->FileId.Vnode,
1703                   (*ppObjectInfo)->FileId.Unique,
1704                   Reason));
1705
1706     if ( BooleanFlagOn( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1707     {
1708
1709         pParentObjectInfo = AFSFindObjectInfo( (*ppObjectInfo)->VolumeCB,
1710                                                &(*ppObjectInfo)->ParentFileId,
1711                                                FALSE);
1712     }
1713
1714     if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_SYMLINK ||
1715         (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DFSLINK ||
1716         (*ppObjectInfo)->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1717     {
1718         //
1719         // We only act on the mount point itself, not the target. If the
1720         // node has been deleted then mark it as such otherwise indicate
1721         // it requires verification
1722         //
1723
1724         if( Reason == AFS_INVALIDATE_DELETED)
1725         {
1726             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
1727         }
1728         else
1729         {
1730
1731             if( Reason == AFS_INVALIDATE_FLUSHED)
1732             {
1733
1734                 (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1735
1736                 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1737             }
1738
1739             (*ppObjectInfo)->Expiration.QuadPart = 0;
1740
1741             (*ppObjectInfo)->TargetFileId.Vnode = 0;
1742
1743             (*ppObjectInfo)->TargetFileId.Unique = 0;
1744
1745             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1746                           AFS_TRACE_LEVEL_VERBOSE,
1747                           "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1748                           (*ppObjectInfo)->FileId.Cell,
1749                           (*ppObjectInfo)->FileId.Volume,
1750                           (*ppObjectInfo)->FileId.Vnode,
1751                           (*ppObjectInfo)->FileId.Unique));
1752
1753             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1754         }
1755
1756         if ( pParentObjectInfo != NULL)
1757         {
1758
1759             ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1760
1761             if( Reason == AFS_INVALIDATE_CREDS)
1762             {
1763                 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1764             }
1765
1766             if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1767                 Reason == AFS_INVALIDATE_FLUSHED)
1768             {
1769                 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1770             }
1771             else
1772             {
1773                 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1774             }
1775
1776             AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1777                                             NULL,
1778                                             ulFilter,
1779                                             FILE_ACTION_MODIFIED);
1780         }
1781
1782         try_return( ntStatus);
1783     }
1784
1785     //
1786     // Depending on the reason for invalidation then perform work on the node
1787     //
1788
1789     switch( Reason)
1790     {
1791
1792     case AFS_INVALIDATE_DELETED:
1793         {
1794
1795             //
1796             // Mark this node as invalid
1797             //
1798
1799             (*ppObjectInfo)->Links = 0;
1800
1801             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_DELETED);
1802
1803             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1804                           AFS_TRACE_LEVEL_VERBOSE,
1805                           "AFSInvalidateObject Set DELETE flag on fid %08lX-%08lX-%08lX-%08lX\n",
1806                           (*ppObjectInfo)->FileId.Cell,
1807                           (*ppObjectInfo)->FileId.Volume,
1808                           (*ppObjectInfo)->FileId.Vnode,
1809                           (*ppObjectInfo)->FileId.Unique));
1810
1811             if( pParentObjectInfo != NULL)
1812             {
1813
1814                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1815                               AFS_TRACE_LEVEL_VERBOSE,
1816                               "AFSInvalidateObject Set VERIFY flag on parent fid %08lX-%08lX-%08lX-%08lX\n",
1817                               pParentObjectInfo->FileId.Cell,
1818                               pParentObjectInfo->FileId.Volume,
1819                               pParentObjectInfo->FileId.Vnode,
1820                               pParentObjectInfo->FileId.Unique));
1821
1822                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1823
1824                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1825
1826                 pParentObjectInfo->Expiration.QuadPart = 0;
1827
1828                 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1829                 {
1830                     ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1831                 }
1832                 else
1833                 {
1834                     ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1835                 }
1836
1837                 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1838                                                 NULL,
1839                                                 ulFilter,
1840                                                 FILE_ACTION_REMOVED);
1841             }
1842
1843             if( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1844                                                       Reason)))
1845             {
1846                 (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1847             }
1848
1849             break;
1850         }
1851
1852     case AFS_INVALIDATE_FLUSHED:
1853         {
1854
1855             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1856                 (*ppObjectInfo)->Fcb != NULL)
1857             {
1858
1859                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1860                               AFS_TRACE_LEVEL_VERBOSE,
1861                               "AFSInvalidateObject Flush/purge file fid %08lX-%08lX-%08lX-%08lX\n",
1862                               (*ppObjectInfo)->FileId.Cell,
1863                               (*ppObjectInfo)->FileId.Volume,
1864                               (*ppObjectInfo)->FileId.Vnode,
1865                               (*ppObjectInfo)->FileId.Unique));
1866
1867                 AFSAcquireExcl( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectResource,
1868                                 TRUE);
1869
1870                 __try
1871                 {
1872
1873                     CcFlushCache( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1874                                   NULL,
1875                                   0,
1876                                   &stIoStatus);
1877
1878                     if( !NT_SUCCESS( stIoStatus.Status))
1879                     {
1880
1881                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1882                                       AFS_TRACE_LEVEL_ERROR,
1883                                       "AFSInvalidateObject CcFlushCache failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1884                                       (*ppObjectInfo)->FileId.Cell,
1885                                       (*ppObjectInfo)->FileId.Volume,
1886                                       (*ppObjectInfo)->FileId.Vnode,
1887                                       (*ppObjectInfo)->FileId.Unique,
1888                                       stIoStatus.Status,
1889                                       stIoStatus.Information));
1890
1891                         ntStatus = stIoStatus.Status;
1892                     }
1893
1894
1895                     if ( (*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
1896                     {
1897
1898                         if ( !CcPurgeCacheSection( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1899                                                    NULL,
1900                                                    0,
1901                                                    FALSE))
1902                         {
1903
1904                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1905                                           AFS_TRACE_LEVEL_WARNING,
1906                                           "AFSInvalidateObject CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
1907                                           (*ppObjectInfo)->FileId.Cell,
1908                                           (*ppObjectInfo)->FileId.Volume,
1909                                           (*ppObjectInfo)->FileId.Vnode,
1910                                           (*ppObjectInfo)->FileId.Unique));
1911
1912                             SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1913                         }
1914                     }
1915                 }
1916                 __except( EXCEPTION_EXECUTE_HANDLER)
1917                 {
1918
1919                     ntStatus = GetExceptionCode();
1920
1921                     AFSDbgTrace(( 0,
1922                                   0,
1923                                   "EXCEPTION - AFSInvalidateObject Cc FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
1924                                   (*ppObjectInfo)->FileId.Cell,
1925                                   (*ppObjectInfo)->FileId.Volume,
1926                                   (*ppObjectInfo)->FileId.Vnode,
1927                                   (*ppObjectInfo)->FileId.Unique,
1928                                   ntStatus));
1929
1930                     SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1931                 }
1932
1933                 AFSReleaseResource( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectResource);
1934
1935                 //
1936                 // Clear out the extents
1937                 // Get rid of them (note this involves waiting
1938                 // for any writes or reads to the cache to complete)
1939                 //
1940
1941                 AFSTearDownFcbExtents( (*ppObjectInfo)->Fcb,
1942                                        NULL);
1943             }
1944
1945             (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1946
1947
1948             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE)
1949             {
1950
1951                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1952                               AFS_TRACE_LEVEL_VERBOSE,
1953                               "AFSInvalidateObject Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
1954                               (*ppObjectInfo)->FileId.Cell,
1955                               (*ppObjectInfo)->FileId.Volume,
1956                               (*ppObjectInfo)->FileId.Vnode,
1957                               (*ppObjectInfo)->FileId.Unique));
1958
1959                 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1960             }
1961
1962             // Fall through to the default processing
1963         }
1964
1965     default:
1966         {
1967
1968             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1969             {
1970                 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1971             }
1972             else
1973             {
1974                 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1975             }
1976
1977             if( Reason == AFS_INVALIDATE_CREDS)
1978             {
1979                 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1980             }
1981
1982             if( Reason == AFS_INVALIDATE_DATA_VERSION)
1983             {
1984                 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1985             }
1986             else
1987             {
1988                 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1989             }
1990
1991             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1992             {
1993
1994                 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo),
1995                                                 NULL,
1996                                                 ulFilter,
1997                                                 FILE_ACTION_MODIFIED);
1998             }
1999             else if ( pParentObjectInfo != NULL)
2000             {
2001
2002                 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
2003                                                 NULL,
2004                                                 ulFilter,
2005                                                 FILE_ACTION_MODIFIED);
2006             }
2007
2008             //
2009             // Indicate this node requires re-evaluation for the remaining reasons
2010             //
2011
2012             (*ppObjectInfo)->Expiration.QuadPart = 0;
2013
2014             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2015                           AFS_TRACE_LEVEL_VERBOSE,
2016                           "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
2017                           (*ppObjectInfo)->FileId.Cell,
2018                           (*ppObjectInfo)->FileId.Volume,
2019                           (*ppObjectInfo)->FileId.Vnode,
2020                           (*ppObjectInfo)->FileId.Unique));
2021
2022             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
2023
2024             if( Reason == AFS_INVALIDATE_DATA_VERSION ||
2025                 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
2026                 ( Reason == AFS_INVALIDATE_CALLBACK ||
2027                   Reason == AFS_INVALIDATE_EXPIRED))
2028             {
2029                 if ( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
2030                                                            AFS_INVALIDATE_DATA_VERSION)))
2031                 {
2032
2033                     (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
2034                 }
2035             }
2036
2037             break;
2038         }
2039     }
2040
2041   try_exit:
2042
2043     if ( pParentObjectInfo != NULL)
2044     {
2045
2046         AFSReleaseObjectInfo( &pParentObjectInfo);
2047     }
2048
2049     return ntStatus;
2050 }
2051
2052 NTSTATUS
2053 AFSInvalidateCache( IN AFSInvalidateCacheCB *InvalidateCB)
2054 {
2055
2056     NTSTATUS ntStatus = STATUS_SUCCESS;
2057     AFSVolumeCB *pVolumeCB = NULL;
2058     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2059     ULONGLONG   ullIndex = 0;
2060     AFSObjectInfoCB *pObjectInfo = NULL;
2061     LONG lCount;
2062
2063     __Enter
2064     {
2065
2066         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2067                       AFS_TRACE_LEVEL_VERBOSE,
2068                       "AFSInvalidateCache Invalidation FID %08lX-%08lX-%08lX-%08lX Type %d WholeVolume %d Reason %d\n",
2069                       InvalidateCB->FileID.Cell,
2070                       InvalidateCB->FileID.Volume,
2071                       InvalidateCB->FileID.Vnode,
2072                       InvalidateCB->FileID.Unique,
2073                       InvalidateCB->FileType,
2074                       InvalidateCB->WholeVolume,
2075                       InvalidateCB->Reason));
2076
2077         //
2078         // Need to locate the Fcb for the directory to purge
2079         //
2080
2081         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2082                       AFS_TRACE_LEVEL_VERBOSE,
2083                       "AFSInvalidateCache Acquiring RDR VolumeTreeLock lock %p SHARED %08lX\n",
2084                       &pDevExt->Specific.RDR.VolumeTreeLock,
2085                       PsGetCurrentThread()));
2086
2087         //
2088         // Starve any exclusive waiters on this paticular call
2089         //
2090
2091         AFSAcquireSharedStarveExclusive( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2092
2093         //
2094         // Locate the volume node
2095         //
2096
2097         ullIndex = AFSCreateHighIndex( &InvalidateCB->FileID);
2098
2099         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2100                                        ullIndex,
2101                                        (AFSBTreeEntry **)&pVolumeCB);
2102
2103         if( pVolumeCB != NULL)
2104         {
2105
2106             lCount = AFSVolumeIncrement( pVolumeCB,
2107                                          AFS_VOLUME_REFERENCE_INVALIDATE);
2108
2109             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2110                           AFS_TRACE_LEVEL_VERBOSE,
2111                           "AFSInvalidateCache Increment count on volume %p Cnt %d\n",
2112                           pVolumeCB,
2113                           lCount));
2114         }
2115
2116         AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2117
2118         if( !NT_SUCCESS( ntStatus) ||
2119             pVolumeCB == NULL)
2120         {
2121
2122             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2123                           AFS_TRACE_LEVEL_WARNING,
2124                           "AFSInvalidateCache Invalidation FAILURE Unable to locate volume node FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2125                           InvalidateCB->FileID.Cell,
2126                           InvalidateCB->FileID.Volume,
2127                           InvalidateCB->FileID.Vnode,
2128                           InvalidateCB->FileID.Unique,
2129                           ntStatus));
2130
2131             try_return( ntStatus = STATUS_SUCCESS);
2132         }
2133
2134         //
2135         // If this is a whole volume invalidation then go do it now
2136         //
2137
2138         if( InvalidateCB->WholeVolume)
2139         {
2140
2141             ntStatus = AFSInvalidateVolume( pVolumeCB,
2142                                             InvalidateCB->Reason);
2143
2144             try_return( ntStatus);
2145         }
2146
2147         AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
2148                           TRUE);
2149
2150         if ( AFSIsVolumeFID( &InvalidateCB->FileID))
2151         {
2152
2153             pObjectInfo = &pVolumeCB->ObjectInformation;
2154         }
2155         else
2156         {
2157
2158             ullIndex = AFSCreateLowIndex( &InvalidateCB->FileID);
2159
2160             ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2161                                            ullIndex,
2162                                            (AFSBTreeEntry **)&pObjectInfo);
2163         }
2164
2165         if( pObjectInfo != NULL)
2166         {
2167
2168             //
2169             // Reference the node so it won't be torn down
2170             //
2171
2172             lCount = AFSObjectInfoIncrement( pObjectInfo,
2173                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2174
2175             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2176                           AFS_TRACE_LEVEL_VERBOSE,
2177                           "AFSInvalidateCache Increment count on object %p Cnt %d\n",
2178                           pObjectInfo,
2179                           lCount));
2180         }
2181
2182         AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2183
2184         if( !NT_SUCCESS( ntStatus) ||
2185             pObjectInfo == NULL)
2186         {
2187
2188             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2189                           AFS_TRACE_LEVEL_VERBOSE,
2190                           "AFSInvalidateCache Invalidation FAILURE Unable to locate object FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2191                           InvalidateCB->FileID.Cell,
2192                           InvalidateCB->FileID.Volume,
2193                           InvalidateCB->FileID.Vnode,
2194                           InvalidateCB->FileID.Unique,
2195                           ntStatus));
2196
2197             try_return( ntStatus = STATUS_SUCCESS);
2198         }
2199
2200         AFSInvalidateObject( &pObjectInfo,
2201                              InvalidateCB->Reason);
2202
2203 try_exit:
2204
2205         if( pObjectInfo != NULL)
2206         {
2207
2208             lCount = AFSObjectInfoDecrement( pObjectInfo,
2209                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2210
2211             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2212                           AFS_TRACE_LEVEL_VERBOSE,
2213                           "AFSInvalidateCache Decrement count on object %p Cnt %d\n",
2214                           pObjectInfo,
2215                           lCount));
2216         }
2217
2218         if ( pVolumeCB != NULL)
2219         {
2220
2221             lCount = AFSVolumeDecrement( pVolumeCB,
2222                                          AFS_VOLUME_REFERENCE_INVALIDATE);
2223
2224             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2225                           AFS_TRACE_LEVEL_VERBOSE,
2226                           "AFSInvalidateCache Decrement count on volume %p Cnt %d\n",
2227                           pVolumeCB,
2228                           lCount));
2229         }
2230     }
2231
2232     return ntStatus;
2233 }
2234
2235 BOOLEAN
2236 AFSIsChildOfParent( IN AFSFcb *Dcb,
2237                     IN AFSFcb *Fcb)
2238 {
2239
2240     BOOLEAN bIsChild = FALSE;
2241     AFSFcb *pCurrentFcb = Fcb;
2242     AFSObjectInfoCB * pParentObjectInfo = NULL;
2243
2244     while( pCurrentFcb != NULL)
2245     {
2246
2247         if( BooleanFlagOn( pCurrentFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
2248             AFSIsEqualFID( &pCurrentFcb->ObjectInformation->ParentFileId, &Dcb->ObjectInformation->FileId))
2249         {
2250
2251             bIsChild = TRUE;
2252
2253             break;
2254         }
2255
2256         pParentObjectInfo = AFSFindObjectInfo( pCurrentFcb->ObjectInformation->VolumeCB,
2257                                                &pCurrentFcb->ObjectInformation->ParentFileId,
2258                                                FALSE);
2259
2260         if ( pParentObjectInfo != NULL)
2261         {
2262
2263             pCurrentFcb = pParentObjectInfo->Fcb;
2264
2265             AFSReleaseObjectInfo( &pParentObjectInfo);
2266         }
2267         else
2268         {
2269
2270             pCurrentFcb = NULL;
2271         }
2272     }
2273
2274     return bIsChild;
2275 }
2276
2277 inline
2278 ULONGLONG
2279 AFSCreateHighIndex( IN AFSFileID *FileID)
2280 {
2281
2282     ULONGLONG ullIndex = 0;
2283
2284     ullIndex = (((ULONGLONG)FileID->Cell << 32) | FileID->Volume);
2285
2286     return ullIndex;
2287 }
2288
2289 inline
2290 ULONGLONG
2291 AFSCreateLowIndex( IN AFSFileID *FileID)
2292 {
2293
2294     ULONGLONG ullIndex = 0;
2295
2296     ullIndex = (((ULONGLONG)FileID->Vnode << 32) | FileID->Unique);
2297
2298     return ullIndex;
2299 }
2300
2301 BOOLEAN
2302 AFSCheckAccess( IN ACCESS_MASK DesiredAccess,
2303                 IN ACCESS_MASK GrantedAccess,
2304                 IN BOOLEAN DirectoryEntry)
2305 {
2306
2307     BOOLEAN bAccessGranted = TRUE;
2308
2309     //
2310     // Check if we are asking for read/write and granted only read only
2311     // NOTE: There will be more checks here
2312     //
2313
2314     if( !AFSCheckForReadOnlyAccess( DesiredAccess,
2315                                     DirectoryEntry) &&
2316         AFSCheckForReadOnlyAccess( GrantedAccess,
2317                                    DirectoryEntry))
2318     {
2319
2320         bAccessGranted = FALSE;
2321     }
2322
2323     return bAccessGranted;
2324 }
2325
2326 NTSTATUS
2327 AFSGetDriverStatus( IN AFSDriverStatusRespCB *DriverStatus)
2328 {
2329
2330     NTSTATUS         ntStatus = STATUS_SUCCESS;
2331     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2332
2333     //
2334     // Start with read
2335     //
2336
2337     DriverStatus->Status = AFS_DRIVER_STATUS_READY;
2338
2339     if( AFSGlobalRoot == NULL)
2340     {
2341
2342         //
2343         // We are not ready
2344         //
2345
2346         DriverStatus->Status = AFS_DRIVER_STATUS_NOT_READY;
2347     }
2348
2349     if( pControlDevExt->Specific.Control.CommServiceCB.IrpPoolControlFlag != POOL_ACTIVE)
2350     {
2351
2352         //
2353         // No service yet
2354         //
2355
2356         DriverStatus->Status = AFS_DRIVER_STATUS_NO_SERVICE;
2357     }
2358
2359     return ntStatus;
2360 }
2361
2362 NTSTATUS
2363 AFSSubstituteSysName( IN UNICODE_STRING *ComponentName,
2364                       IN UNICODE_STRING *SubstituteName,
2365                       IN ULONG StringIndex)
2366 {
2367
2368     NTSTATUS ntStatus = STATUS_SUCCESS;
2369     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2370     AFSSysNameCB    *pSysName = NULL;
2371     ERESOURCE       *pSysNameLock = NULL;
2372     ULONG            ulIndex = 1;
2373     USHORT           usIndex = 0;
2374     UNICODE_STRING   uniSysName;
2375
2376     __Enter
2377     {
2378
2379 #if defined(_WIN64)
2380
2381         if( IoIs32bitProcess( NULL))
2382         {
2383
2384             pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2385
2386             pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2387         }
2388         else
2389         {
2390
2391             pSysNameLock = &pControlDevExt->Specific.Control.SysName64ListLock;
2392
2393             pSysName = pControlDevExt->Specific.Control.SysName64ListHead;
2394         }
2395 #else
2396
2397         pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2398
2399         pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2400
2401 #endif
2402
2403         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2404                       AFS_TRACE_LEVEL_VERBOSE,
2405                       "AFSSubstituteSysName Acquiring SysName lock %p SHARED %08lX\n",
2406                       pSysNameLock,
2407                       PsGetCurrentThread()));
2408
2409         AFSAcquireShared( pSysNameLock,
2410                           TRUE);
2411
2412         //
2413         // Find where we are in the list
2414         //
2415
2416         while( pSysName != NULL &&
2417             ulIndex < StringIndex)
2418         {
2419
2420             pSysName = pSysName->fLink;
2421
2422             ulIndex++;
2423         }
2424
2425         if( pSysName == NULL)
2426         {
2427
2428             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2429                           AFS_TRACE_LEVEL_VERBOSE_2,
2430                           "AFSSubstituteSysName No sysname %wZ Status %08lX\n",
2431                           &ComponentName,
2432                           STATUS_OBJECT_NAME_NOT_FOUND));
2433
2434             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
2435         }
2436
2437         RtlInitUnicodeString( &uniSysName,
2438                               L"@SYS");
2439         //
2440         // If it is a full component of @SYS then just substitue the
2441         // name in
2442         //
2443
2444         if( RtlCompareUnicodeString( &uniSysName,
2445                                      ComponentName,
2446                                      TRUE) == 0)
2447         {
2448
2449             SubstituteName->Length = pSysName->SysName.Length;
2450             SubstituteName->MaximumLength = SubstituteName->Length;
2451
2452             SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2453                                                                         SubstituteName->Length,
2454                                                                         AFS_SUBST_BUFFER_TAG);
2455
2456             if( SubstituteName->Buffer == NULL)
2457             {
2458
2459                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2460             }
2461
2462             RtlCopyMemory( SubstituteName->Buffer,
2463                            pSysName->SysName.Buffer,
2464                            pSysName->SysName.Length);
2465         }
2466         else
2467         {
2468
2469             usIndex = 0;
2470
2471             while( ComponentName->Buffer[ usIndex] != L'@')
2472             {
2473
2474                 usIndex++;
2475             }
2476
2477             SubstituteName->Length = (usIndex * sizeof( WCHAR)) + pSysName->SysName.Length;
2478             SubstituteName->MaximumLength = SubstituteName->Length;
2479
2480             SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2481                                                                         SubstituteName->Length,
2482                                                                         AFS_SUBST_BUFFER_TAG);
2483
2484             if( SubstituteName->Buffer == NULL)
2485             {
2486
2487                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2488             }
2489
2490             RtlCopyMemory( SubstituteName->Buffer,
2491                            ComponentName->Buffer,
2492                            usIndex * sizeof( WCHAR));
2493
2494             RtlCopyMemory( &SubstituteName->Buffer[ usIndex],
2495                            pSysName->SysName.Buffer,
2496                            pSysName->SysName.Length);
2497         }
2498
2499 try_exit:
2500
2501         AFSReleaseResource( pSysNameLock);
2502     }
2503
2504     return ntStatus;
2505 }
2506
2507 NTSTATUS
2508 AFSSubstituteNameInPath( IN OUT UNICODE_STRING *FullPathName,
2509                          IN OUT UNICODE_STRING *ComponentName,
2510                          IN UNICODE_STRING *SubstituteName,
2511                          IN OUT UNICODE_STRING *RemainingPath,
2512                          IN BOOLEAN FreePathName)
2513 {
2514
2515     NTSTATUS ntStatus = STATUS_SUCCESS;
2516     UNICODE_STRING uniPathName;
2517     USHORT usPrefixNameLen = 0;
2518     SHORT  sNameLenDelta = 0;
2519
2520     __Enter
2521     {
2522
2523         //
2524         // If the passed in name can handle the additional length
2525         // then just moves things around
2526         //
2527
2528         sNameLenDelta = SubstituteName->Length - ComponentName->Length;
2529
2530         usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2531
2532         if( FullPathName->MaximumLength > FullPathName->Length + sNameLenDelta)
2533         {
2534
2535             if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2536             {
2537
2538                 RtlMoveMemory( &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + SubstituteName->Length)/sizeof( WCHAR))],
2539                                &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + ComponentName->Length)/sizeof( WCHAR))],
2540                                FullPathName->Length - usPrefixNameLen*sizeof( WCHAR) - ComponentName->Length);
2541             }
2542
2543             RtlCopyMemory( &FullPathName->Buffer[ usPrefixNameLen],
2544                            SubstituteName->Buffer,
2545                            SubstituteName->Length);
2546
2547             FullPathName->Length += sNameLenDelta;
2548
2549             ComponentName->Length += sNameLenDelta;
2550
2551             ComponentName->MaximumLength = ComponentName->Length;
2552
2553             if ( RemainingPath->Buffer)
2554             {
2555
2556                 RemainingPath->Buffer += sNameLenDelta/sizeof( WCHAR);
2557             }
2558
2559             try_return( ntStatus);
2560         }
2561
2562         //
2563         // Need to re-allocate the buffer
2564         //
2565
2566         uniPathName.Length = FullPathName->Length -
2567                                          ComponentName->Length +
2568                                          SubstituteName->Length;
2569
2570         uniPathName.MaximumLength = FullPathName->MaximumLength + PAGE_SIZE;
2571
2572         uniPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2573                                                                 uniPathName.MaximumLength,
2574                                                                 AFS_NAME_BUFFER_FOUR_TAG);
2575
2576         if( uniPathName.Buffer == NULL)
2577         {
2578
2579             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2580         }
2581
2582         usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2583
2584         usPrefixNameLen *= sizeof( WCHAR);
2585
2586         RtlZeroMemory( uniPathName.Buffer,
2587                        uniPathName.MaximumLength);
2588
2589         RtlCopyMemory( uniPathName.Buffer,
2590                        FullPathName->Buffer,
2591                        usPrefixNameLen);
2592
2593         RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen/sizeof( WCHAR))],
2594                        SubstituteName->Buffer,
2595                        SubstituteName->Length);
2596
2597         if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2598         {
2599
2600             RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen + SubstituteName->Length)/sizeof( WCHAR)],
2601                            &FullPathName->Buffer[ (usPrefixNameLen + ComponentName->Length)/sizeof( WCHAR)],
2602                            FullPathName->Length - usPrefixNameLen - ComponentName->Length);
2603         }
2604
2605         ComponentName->Buffer = uniPathName.Buffer + (ComponentName->Buffer - FullPathName->Buffer);
2606
2607         ComponentName->Length += sNameLenDelta;
2608
2609         ComponentName->MaximumLength = ComponentName->Length;
2610
2611         if ( RemainingPath->Buffer)
2612         {
2613
2614             RemainingPath->Buffer = uniPathName.Buffer
2615                 + (RemainingPath->Buffer - FullPathName->Buffer)
2616                 + sNameLenDelta/sizeof( WCHAR);
2617         }
2618
2619         if( FreePathName)
2620         {
2621             AFSExFreePoolWithTag( FullPathName->Buffer, 0);
2622         }
2623
2624         *FullPathName = uniPathName;
2625
2626 try_exit:
2627
2628         NOTHING;
2629     }
2630
2631     return ntStatus;
2632 }
2633
2634 NTSTATUS
2635 AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
2636                      IN ULONG Reason)
2637 {
2638
2639     NTSTATUS ntStatus = STATUS_SUCCESS;
2640     AFSObjectInfoCB *pCurrentObject = NULL;
2641     AFSObjectInfoCB *pNextObject = NULL;
2642     LONG lCount;
2643
2644     __Enter
2645     {
2646
2647         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2648                       AFS_TRACE_LEVEL_VERBOSE,
2649                       "AFSInvalidateVolume Invalidate volume fid %08lX-%08lX-%08lX-%08lX Reason %08lX\n",
2650                       VolumeCB->ObjectInformation.FileId.Cell,
2651                       VolumeCB->ObjectInformation.FileId.Volume,
2652                       VolumeCB->ObjectInformation.FileId.Vnode,
2653                       VolumeCB->ObjectInformation.FileId.Unique,
2654                       Reason));
2655
2656         //
2657         // Depending on the reason for invalidation then perform work on the node
2658         //
2659
2660         switch( Reason)
2661         {
2662
2663             case AFS_INVALIDATE_DELETED:
2664             {
2665
2666                 //
2667                 // Mark this volume as invalid
2668                 //
2669
2670                 SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
2671
2672                 SetFlag( VolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE);
2673
2674                 break;
2675             }
2676         }
2677
2678         AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2679                           TRUE);
2680
2681         //
2682         // Invalidate the volume root directory
2683         //
2684
2685         pCurrentObject = &VolumeCB->ObjectInformation;
2686
2687         if ( pCurrentObject )
2688         {
2689
2690             lCount = AFSObjectInfoIncrement( pCurrentObject,
2691                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2692
2693             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2694                           AFS_TRACE_LEVEL_VERBOSE,
2695                           "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2696                           pCurrentObject,
2697                           lCount));
2698
2699             AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2700
2701             AFSInvalidateObject( &pCurrentObject,
2702                                  Reason);
2703
2704             AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2705                               TRUE);
2706
2707             if ( pCurrentObject)
2708             {
2709
2710                 lCount = AFSObjectInfoDecrement( pCurrentObject,
2711                                                  AFS_OBJECT_REFERENCE_INVALIDATION);
2712
2713                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2714                               AFS_TRACE_LEVEL_VERBOSE,
2715                               "AFSInvalidateVolumeObjects Decrement count on object %p Cnt %d\n",
2716                               pCurrentObject,
2717                               lCount));
2718             }
2719         }
2720
2721         //
2722         // Apply invalidation to all other volume objects
2723         //
2724
2725         pCurrentObject = VolumeCB->ObjectInfoListHead;
2726
2727         if ( pCurrentObject)
2728         {
2729
2730             //
2731             // Reference the node so it won't be torn down
2732             //
2733
2734             lCount = AFSObjectInfoIncrement( pCurrentObject,
2735                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2736
2737             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2738                           AFS_TRACE_LEVEL_VERBOSE,
2739                           "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2740                           pCurrentObject,
2741                           lCount));
2742         }
2743
2744         while( pCurrentObject != NULL)
2745         {
2746
2747             pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2748
2749             if ( pNextObject)
2750             {
2751
2752                 //
2753                 // Reference the node so it won't be torn down
2754                 //
2755
2756                 lCount = AFSObjectInfoIncrement( pNextObject,
2757                                                  AFS_OBJECT_REFERENCE_INVALIDATION);
2758
2759                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2760                               AFS_TRACE_LEVEL_VERBOSE,
2761                               "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2762                               pNextObject,
2763                               lCount));
2764             }
2765
2766             AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2767
2768             AFSInvalidateObject( &pCurrentObject,
2769                                  Reason);
2770
2771             AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2772                               TRUE);
2773
2774             if ( pCurrentObject )
2775             {
2776
2777                 lCount = AFSObjectInfoDecrement( pCurrentObject,
2778                                                  AFS_OBJECT_REFERENCE_INVALIDATION);
2779
2780                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2781                               AFS_TRACE_LEVEL_VERBOSE,
2782                               "AFSInvalidateVolumeObjects Decrement count on object %p Cnt %d\n",
2783                               pCurrentObject,
2784                               lCount));
2785             }
2786
2787             pCurrentObject = pNextObject;
2788         }
2789
2790         AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2791     }
2792
2793     return ntStatus;
2794 }
2795
2796 VOID
2797 AFSInvalidateAllVolumes( VOID)
2798 {
2799     AFSVolumeCB *pVolumeCB = NULL;
2800     AFSVolumeCB *pNextVolumeCB = NULL;
2801     AFSDeviceExt *pRDRDeviceExt = NULL;
2802     LONG lCount;
2803
2804     pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2805
2806     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2807                   AFS_TRACE_LEVEL_VERBOSE,
2808                   "AFSInvalidateAllVolumes Acquiring RDR VolumeListLock lock %p SHARED %08lX\n",
2809                   &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2810                   PsGetCurrentThread()));
2811
2812     AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2813                       TRUE);
2814
2815     pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
2816
2817     if ( pVolumeCB)
2818     {
2819
2820         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2821                       AFS_TRACE_LEVEL_VERBOSE,
2822                       "AFSInvalidateAllVolumes Acquiring VolumeRoot ObjectInfoTree lock %p SHARED %08lX\n",
2823                       pVolumeCB->ObjectInfoTree.TreeLock,
2824                       PsGetCurrentThread()));
2825
2826         lCount = AFSVolumeIncrement( pVolumeCB,
2827                                      AFS_VOLUME_REFERENCE_INVALIDATE);
2828
2829         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2830                       AFS_TRACE_LEVEL_VERBOSE,
2831                       "AFSInvalidateAllVolumes Increment count on volume %p Cnt %d\n",
2832                       pVolumeCB,
2833                       lCount));
2834     }
2835
2836     while( pVolumeCB != NULL)
2837     {
2838
2839         pNextVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2840
2841         if ( pNextVolumeCB)
2842         {
2843
2844             lCount = AFSVolumeIncrement( pNextVolumeCB,
2845                                          AFS_VOLUME_REFERENCE_INVALIDATE);
2846
2847             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2848                           AFS_TRACE_LEVEL_VERBOSE,
2849                           "AFSInvalidateAllVolumes Increment count on volume %p Cnt %d\n",
2850                           pVolumeCB,
2851                           lCount));
2852         }
2853
2854         AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2855
2856         // do I need to hold the volume lock here?
2857
2858         AFSInvalidateVolume( pVolumeCB, AFS_INVALIDATE_EXPIRED);
2859
2860         AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2861                           TRUE);
2862
2863         lCount = AFSVolumeDecrement( pVolumeCB,
2864                                      AFS_VOLUME_REFERENCE_INVALIDATE);
2865
2866         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2867                       AFS_TRACE_LEVEL_VERBOSE,
2868                       "AFSInvalidateAllVolumes Decrement count on volume %p Cnt %d\n",
2869                       pVolumeCB,
2870                       lCount));
2871
2872         pVolumeCB = pNextVolumeCB;
2873     }
2874
2875     AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2876 }
2877
2878 NTSTATUS
2879 AFSVerifyEntry( IN GUID *AuthGroup,
2880                 IN AFSDirectoryCB *DirEntry)
2881 {
2882
2883     NTSTATUS ntStatus = STATUS_SUCCESS;
2884     AFSDirEnumEntry *pDirEnumEntry = NULL;
2885     AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
2886     IO_STATUS_BLOCK stIoStatus;
2887
2888     __Enter
2889     {
2890
2891         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2892                       AFS_TRACE_LEVEL_VERBOSE_2,
2893                       "AFSVerifyEntry Verifying entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2894                       &DirEntry->NameInformation.FileName,
2895                       pObjectInfo->FileId.Cell,
2896                       pObjectInfo->FileId.Volume,
2897                       pObjectInfo->FileId.Vnode,
2898                       pObjectInfo->FileId.Unique));
2899
2900         ntStatus = AFSEvaluateTargetByID( pObjectInfo,
2901                                           AuthGroup,
2902                                           FALSE,
2903                                           &pDirEnumEntry);
2904
2905         if( !NT_SUCCESS( ntStatus))
2906         {
2907
2908             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2909                           AFS_TRACE_LEVEL_ERROR,
2910                           "AFSVerifyEntry Evaluate Target failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2911                           &DirEntry->NameInformation.FileName,
2912                           pObjectInfo->FileId.Cell,
2913                           pObjectInfo->FileId.Volume,
2914                           pObjectInfo->FileId.Vnode,
2915                           pObjectInfo->FileId.Unique,
2916                           ntStatus));
2917
2918             try_return( ntStatus);
2919         }
2920
2921         //
2922         // Check the data version of the file
2923         //
2924
2925         if( pObjectInfo->DataVersion.QuadPart == pDirEnumEntry->DataVersion.QuadPart)
2926         {
2927             if ( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2928             {
2929
2930                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2931                               AFS_TRACE_LEVEL_VERBOSE,
2932                               "AFSVerifyEntry No DV change %I64X for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2933                               pObjectInfo->DataVersion.QuadPart,
2934                               &DirEntry->NameInformation.FileName,
2935                               pObjectInfo->FileId.Cell,
2936                               pObjectInfo->FileId.Volume,
2937                               pObjectInfo->FileId.Vnode,
2938                               pObjectInfo->FileId.Unique));
2939
2940                 //
2941                 // We are ok, just get out
2942                 //
2943
2944                 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2945
2946                 try_return( ntStatus = STATUS_SUCCESS);
2947             }
2948         }
2949
2950         //
2951         // New data version so we will need to process the node based on the type
2952         //
2953
2954         switch( pDirEnumEntry->FileType)
2955         {
2956
2957             case AFS_FILE_TYPE_MOUNTPOINT:
2958             {
2959
2960                 //
2961                 // For a mount point we need to ensure the target is the same
2962                 //
2963
2964                 if( !AFSIsEqualFID( &pObjectInfo->TargetFileId,
2965                                     &pDirEnumEntry->TargetFileId))
2966                 {
2967
2968                 }
2969
2970                 //
2971                 // Update the metadata for the entry
2972                 //
2973
2974                 ntStatus = AFSUpdateMetaData( DirEntry,
2975                                               pDirEnumEntry);
2976
2977                 if( NT_SUCCESS( ntStatus))
2978                 {
2979
2980                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2981                 }
2982
2983                 break;
2984             }
2985
2986             case AFS_FILE_TYPE_SYMLINK:
2987             {
2988
2989                 //
2990                 // Update the metadata for the entry
2991                 //
2992
2993                 ntStatus = AFSUpdateMetaData( DirEntry,
2994                                               pDirEnumEntry);
2995
2996                 if( NT_SUCCESS( ntStatus))
2997                 {
2998
2999                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3000                 }
3001
3002                 break;
3003             }
3004
3005             case AFS_FILE_TYPE_FILE:
3006             {
3007                 FILE_OBJECT * pCCFileObject = NULL;
3008                 BOOLEAN bPurgeExtents = FALSE;
3009
3010                 if ( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
3011                 {
3012
3013                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3014                                   AFS_TRACE_LEVEL_VERBOSE,
3015                                   "AFSVerifyEntry DV Change %wZ FID %08lX-%08lX-%08lX-%08lX (%08lX != %08lX)\n",
3016                                   &DirEntry->NameInformation.FileName,
3017                                   pObjectInfo->FileId.Cell,
3018                                   pObjectInfo->FileId.Volume,
3019                                   pObjectInfo->FileId.Vnode,
3020                                   pObjectInfo->FileId.Unique,
3021                                   pObjectInfo->DataVersion.LowPart,
3022                                   pDirEnumEntry->DataVersion.LowPart));
3023
3024                     bPurgeExtents = TRUE;
3025                 }
3026
3027                 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
3028                 {
3029
3030                     bPurgeExtents = TRUE;
3031
3032                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3033                                   AFS_TRACE_LEVEL_VERBOSE,
3034                                   "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3035                                   &DirEntry->NameInformation.FileName,
3036                                   pObjectInfo->FileId.Cell,
3037                                   pObjectInfo->FileId.Volume,
3038                                   pObjectInfo->FileId.Vnode,
3039                                   pObjectInfo->FileId.Unique));
3040
3041                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
3042                 }
3043
3044                 if( pObjectInfo->Fcb != NULL)
3045                 {
3046
3047                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3048                                   AFS_TRACE_LEVEL_VERBOSE,
3049                                   "AFSVerifyEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3050                                   &DirEntry->NameInformation.FileName,
3051                                   pObjectInfo->FileId.Cell,
3052                                   pObjectInfo->FileId.Volume,
3053                                   pObjectInfo->FileId.Vnode,
3054                                   pObjectInfo->FileId.Unique));
3055
3056                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3057                                     TRUE);
3058
3059                     __try
3060                     {
3061
3062                         CcFlushCache( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
3063                                       NULL,
3064                                       0,
3065                                       &stIoStatus);
3066
3067                         if( !NT_SUCCESS( stIoStatus.Status))
3068                         {
3069
3070                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
3071                                           AFS_TRACE_LEVEL_ERROR,
3072                                           "AFSVerifyEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
3073                                           &DirEntry->NameInformation.FileName,
3074                                           pObjectInfo->FileId.Cell,
3075                                           pObjectInfo->FileId.Volume,
3076                                           pObjectInfo->FileId.Vnode,
3077                                           pObjectInfo->FileId.Unique,
3078                                           stIoStatus.Status,
3079                                           stIoStatus.Information));
3080
3081                             ntStatus = stIoStatus.Status;
3082                         }
3083
3084                         if ( bPurgeExtents &&
3085                              pObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
3086                         {
3087
3088                             if ( !CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
3089                                                        NULL,
3090                                                        0,
3091                                                        FALSE))
3092                             {
3093
3094                                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
3095                                               AFS_TRACE_LEVEL_WARNING,
3096                                               "AFSVerifyEntry CcPurgeCacheSection failure %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3097                                               &DirEntry->NameInformation.FileName,
3098                                               pObjectInfo->FileId.Cell,
3099                                               pObjectInfo->FileId.Volume,
3100                                               pObjectInfo->FileId.Vnode,
3101                                               pObjectInfo->FileId.Unique));
3102
3103                                 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
3104                             }
3105                         }
3106                     }
3107                     __except( EXCEPTION_EXECUTE_HANDLER)
3108                     {
3109                         ntStatus = GetExceptionCode();
3110
3111                         AFSDbgTrace(( 0,
3112                                       0,
3113                                       "EXCEPTION - AFSVerifyEntry CcFlushCache or CcPurgeCacheSection %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
3114                                       &DirEntry->NameInformation.FileName,
3115                                       pObjectInfo->FileId.Cell,
3116                                       pObjectInfo->FileId.Volume,
3117                                       pObjectInfo->FileId.Vnode,
3118                                       pObjectInfo->FileId.Unique,
3119                                       ntStatus));
3120
3121                         SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
3122                     }
3123
3124                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
3125
3126                     if ( bPurgeExtents)
3127                     {
3128                         AFSFlushExtents( pObjectInfo->Fcb,
3129                                          AuthGroup);
3130                     }
3131
3132                     //
3133                     // Reacquire the Fcb to purge the cache
3134                     //
3135
3136                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3137                                   AFS_TRACE_LEVEL_VERBOSE,
3138                                   "AFSVerifyEntry Acquiring Fcb lock %p EXCL %08lX\n",
3139                                   &pObjectInfo->Fcb->NPFcb->Resource,
3140                                   PsGetCurrentThread()));
3141
3142                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
3143                                     TRUE);
3144
3145                     //
3146                     // Update the metadata for the entry
3147                     //
3148
3149                     ntStatus = AFSUpdateMetaData( DirEntry,
3150                                                   pDirEnumEntry);
3151
3152                     if( !NT_SUCCESS( ntStatus))
3153                     {
3154
3155                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3156                                       AFS_TRACE_LEVEL_ERROR,
3157                                       "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
3158                                       &DirEntry->NameInformation.FileName,
3159                                       pObjectInfo->FileId.Cell,
3160                                       pObjectInfo->FileId.Volume,
3161                                       pObjectInfo->FileId.Vnode,
3162                                       pObjectInfo->FileId.Unique,
3163                                       ntStatus));
3164
3165                         break;
3166                     }
3167
3168                     //
3169                     // Update file sizes
3170                     //
3171
3172                     pObjectInfo->Fcb->Header.AllocationSize.QuadPart  = pObjectInfo->AllocationSize.QuadPart;
3173                     pObjectInfo->Fcb->Header.FileSize.QuadPart        = pObjectInfo->EndOfFile.QuadPart;
3174                     pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
3175
3176                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3177                                   AFS_TRACE_LEVEL_VERBOSE,
3178                                   "AFSVerifyEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
3179                                   &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3180                                   PsGetCurrentThread()));
3181
3182                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3183                                     TRUE);
3184
3185                     pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
3186
3187                     if ( pCCFileObject != NULL)
3188                     {
3189                         CcSetFileSizes( pCCFileObject,
3190                                         (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
3191                     }
3192
3193                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3194                                   AFS_TRACE_LEVEL_VERBOSE,
3195                                   "AFSVerifyEntry Releasing Fcb SectionObject lock %p EXCL %08lX\n",
3196                                   &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3197                                   PsGetCurrentThread()));
3198
3199                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
3200
3201                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
3202                 }
3203                 else
3204                 {
3205
3206                     //
3207                     // Update the metadata for the entry
3208                     //
3209
3210                     ntStatus = AFSUpdateMetaData( DirEntry,
3211                                                   pDirEnumEntry);
3212
3213                     if( !NT_SUCCESS( ntStatus))
3214                     {
3215
3216                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3217                                       AFS_TRACE_LEVEL_ERROR,
3218                                       "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
3219                                       &DirEntry->NameInformation.FileName,
3220                                       pObjectInfo->FileId.Cell,
3221                                       pObjectInfo->FileId.Volume,
3222                                       pObjectInfo->FileId.Vnode,
3223                                       pObjectInfo->FileId.Unique,
3224                                       ntStatus));
3225
3226                         break;
3227                     }
3228
3229                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3230                                   AFS_TRACE_LEVEL_WARNING,
3231                                   "AFSVerifyEntry Fcb NULL %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3232                                   &DirEntry->NameInformation.FileName,
3233                                   pObjectInfo->FileId.Cell,
3234                                   pObjectInfo->FileId.Volume,
3235                                   pObjectInfo->FileId.Vnode,
3236                                   pObjectInfo->FileId.Unique));
3237                 }
3238
3239                 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3240
3241                 break;
3242             }
3243
3244             case AFS_FILE_TYPE_DIRECTORY:
3245             {
3246
3247                 //
3248                 // For a directory or root entry flush the content of
3249                 // the directory enumeration.
3250                 //
3251
3252                 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3253                 {
3254
3255                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3256                                   AFS_TRACE_LEVEL_VERBOSE_2,
3257                                   "AFSVerifyEntry Validating directory content for entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3258                                   &DirEntry->NameInformation.FileName,
3259                                   pObjectInfo->FileId.Cell,
3260                                   pObjectInfo->FileId.Volume,
3261                                   pObjectInfo->FileId.Vnode,
3262                                   pObjectInfo->FileId.Unique));
3263
3264                     AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3265                                     TRUE);
3266
3267                     ntStatus = AFSValidateDirectoryCache( pObjectInfo,
3268                                                           AuthGroup);
3269
3270                     AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3271
3272                     if ( !NT_SUCCESS( ntStatus))
3273                     {
3274
3275                         try_return( ntStatus);
3276                     }
3277                 }
3278
3279                 //
3280                 // Update the metadata for the entry
3281                 //
3282
3283                 ntStatus = AFSUpdateMetaData( DirEntry,
3284                                               pDirEnumEntry);
3285
3286                 if( NT_SUCCESS( ntStatus))
3287                 {
3288
3289                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3290                 }
3291
3292                 break;
3293             }
3294
3295             case AFS_FILE_TYPE_DFSLINK:
3296             {
3297
3298                 UNICODE_STRING uniTargetName;
3299
3300                 //
3301                 // For a DFS link need to check the target name has not changed
3302                 //
3303
3304                 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
3305
3306                 uniTargetName.MaximumLength = uniTargetName.Length;
3307
3308                 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
3309
3310                 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3311                                 TRUE);
3312
3313                 if( DirEntry->NameInformation.TargetName.Length == 0 ||
3314                     RtlCompareUnicodeString( &uniTargetName,
3315                                              &DirEntry->NameInformation.TargetName,
3316                                              TRUE) != 0)
3317                 {
3318
3319                     //
3320                     // Update the target name
3321                     //
3322
3323                     ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3324                                                     &DirEntry->Flags,
3325                                                     uniTargetName.Buffer,
3326                                                     uniTargetName.Length);
3327
3328                     if( !NT_SUCCESS( ntStatus))
3329                     {
3330
3331                         AFSReleaseResource( &DirEntry->NonPaged->Lock);
3332
3333                         break;
3334                     }
3335                 }
3336
3337                 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3338
3339                 //
3340                 // Update the metadata for the entry
3341                 //
3342
3343                 ntStatus = AFSUpdateMetaData( DirEntry,
3344                                               pDirEnumEntry);
3345
3346                 if( NT_SUCCESS( ntStatus))
3347                 {
3348
3349                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3350                 }
3351
3352                 break;
3353             }
3354
3355             default:
3356
3357                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3358                               AFS_TRACE_LEVEL_WARNING,
3359                               "AFSVerifyEntry Attempt to verify node of type %d %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3360                               pObjectInfo->FileType,
3361                               &DirEntry->NameInformation.FileName,
3362                               pObjectInfo->FileId.Cell,
3363                               pObjectInfo->FileId.Volume,
3364                               pObjectInfo->FileId.Vnode,
3365                               pObjectInfo->FileId.Unique));
3366
3367                 break;
3368         }
3369
3370  try_exit:
3371
3372         if( pDirEnumEntry != NULL)
3373         {
3374
3375             AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_2_TAG);
3376         }
3377     }
3378
3379     return ntStatus;
3380 }
3381
3382 NTSTATUS
3383 AFSSetVolumeState( IN AFSVolumeStatusCB *VolumeStatus)
3384 {
3385
3386     NTSTATUS ntStatus = STATUS_SUCCESS;
3387     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
3388     ULONGLONG   ullIndex = 0;
3389     AFSVolumeCB *pVolumeCB = NULL;
3390     LONG lCount;
3391
3392     __Enter
3393     {
3394
3395         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3396                       AFS_TRACE_LEVEL_VERBOSE,
3397                       "AFSSetVolumeState Marking volume state %d Volume Cell %08lX Volume %08lX\n",
3398                       VolumeStatus->Online,
3399                       VolumeStatus->FileID.Cell,
3400                       VolumeStatus->FileID.Volume));
3401
3402         //
3403         // Need to locate the Fcb for the directory to purge
3404         //
3405
3406         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3407                       AFS_TRACE_LEVEL_VERBOSE,
3408                       "AFSSetVolumeState Acquiring RDR VolumeTreeLock lock %p SHARED %08lX\n",
3409                       &pDevExt->Specific.RDR.VolumeTreeLock,
3410                       PsGetCurrentThread()));
3411
3412         AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
3413
3414         //
3415         // Locate the volume node
3416         //
3417
3418         ullIndex = AFSCreateHighIndex( &VolumeStatus->FileID);
3419
3420         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
3421                                        ullIndex,
3422                                        (AFSBTreeEntry **)&pVolumeCB);
3423
3424         if( pVolumeCB != NULL)
3425         {
3426
3427             lCount = AFSVolumeIncrement( pVolumeCB,
3428                                          AFS_VOLUME_REFERENCE_INVALIDATE);
3429
3430             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3431                           AFS_TRACE_LEVEL_VERBOSE,
3432                           "AFSSetVolumeState Increment count on volume %p Cnt %d\n",
3433                           pVolumeCB,
3434                           lCount));
3435
3436             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3437
3438             //
3439             // Set the volume state accordingly
3440             //
3441
3442             if( VolumeStatus->Online)
3443             {
3444
3445                 InterlockedAnd( (LONG *)&(pVolumeCB->Flags), ~AFS_VOLUME_FLAGS_OFFLINE);
3446             }
3447             else
3448             {
3449
3450                 InterlockedOr( (LONG *)&(pVolumeCB->Flags), AFS_VOLUME_FLAGS_OFFLINE);
3451             }
3452         }
3453     }
3454
3455     return ntStatus;
3456 }
3457
3458 NTSTATUS
3459 AFSSetNetworkState( IN AFSNetworkStatusCB *NetworkStatus)
3460 {
3461
3462     NTSTATUS ntStatus = STATUS_SUCCESS;
3463
3464     __Enter
3465     {
3466
3467         if( AFSGlobalRoot == NULL)
3468         {
3469
3470             try_return( ntStatus);
3471         }
3472
3473         AFSAcquireExcl( AFSGlobalRoot->VolumeLock,
3474                         TRUE);
3475
3476         //
3477         // Set the network state according to the information
3478         //
3479
3480         if( NetworkStatus->Online)
3481         {
3482
3483             ClearFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3484         }
3485         else
3486         {
3487
3488             SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3489         }
3490
3491         AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3492
3493 try_exit:
3494
3495         NOTHING;
3496     }
3497
3498     return ntStatus;
3499 }
3500
3501 NTSTATUS
3502 AFSValidateDirectoryCache( IN AFSObjectInfoCB *ObjectInfo,
3503                            IN GUID *AuthGroup)
3504 {
3505
3506     NTSTATUS ntStatus = STATUS_SUCCESS;
3507     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3508     BOOLEAN  bAcquiredLock = FALSE;
3509     AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
3510
3511     __Enter
3512     {
3513
3514         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3515                       AFS_TRACE_LEVEL_VERBOSE,
3516                       "AFSValidateDirectoryCache Validating content for FID %08lX-%08lX-%08lX-%08lX\n",
3517                       ObjectInfo->FileId.Cell,
3518                       ObjectInfo->FileId.Volume,
3519                       ObjectInfo->FileId.Vnode,
3520                       ObjectInfo->FileId.Unique));
3521
3522         if( !ExIsResourceAcquiredLite( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock))
3523         {
3524
3525             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3526                           AFS_TRACE_LEVEL_VERBOSE,
3527                           "AFSValidateDirectoryCache Acquiring DirectoryNodeHdr.TreeLock lock %p EXCL %08lX\n",
3528                           ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3529                           PsGetCurrentThread()));
3530
3531             AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3532                             TRUE);
3533
3534             bAcquiredLock = TRUE;
3535         }
3536
3537         //
3538         // Check for inconsistency between DirectoryNodeList and DirectoryNodeCount
3539         //
3540
3541         if ( ObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL &&
3542              ObjectInfo->Specific.Directory.DirectoryNodeCount > 0)
3543         {
3544
3545             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3546                           AFS_TRACE_LEVEL_ERROR,
3547                           "AFSValidateDirectoryCache Empty Node List but Non-Zero Node Count %d for dir FID %08lX-%08lX-%08lX-%08lX\n",
3548                           ObjectInfo->Specific.Directory.DirectoryNodeCount,
3549                           ObjectInfo->FileId.Cell,
3550                           ObjectInfo->FileId.Volume,
3551                           ObjectInfo->FileId.Vnode,
3552                           ObjectInfo->FileId.Unique));
3553         }
3554
3555         //
3556         // Reset the directory list information by clearing all valid entries
3557         //
3558
3559         pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3560
3561         while( pCurrentDirEntry != NULL)
3562         {
3563
3564             pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3565
3566             if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
3567             {
3568
3569                 //
3570                 // If this entry has been deleted then process it here
3571                 //
3572
3573                 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
3574                     pCurrentDirEntry->DirOpenReferenceCount <= 0 &&
3575                     pCurrentDirEntry->NameArrayReferenceCount <= 0)
3576                 {
3577
3578                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3579                                   AFS_TRACE_LEVEL_VERBOSE,
3580                                   "AFSValidateDirectoryCache Deleting dir entry %p name %wZ\n",
3581                                   pCurrentDirEntry,
3582                                   &pCurrentDirEntry->NameInformation.FileName));
3583
3584                     AFSDeleteDirEntry( ObjectInfo,
3585                                        &pCurrentDirEntry);
3586                 }
3587                 else
3588                 {
3589
3590                     ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID);
3591
3592                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3593                                   AFS_TRACE_LEVEL_VERBOSE,
3594                                   "AFSValidateDirectoryCache Clear VALID flag on DE %p Reference count %d\n",
3595                                   pCurrentDirEntry,
3596                                   pCurrentDirEntry->DirOpenReferenceCount));
3597
3598                     //
3599                     // We pull the short name from the parent tree since it could change below
3600                     //
3601
3602                     if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
3603                     {
3604
3605                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3606                                       AFS_TRACE_LEVEL_VERBOSE,
3607                                       "AFSValidateDirectoryCache Removing DE %p (%08lX) from shortname tree for %wZ\n",
3608                                       pCurrentDirEntry,
3609                                       pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3610                                       &pCurrentDirEntry->NameInformation.FileName));
3611
3612                         AFSRemoveShortNameDirEntry( &ObjectInfo->Specific.Directory.ShortNameTree,
3613                                                     pCurrentDirEntry);
3614
3615                         ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3616                     }
3617                 }
3618             }
3619
3620             pCurrentDirEntry = pNextDirEntry;
3621         }
3622
3623         //
3624         // Reget the directory contents
3625         //
3626
3627         ntStatus = AFSVerifyDirectoryContent( ObjectInfo,
3628                                               AuthGroup);
3629
3630         if ( !NT_SUCCESS( ntStatus))
3631         {
3632             try_return( ntStatus);
3633         }
3634
3635         //
3636         // Now start again and tear down any entries not valid
3637         //
3638
3639         pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3640
3641         while( pCurrentDirEntry != NULL)
3642         {
3643
3644             pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3645
3646             if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID))
3647             {
3648
3649                 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3650                     !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME) &&
3651                     pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex > 0)
3652                 {
3653
3654                     if( ObjectInfo->Specific.Directory.ShortNameTree == NULL)
3655                     {
3656
3657                         ObjectInfo->Specific.Directory.ShortNameTree = pCurrentDirEntry;
3658
3659                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3660                                       AFS_TRACE_LEVEL_VERBOSE,
3661                                       "AFSValidateDirectoryCache Insert DE %p to head of shortname tree for %wZ\n",
3662                                       pCurrentDirEntry,
3663                                       &pCurrentDirEntry->NameInformation.FileName));
3664
3665                         SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3666                     }
3667                     else
3668                     {
3669
3670                         if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfo->Specific.Directory.ShortNameTree,
3671                                                                      pCurrentDirEntry)))
3672                         {
3673                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3674                                           AFS_TRACE_LEVEL_VERBOSE,
3675                                           "AFSValidateDirectoryCache Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
3676                                           pCurrentDirEntry,
3677                                           pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3678                                           &pCurrentDirEntry->NameInformation.FileName));
3679                         }
3680                         else
3681                         {
3682                             SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3683
3684                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3685                                           AFS_TRACE_LEVEL_VERBOSE,
3686                                           "AFSValidateDirectoryCache Insert DE %p to shortname tree for %wZ\n",
3687                                           pCurrentDirEntry,
3688                                           &pCurrentDirEntry->NameInformation.FileName));
3689                         }
3690                     }
3691                 }
3692
3693                 pCurrentDirEntry = pNextDirEntry;
3694
3695                 continue;
3696             }
3697
3698             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3699                           AFS_TRACE_LEVEL_VERBOSE,
3700                           "AFSValidateDirectoryCache Processing INVALID DE %p Reference count %d\n",
3701                           pCurrentDirEntry,
3702                           pCurrentDirEntry->DirOpenReferenceCount));
3703
3704             if( pCurrentDirEntry->DirOpenReferenceCount <= 0 &&
3705                 pCurrentDirEntry->NameArrayReferenceCount <= 0)
3706             {
3707
3708                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3709                               AFS_TRACE_LEVEL_VERBOSE,
3710                               "AFSValidateDirectoryCache Deleting dir entry %wZ from parent FID %08lX-%08lX-%08lX-%08lX\n",
3711                               &pCurrentDirEntry->NameInformation.FileName,
3712                               ObjectInfo->FileId.Cell,
3713                               ObjectInfo->FileId.Volume,
3714                               ObjectInfo->FileId.Vnode,
3715                               ObjectInfo->FileId.Unique));
3716
3717                 AFSDeleteDirEntry( ObjectInfo,
3718                                  &nb