f62347035abf3f052f5b4fb5abe26f13d0fef0f4
[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     BOOLEAN bAllocatedObjectCB = FALSE;
1006     ULONGLONG ullIndex = 0;
1007     AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
1008     LONG lCount;
1009
1010     __Enter
1011     {
1012
1013         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1014                       AFS_TRACE_LEVEL_VERBOSE,
1015                       "AFSInitDirEntry Initializing entry %wZ parent FID %08lX-%08lX-%08lX-%08lX\n",
1016                       FileName,
1017                       ParentObjectInfo->FileId.Cell,
1018                       ParentObjectInfo->FileId.Volume,
1019                       ParentObjectInfo->FileId.Vnode,
1020                       ParentObjectInfo->FileId.Unique));
1021
1022         //
1023         // First thing is to locate/create our object information block
1024         // for this entry
1025         //
1026
1027         AFSAcquireExcl( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
1028                         TRUE);
1029
1030         ullIndex = AFSCreateLowIndex( &DirEnumEntry->FileId);
1031
1032         ntStatus = AFSLocateHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
1033                                        ullIndex,
1034                                        (AFSBTreeEntry **)&pObjectInfoCB);
1035
1036         if( !NT_SUCCESS( ntStatus) ||
1037             pObjectInfoCB == NULL)
1038         {
1039
1040             //
1041             // Allocate our object info cb
1042             //
1043
1044             pObjectInfoCB = AFSAllocateObjectInfo( ParentObjectInfo,
1045                                                    ullIndex);
1046
1047             if( pObjectInfoCB == NULL)
1048             {
1049
1050                 AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
1051
1052                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1053             }
1054
1055             bAllocatedObjectCB = TRUE;
1056
1057             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1058                           AFS_TRACE_LEVEL_VERBOSE,
1059                           "AFSInitDirEntry initialized object %p Parent Object %p for %wZ\n",
1060                           pObjectInfoCB,
1061                           ParentObjectInfo,
1062                           FileName));
1063         }
1064
1065         lCount = AFSObjectInfoIncrement( pObjectInfoCB,
1066                                          AFS_OBJECT_REFERENCE_DIRENTRY);
1067
1068         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1069                       AFS_TRACE_LEVEL_VERBOSE,
1070                       "AFSInitDirEntry Increment count on object %p Cnt %d\n",
1071                       pObjectInfoCB,
1072                       lCount));
1073
1074         AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
1075
1076         ntStatus = STATUS_SUCCESS;
1077
1078         ulEntryLength = sizeof( AFSDirectoryCB) +
1079                                      FileName->Length;
1080
1081         if( TargetName != NULL)
1082         {
1083
1084             ulEntryLength += TargetName->Length;
1085         }
1086
1087         pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
1088                                                                ulEntryLength,
1089                                                                AFS_DIR_ENTRY_TAG);
1090
1091         if( pDirNode == NULL)
1092         {
1093
1094             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1095         }
1096
1097         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1098                       AFS_TRACE_LEVEL_VERBOSE,
1099                       "AFSInitDirEntry AFS_DIR_ENTRY_TAG allocated %p\n",
1100                       pDirNode));
1101
1102         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
1103                                                                                 sizeof( AFSNonPagedDirectoryCB),
1104                                                                                 AFS_DIR_ENTRY_NP_TAG);
1105
1106         if( pNonPagedDirEntry == NULL)
1107         {
1108
1109             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1110         }
1111
1112         RtlZeroMemory( pDirNode,
1113                        ulEntryLength);
1114
1115         RtlZeroMemory( pNonPagedDirEntry,
1116                        sizeof( AFSNonPagedDirectoryCB));
1117
1118         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
1119
1120         pDirNode->NonPaged = pNonPagedDirEntry;
1121
1122         pDirNode->ObjectInformation = pObjectInfoCB;
1123
1124         //
1125         // Set valid entry and NOT_IN_PARENT flag
1126         //
1127
1128         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1129
1130         pDirNode->FileIndex = FileIndex;
1131
1132         //
1133         // Setup the names in the entry
1134         //
1135
1136         if( FileName->Length > 0)
1137         {
1138
1139             pDirNode->NameInformation.FileName.Length = FileName->Length;
1140
1141             pDirNode->NameInformation.FileName.MaximumLength = FileName->Length;
1142
1143             pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
1144
1145             RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
1146                            FileName->Buffer,
1147                            pDirNode->NameInformation.FileName.Length);
1148
1149             //
1150             // Create a CRC for the file
1151             //
1152
1153             pDirNode->CaseSensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1154                                                                          FALSE);
1155
1156             pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1157                                                                            TRUE);
1158         }
1159
1160         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1161                       AFS_TRACE_LEVEL_VERBOSE,
1162                       "AFSInitDirEntry Initialized DE %p for %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1163                       pDirNode,
1164                       FileName,
1165                       ParentObjectInfo->FileId.Cell,
1166                       ParentObjectInfo->FileId.Volume,
1167                       ParentObjectInfo->FileId.Vnode,
1168                       ParentObjectInfo->FileId.Unique));
1169
1170         if( TargetName != NULL &&
1171             TargetName->Length > 0)
1172         {
1173
1174             pDirNode->NameInformation.TargetName.Length = TargetName->Length;
1175
1176             pDirNode->NameInformation.TargetName.MaximumLength = pDirNode->NameInformation.TargetName.Length;
1177
1178             pDirNode->NameInformation.TargetName.Buffer = (WCHAR *)((char *)pDirNode +
1179                                                                             sizeof( AFSDirectoryCB) +
1180                                                                             pDirNode->NameInformation.FileName.Length);
1181
1182             RtlCopyMemory( pDirNode->NameInformation.TargetName.Buffer,
1183                            TargetName->Buffer,
1184                            pDirNode->NameInformation.TargetName.Length);
1185         }
1186
1187         //
1188         // If we allocated the object information cb then update the information
1189         //
1190
1191         if( bAllocatedObjectCB)
1192         {
1193
1194             //
1195             // Populate the rest of the data
1196             //
1197
1198             pObjectInfoCB->FileId = DirEnumEntry->FileId;
1199
1200             pObjectInfoCB->TargetFileId = DirEnumEntry->TargetFileId;
1201
1202             pObjectInfoCB->FileType = DirEnumEntry->FileType;
1203
1204             pObjectInfoCB->CreationTime = DirEnumEntry->CreationTime;
1205
1206             pObjectInfoCB->LastAccessTime = DirEnumEntry->LastAccessTime;
1207
1208             pObjectInfoCB->LastWriteTime = DirEnumEntry->LastWriteTime;
1209
1210             pObjectInfoCB->ChangeTime = DirEnumEntry->ChangeTime;
1211
1212             pObjectInfoCB->EndOfFile = DirEnumEntry->EndOfFile;
1213
1214             pObjectInfoCB->AllocationSize = DirEnumEntry->AllocationSize;
1215
1216             pObjectInfoCB->FileAttributes = DirEnumEntry->FileAttributes;
1217
1218             if( pObjectInfoCB->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1219                 pObjectInfoCB->FileType == AFS_FILE_TYPE_DFSLINK)
1220             {
1221
1222                 pObjectInfoCB->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1223             }
1224
1225             if (pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK)
1226             {
1227
1228                 if ( pObjectInfoCB->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1229                 {
1230
1231                     pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1232                 }
1233                 else
1234                 {
1235
1236                     pObjectInfoCB->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1237                 }
1238             }
1239
1240             pObjectInfoCB->EaSize = DirEnumEntry->EaSize;
1241
1242             //
1243             // Check for the case where we have a filetype of SymLink but both the TargetFid and the
1244             // TargetName are empty. In this case set the filetype to zero so we evaluate it later in
1245             // the code
1246             //
1247
1248             if( pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK &&
1249                 pObjectInfoCB->TargetFileId.Vnode == 0 &&
1250                 pObjectInfoCB->TargetFileId.Unique == 0 &&
1251                 pDirNode->NameInformation.TargetName.Length == 0)
1252             {
1253
1254                 //
1255                 // This will ensure we perform a validation on the node
1256                 //
1257
1258                 pObjectInfoCB->FileType = AFS_FILE_TYPE_UNKNOWN;
1259             }
1260
1261             if( pObjectInfoCB->FileType == AFS_FILE_TYPE_UNKNOWN)
1262             {
1263
1264                 SetFlag( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
1265             }
1266         }
1267
1268         //
1269         // Object specific information
1270         //
1271
1272         pObjectInfoCB->Links = DirEnumEntry->Links;
1273
1274         pObjectInfoCB->Expiration = DirEnumEntry->Expiration;
1275
1276         pObjectInfoCB->DataVersion = DirEnumEntry->DataVersion;
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                 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
1312                                                  AFS_OBJECT_REFERENCE_DIRENTRY);
1313
1314                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1315                               AFS_TRACE_LEVEL_VERBOSE,
1316                               "AFSInitDirEntry Decrement count on object %p Cnt %d\n",
1317                               pObjectInfoCB,
1318                               lCount));
1319
1320                 if( bAllocatedObjectCB &&
1321                     lCount == 0)
1322                 {
1323
1324                     AFSDeleteObjectInfo( &pObjectInfoCB);
1325                 }
1326             }
1327         }
1328     }
1329
1330     return pDirNode;
1331 }
1332
1333 BOOLEAN
1334 AFSCheckForReadOnlyAccess( IN ACCESS_MASK DesiredAccess,
1335                            IN BOOLEAN DirectoryEntry)
1336 {
1337
1338     BOOLEAN bReturn = TRUE;
1339     ACCESS_MASK stAccessMask = 0;
1340
1341     //
1342     // Get rid of anything we don't know about
1343     //
1344
1345     DesiredAccess = (DesiredAccess   &
1346                           ( DELETE |
1347                             READ_CONTROL |
1348                             WRITE_OWNER |
1349                             WRITE_DAC |
1350                             SYNCHRONIZE |
1351                             ACCESS_SYSTEM_SECURITY |
1352                             FILE_WRITE_DATA |
1353                             FILE_READ_EA |
1354                             FILE_WRITE_EA |
1355                             FILE_READ_ATTRIBUTES |
1356                             FILE_WRITE_ATTRIBUTES |
1357                             FILE_LIST_DIRECTORY |
1358                             FILE_TRAVERSE |
1359                             FILE_DELETE_CHILD |
1360                             FILE_APPEND_DATA));
1361
1362     //
1363     // Our 'read only' access mask. These are the accesses we will
1364     // allow for a read only file
1365     //
1366
1367     stAccessMask = DELETE |
1368                         READ_CONTROL |
1369                         WRITE_OWNER |
1370                         WRITE_DAC |
1371                         SYNCHRONIZE |
1372                         ACCESS_SYSTEM_SECURITY |
1373                         FILE_READ_DATA |
1374                         FILE_READ_EA |
1375                         FILE_WRITE_EA |
1376                         FILE_READ_ATTRIBUTES |
1377                         FILE_WRITE_ATTRIBUTES |
1378                         FILE_EXECUTE |
1379                         FILE_LIST_DIRECTORY |
1380                         FILE_TRAVERSE;
1381
1382     //
1383     // For a directory, add in the directory specific accesses
1384     //
1385
1386     if( DirectoryEntry)
1387     {
1388
1389         stAccessMask |= FILE_ADD_SUBDIRECTORY |
1390                                 FILE_ADD_FILE |
1391                                 FILE_DELETE_CHILD;
1392     }
1393
1394     if( FlagOn( DesiredAccess, ~stAccessMask))
1395     {
1396
1397         //
1398         // A write access is set ...
1399         //
1400
1401         bReturn = FALSE;
1402     }
1403
1404     return bReturn;
1405 }
1406
1407 NTSTATUS
1408 AFSEvaluateNode( IN GUID *AuthGroup,
1409                  IN AFSDirectoryCB *DirEntry)
1410 {
1411
1412     NTSTATUS ntStatus = STATUS_SUCCESS;
1413     AFSDirEnumEntry *pDirEntry = NULL;
1414     UNICODE_STRING uniTargetName;
1415
1416     __Enter
1417     {
1418
1419         ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1420                                           AuthGroup,
1421                                           FALSE,
1422                                           &pDirEntry);
1423
1424         if( !NT_SUCCESS( ntStatus))
1425         {
1426
1427             try_return( ntStatus);
1428         }
1429
1430         DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1431
1432         DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1433
1434         DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1435
1436         DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1437
1438         DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1439
1440         DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1441
1442         DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1443
1444         DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1445
1446         DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1447
1448         DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1449
1450         DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1451
1452         if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1453             pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1454         {
1455
1456             DirEntry->ObjectInformation->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1457         }
1458
1459         if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK)
1460         {
1461
1462             if ( DirEntry->ObjectInformation->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1463             {
1464
1465                 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1466             }
1467             else
1468             {
1469
1470                 DirEntry->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1471             }
1472         }
1473
1474         DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1475
1476         DirEntry->ObjectInformation->Links = pDirEntry->Links;
1477
1478         //
1479         // If we have a target name then see if it needs updating ...
1480         //
1481
1482         if( pDirEntry->TargetNameLength > 0)
1483         {
1484
1485             //
1486             // Update the target name information if needed
1487             //
1488
1489             uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1490
1491             uniTargetName.MaximumLength = uniTargetName.Length;
1492
1493             uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1494
1495             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1496                             TRUE);
1497
1498             if( DirEntry->NameInformation.TargetName.Length == 0 ||
1499                 RtlCompareUnicodeString( &uniTargetName,
1500                                          &DirEntry->NameInformation.TargetName,
1501                                          TRUE) != 0)
1502             {
1503
1504                 //
1505                 // Update the target name
1506                 //
1507
1508                 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1509                                                 &DirEntry->Flags,
1510                                                 uniTargetName.Buffer,
1511                                                 uniTargetName.Length);
1512
1513                 if( !NT_SUCCESS( ntStatus))
1514                 {
1515
1516                     AFSReleaseResource( &DirEntry->NonPaged->Lock);
1517
1518                     try_return( ntStatus);
1519                 }
1520             }
1521
1522             AFSReleaseResource( &DirEntry->NonPaged->Lock);
1523         }
1524
1525 try_exit:
1526
1527         if( pDirEntry != NULL)
1528         {
1529
1530             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
1531         }
1532     }
1533
1534     return ntStatus;
1535 }
1536
1537 NTSTATUS
1538 AFSValidateSymLink( IN GUID *AuthGroup,
1539                     IN AFSDirectoryCB *DirEntry)
1540 {
1541
1542     NTSTATUS ntStatus = STATUS_SUCCESS;
1543     AFSDirEnumEntry *pDirEntry = NULL;
1544     UNICODE_STRING uniTargetName;
1545
1546     __Enter
1547     {
1548
1549         ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1550                                           AuthGroup,
1551                                           FALSE,
1552                                           &pDirEntry);
1553
1554         if( !NT_SUCCESS( ntStatus))
1555         {
1556
1557             try_return( ntStatus);
1558         }
1559
1560         if( pDirEntry->FileType == AFS_FILE_TYPE_UNKNOWN ||
1561             pDirEntry->FileType == AFS_FILE_TYPE_INVALID)
1562         {
1563
1564             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1565                           AFS_TRACE_LEVEL_VERBOSE_2,
1566                           "AFSValidateSymLink Invalid type Status %08lX\n",
1567                           STATUS_OBJECT_NAME_NOT_FOUND));
1568
1569             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
1570         }
1571
1572         DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1573
1574         DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1575
1576         DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1577
1578         //
1579         // Update the target name information if needed
1580         //
1581
1582         uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1583
1584         uniTargetName.MaximumLength = uniTargetName.Length;
1585
1586         uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1587
1588         if( uniTargetName.Length > 0)
1589         {
1590
1591             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1592                             TRUE);
1593
1594             if( DirEntry->NameInformation.TargetName.Length == 0 ||
1595                 RtlCompareUnicodeString( &uniTargetName,
1596                                          &DirEntry->NameInformation.TargetName,
1597                                          TRUE) != 0)
1598             {
1599
1600                 //
1601                 // Update the target name
1602                 //
1603
1604                 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1605                                                 &DirEntry->Flags,
1606                                                 uniTargetName.Buffer,
1607                                                 uniTargetName.Length);
1608
1609                 if( !NT_SUCCESS( ntStatus))
1610                 {
1611
1612                     AFSReleaseResource( &DirEntry->NonPaged->Lock);
1613
1614                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1615                 }
1616             }
1617
1618             AFSReleaseResource( &DirEntry->NonPaged->Lock);
1619         }
1620
1621         //
1622         // If the FileType is the same then nothing to do since it IS
1623         // a SymLink
1624         //
1625
1626         if( pDirEntry->FileType == DirEntry->ObjectInformation->FileType)
1627         {
1628
1629             ASSERT( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK);
1630
1631             try_return( ntStatus = STATUS_SUCCESS);
1632         }
1633
1634         DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1635
1636         DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1637
1638         DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1639
1640         DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1641
1642         DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1643
1644         DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1645
1646         DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1647
1648         DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1649
1650         if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1651             pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1652         {
1653
1654             DirEntry->ObjectInformation->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1655         }
1656
1657         if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK)
1658         {
1659
1660             if ( DirEntry->ObjectInformation->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1661             {
1662
1663                 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1664             }
1665             else
1666             {
1667
1668                 DirEntry->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1669             }
1670         }
1671
1672         DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1673
1674         DirEntry->ObjectInformation->Links = pDirEntry->Links;
1675
1676 try_exit:
1677
1678         if( pDirEntry != NULL)
1679         {
1680
1681             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
1682         }
1683     }
1684
1685     return ntStatus;
1686 }
1687
1688 NTSTATUS
1689 AFSInvalidateObject( IN OUT AFSObjectInfoCB **ppObjectInfo,
1690                      IN     ULONG Reason)
1691 {
1692
1693     NTSTATUS ntStatus = STATUS_SUCCESS;
1694     IO_STATUS_BLOCK stIoStatus;
1695     ULONG ulFilter = 0;
1696     AFSObjectInfoCB * pParentObjectInfo = NULL;
1697
1698     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1699                   AFS_TRACE_LEVEL_VERBOSE,
1700                   "AFSInvalidateObject Invalidation on node type %d for fid %08lX-%08lX-%08lX-%08lX Reason %d\n",
1701                   (*ppObjectInfo)->FileType,
1702                   (*ppObjectInfo)->FileId.Cell,
1703                   (*ppObjectInfo)->FileId.Volume,
1704                   (*ppObjectInfo)->FileId.Vnode,
1705                   (*ppObjectInfo)->FileId.Unique,
1706                   Reason));
1707
1708     if ( BooleanFlagOn( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1709     {
1710
1711         pParentObjectInfo = AFSFindObjectInfo( (*ppObjectInfo)->VolumeCB,
1712                                                &(*ppObjectInfo)->ParentFileId);
1713     }
1714
1715     if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_SYMLINK ||
1716         (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DFSLINK ||
1717         (*ppObjectInfo)->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1718     {
1719         //
1720         // We only act on the mount point itself, not the target. If the
1721         // node has been deleted then mark it as such otherwise indicate
1722         // it requires verification
1723         //
1724
1725         if( Reason == AFS_INVALIDATE_DELETED)
1726         {
1727             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
1728         }
1729         else
1730         {
1731
1732             if( Reason == AFS_INVALIDATE_FLUSHED)
1733             {
1734
1735                 (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1736
1737                 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1738             }
1739
1740             (*ppObjectInfo)->Expiration.QuadPart = 0;
1741
1742             (*ppObjectInfo)->TargetFileId.Vnode = 0;
1743
1744             (*ppObjectInfo)->TargetFileId.Unique = 0;
1745
1746             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1747                           AFS_TRACE_LEVEL_VERBOSE,
1748                           "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1749                           (*ppObjectInfo)->FileId.Cell,
1750                           (*ppObjectInfo)->FileId.Volume,
1751                           (*ppObjectInfo)->FileId.Vnode,
1752                           (*ppObjectInfo)->FileId.Unique));
1753
1754             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1755         }
1756
1757         if ( pParentObjectInfo != NULL)
1758         {
1759
1760             ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1761
1762             if( Reason == AFS_INVALIDATE_CREDS)
1763             {
1764                 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1765             }
1766
1767             if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1768                 Reason == AFS_INVALIDATE_FLUSHED)
1769             {
1770                 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1771             }
1772             else
1773             {
1774                 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1775             }
1776
1777             AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1778                                             NULL,
1779                                             ulFilter,
1780                                             FILE_ACTION_MODIFIED);
1781         }
1782
1783         try_return( ntStatus);
1784     }
1785
1786     //
1787     // Depending on the reason for invalidation then perform work on the node
1788     //
1789
1790     switch( Reason)
1791     {
1792
1793     case AFS_INVALIDATE_DELETED:
1794         {
1795
1796             //
1797             // Mark this node as invalid
1798             //
1799
1800             (*ppObjectInfo)->Links = 0;
1801
1802             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_DELETED);
1803
1804             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1805                           AFS_TRACE_LEVEL_VERBOSE,
1806                           "AFSInvalidateObject Set DELETE flag on fid %08lX-%08lX-%08lX-%08lX\n",
1807                           (*ppObjectInfo)->FileId.Cell,
1808                           (*ppObjectInfo)->FileId.Volume,
1809                           (*ppObjectInfo)->FileId.Vnode,
1810                           (*ppObjectInfo)->FileId.Unique));
1811
1812             if( pParentObjectInfo != NULL)
1813             {
1814
1815                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1816                               AFS_TRACE_LEVEL_VERBOSE,
1817                               "AFSInvalidateObject Set VERIFY flag on parent fid %08lX-%08lX-%08lX-%08lX\n",
1818                               pParentObjectInfo->FileId.Cell,
1819                               pParentObjectInfo->FileId.Volume,
1820                               pParentObjectInfo->FileId.Vnode,
1821                               pParentObjectInfo->FileId.Unique));
1822
1823                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1824
1825                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1826
1827                 pParentObjectInfo->Expiration.QuadPart = 0;
1828
1829                 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1830                 {
1831                     ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1832                 }
1833                 else
1834                 {
1835                     ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1836                 }
1837
1838                 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1839                                                 NULL,
1840                                                 ulFilter,
1841                                                 FILE_ACTION_REMOVED);
1842             }
1843
1844             if( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1845                                                       Reason)))
1846             {
1847                 (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1848             }
1849
1850             break;
1851         }
1852
1853     case AFS_INVALIDATE_FLUSHED:
1854         {
1855
1856             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1857                 (*ppObjectInfo)->Fcb != NULL)
1858             {
1859
1860                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1861                               AFS_TRACE_LEVEL_VERBOSE,
1862                               "AFSInvalidateObject Flush/purge file fid %08lX-%08lX-%08lX-%08lX\n",
1863                               (*ppObjectInfo)->FileId.Cell,
1864                               (*ppObjectInfo)->FileId.Volume,
1865                               (*ppObjectInfo)->FileId.Vnode,
1866                               (*ppObjectInfo)->FileId.Unique));
1867
1868                 AFSAcquireExcl( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectResource,
1869                                 TRUE);
1870
1871                 __try
1872                 {
1873
1874                     CcFlushCache( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1875                                   NULL,
1876                                   0,
1877                                   &stIoStatus);
1878
1879                     if( !NT_SUCCESS( stIoStatus.Status))
1880                     {
1881
1882                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1883                                       AFS_TRACE_LEVEL_ERROR,
1884                                       "AFSInvalidateObject CcFlushCache failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1885                                       (*ppObjectInfo)->FileId.Cell,
1886                                       (*ppObjectInfo)->FileId.Volume,
1887                                       (*ppObjectInfo)->FileId.Vnode,
1888                                       (*ppObjectInfo)->FileId.Unique,
1889                                       stIoStatus.Status,
1890                                       stIoStatus.Information));
1891
1892                         ntStatus = stIoStatus.Status;
1893                     }
1894
1895
1896                     if ( (*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
1897                     {
1898
1899                         if ( !CcPurgeCacheSection( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1900                                                    NULL,
1901                                                    0,
1902                                                    FALSE))
1903                         {
1904
1905                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1906                                           AFS_TRACE_LEVEL_WARNING,
1907                                           "AFSInvalidateObject CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
1908                                           (*ppObjectInfo)->FileId.Cell,
1909                                           (*ppObjectInfo)->FileId.Volume,
1910                                           (*ppObjectInfo)->FileId.Vnode,
1911                                           (*ppObjectInfo)->FileId.Unique));
1912
1913                             SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1914                         }
1915                     }
1916                 }
1917                 __except( EXCEPTION_EXECUTE_HANDLER)
1918                 {
1919
1920                     ntStatus = GetExceptionCode();
1921
1922                     AFSDbgTrace(( 0,
1923                                   0,
1924                                   "EXCEPTION - AFSInvalidateObject Cc FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
1925                                   (*ppObjectInfo)->FileId.Cell,
1926                                   (*ppObjectInfo)->FileId.Volume,
1927                                   (*ppObjectInfo)->FileId.Vnode,
1928                                   (*ppObjectInfo)->FileId.Unique,
1929                                   ntStatus));
1930
1931                     SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1932                 }
1933
1934                 AFSReleaseResource( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectResource);
1935
1936                 //
1937                 // Clear out the extents
1938                 // Get rid of them (note this involves waiting
1939                 // for any writes or reads to the cache to complete)
1940                 //
1941
1942                 AFSTearDownFcbExtents( (*ppObjectInfo)->Fcb,
1943                                        NULL);
1944             }
1945
1946             (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1947
1948
1949             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE)
1950             {
1951
1952                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1953                               AFS_TRACE_LEVEL_VERBOSE,
1954                               "AFSInvalidateObject Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
1955                               (*ppObjectInfo)->FileId.Cell,
1956                               (*ppObjectInfo)->FileId.Volume,
1957                               (*ppObjectInfo)->FileId.Vnode,
1958                               (*ppObjectInfo)->FileId.Unique));
1959
1960                 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1961             }
1962
1963             // Fall through to the default processing
1964         }
1965
1966     default:
1967         {
1968
1969             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1970             {
1971                 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1972             }
1973             else
1974             {
1975                 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1976             }
1977
1978             if( Reason == AFS_INVALIDATE_CREDS)
1979             {
1980                 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1981             }
1982
1983             if( Reason == AFS_INVALIDATE_DATA_VERSION)
1984             {
1985                 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1986             }
1987             else
1988             {
1989                 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1990             }
1991
1992             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1993             {
1994
1995                 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo),
1996                                                 NULL,
1997                                                 ulFilter,
1998                                                 FILE_ACTION_MODIFIED);
1999             }
2000             else if ( pParentObjectInfo != NULL)
2001             {
2002
2003                 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
2004                                                 NULL,
2005                                                 ulFilter,
2006                                                 FILE_ACTION_MODIFIED);
2007             }
2008
2009             //
2010             // Indicate this node requires re-evaluation for the remaining reasons
2011             //
2012
2013             (*ppObjectInfo)->Expiration.QuadPart = 0;
2014
2015             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2016                           AFS_TRACE_LEVEL_VERBOSE,
2017                           "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
2018                           (*ppObjectInfo)->FileId.Cell,
2019                           (*ppObjectInfo)->FileId.Volume,
2020                           (*ppObjectInfo)->FileId.Vnode,
2021                           (*ppObjectInfo)->FileId.Unique));
2022
2023             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
2024
2025             if( Reason == AFS_INVALIDATE_DATA_VERSION ||
2026                 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
2027                 ( Reason == AFS_INVALIDATE_CALLBACK ||
2028                   Reason == AFS_INVALIDATE_EXPIRED))
2029             {
2030                 if ( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
2031                                                            AFS_INVALIDATE_DATA_VERSION)))
2032                 {
2033
2034                     (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
2035                 }
2036             }
2037
2038             break;
2039         }
2040     }
2041
2042   try_exit:
2043
2044     if ( pParentObjectInfo != NULL)
2045     {
2046
2047         AFSReleaseObjectInfo( &pParentObjectInfo);
2048     }
2049
2050     return ntStatus;
2051 }
2052
2053 NTSTATUS
2054 AFSInvalidateCache( IN AFSInvalidateCacheCB *InvalidateCB)
2055 {
2056
2057     NTSTATUS ntStatus = STATUS_SUCCESS;
2058     AFSVolumeCB *pVolumeCB = NULL;
2059     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2060     ULONGLONG   ullIndex = 0;
2061     AFSObjectInfoCB *pObjectInfo = NULL;
2062     LONG lCount;
2063
2064     __Enter
2065     {
2066
2067         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2068                       AFS_TRACE_LEVEL_VERBOSE,
2069                       "AFSInvalidateCache Invalidation FID %08lX-%08lX-%08lX-%08lX Type %d WholeVolume %d Reason %d\n",
2070                       InvalidateCB->FileID.Cell,
2071                       InvalidateCB->FileID.Volume,
2072                       InvalidateCB->FileID.Vnode,
2073                       InvalidateCB->FileID.Unique,
2074                       InvalidateCB->FileType,
2075                       InvalidateCB->WholeVolume,
2076                       InvalidateCB->Reason));
2077
2078         //
2079         // Need to locate the Fcb for the directory to purge
2080         //
2081
2082         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2083                       AFS_TRACE_LEVEL_VERBOSE,
2084                       "AFSInvalidateCache Acquiring RDR VolumeTreeLock lock %p SHARED %08lX\n",
2085                       &pDevExt->Specific.RDR.VolumeTreeLock,
2086                       PsGetCurrentThread()));
2087
2088         //
2089         // Starve any exclusive waiters on this paticular call
2090         //
2091
2092         AFSAcquireSharedStarveExclusive( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2093
2094         //
2095         // Locate the volume node
2096         //
2097
2098         ullIndex = AFSCreateHighIndex( &InvalidateCB->FileID);
2099
2100         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2101                                        ullIndex,
2102                                        (AFSBTreeEntry **)&pVolumeCB);
2103
2104         if( pVolumeCB != NULL)
2105         {
2106
2107             lCount = AFSVolumeIncrement( pVolumeCB,
2108                                          AFS_VOLUME_REFERENCE_INVALIDATE);
2109
2110             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2111                           AFS_TRACE_LEVEL_VERBOSE,
2112                           "AFSInvalidateCache Increment count on volume %p Cnt %d\n",
2113                           pVolumeCB,
2114                           lCount));
2115         }
2116
2117         AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2118
2119         if( !NT_SUCCESS( ntStatus) ||
2120             pVolumeCB == NULL)
2121         {
2122
2123             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2124                           AFS_TRACE_LEVEL_WARNING,
2125                           "AFSInvalidateCache Invalidation FAILURE Unable to locate volume node FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2126                           InvalidateCB->FileID.Cell,
2127                           InvalidateCB->FileID.Volume,
2128                           InvalidateCB->FileID.Vnode,
2129                           InvalidateCB->FileID.Unique,
2130                           ntStatus));
2131
2132             try_return( ntStatus = STATUS_SUCCESS);
2133         }
2134
2135         //
2136         // If this is a whole volume invalidation then go do it now
2137         //
2138
2139         if( InvalidateCB->WholeVolume)
2140         {
2141
2142             ntStatus = AFSInvalidateVolume( pVolumeCB,
2143                                             InvalidateCB->Reason);
2144
2145             try_return( ntStatus);
2146         }
2147
2148         AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2149                           TRUE);
2150
2151         if ( AFSIsVolumeFID( &InvalidateCB->FileID))
2152         {
2153
2154             pObjectInfo = &pVolumeCB->ObjectInformation;
2155         }
2156         else
2157         {
2158
2159             ullIndex = AFSCreateLowIndex( &InvalidateCB->FileID);
2160
2161             ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2162                                            ullIndex,
2163                                            (AFSBTreeEntry **)&pObjectInfo);
2164         }
2165
2166         if( pObjectInfo != NULL)
2167         {
2168
2169             //
2170             // Reference the node so it won't be torn down
2171             //
2172
2173             lCount = AFSObjectInfoIncrement( pObjectInfo,
2174                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2175
2176             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2177                           AFS_TRACE_LEVEL_VERBOSE,
2178                           "AFSInvalidateCache Increment count on object %p Cnt %d\n",
2179                           pObjectInfo,
2180                           lCount));
2181         }
2182
2183         AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2184
2185         if( !NT_SUCCESS( ntStatus) ||
2186             pObjectInfo == NULL)
2187         {
2188
2189             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2190                           AFS_TRACE_LEVEL_VERBOSE,
2191                           "AFSInvalidateCache Invalidation FAILURE Unable to locate object FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2192                           InvalidateCB->FileID.Cell,
2193                           InvalidateCB->FileID.Volume,
2194                           InvalidateCB->FileID.Vnode,
2195                           InvalidateCB->FileID.Unique,
2196                           ntStatus));
2197
2198             try_return( ntStatus = STATUS_SUCCESS);
2199         }
2200
2201         AFSInvalidateObject( &pObjectInfo,
2202                              InvalidateCB->Reason);
2203
2204 try_exit:
2205
2206         if( pObjectInfo != NULL)
2207         {
2208
2209             lCount = AFSObjectInfoDecrement( pObjectInfo,
2210                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2211
2212             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2213                           AFS_TRACE_LEVEL_VERBOSE,
2214                           "AFSInvalidateCache Decrement count on object %p Cnt %d\n",
2215                           pObjectInfo,
2216                           lCount));
2217         }
2218
2219         if ( pVolumeCB != NULL)
2220         {
2221
2222             lCount = AFSVolumeDecrement( pVolumeCB,
2223                                          AFS_VOLUME_REFERENCE_INVALIDATE);
2224
2225             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2226                           AFS_TRACE_LEVEL_VERBOSE,
2227                           "AFSInvalidateCache Decrement count on volume %p Cnt %d\n",
2228                           pVolumeCB,
2229                           lCount));
2230         }
2231     }
2232
2233     return ntStatus;
2234 }
2235
2236 BOOLEAN
2237 AFSIsChildOfParent( IN AFSFcb *Dcb,
2238                     IN AFSFcb *Fcb)
2239 {
2240
2241     BOOLEAN bIsChild = FALSE;
2242     AFSFcb *pCurrentFcb = Fcb;
2243     AFSObjectInfoCB * pParentObjectInfo = NULL;
2244
2245     while( pCurrentFcb != NULL)
2246     {
2247
2248         if( BooleanFlagOn( pCurrentFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
2249             AFSIsEqualFID( &pCurrentFcb->ObjectInformation->ParentFileId, &Dcb->ObjectInformation->FileId))
2250         {
2251
2252             bIsChild = TRUE;
2253
2254             break;
2255         }
2256
2257         pParentObjectInfo = AFSFindObjectInfo( pCurrentFcb->ObjectInformation->VolumeCB,
2258                                                &pCurrentFcb->ObjectInformation->ParentFileId);
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         //
2679         // Invalidate the volume root directory
2680         //
2681
2682         pCurrentObject = &VolumeCB->ObjectInformation;
2683
2684         if ( pCurrentObject )
2685         {
2686
2687             lCount = AFSObjectInfoIncrement( pCurrentObject,
2688                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2689
2690             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2691                           AFS_TRACE_LEVEL_VERBOSE,
2692                           "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2693                           pCurrentObject,
2694                           lCount));
2695
2696             AFSInvalidateObject( &pCurrentObject,
2697                                  Reason);
2698
2699             if ( pCurrentObject)
2700             {
2701
2702                 lCount = AFSObjectInfoDecrement( pCurrentObject,
2703                                                  AFS_OBJECT_REFERENCE_INVALIDATION);
2704
2705                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2706                               AFS_TRACE_LEVEL_VERBOSE,
2707                               "AFSInvalidateVolumeObjects Decrement count on object %p Cnt %d\n",
2708                               pCurrentObject,
2709                               lCount));
2710             }
2711         }
2712
2713         //
2714         // Apply invalidation to all other volume objects
2715         //
2716
2717         AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2718                           TRUE);
2719
2720         pCurrentObject = VolumeCB->ObjectInfoListHead;
2721
2722         if ( pCurrentObject)
2723         {
2724
2725             //
2726             // Reference the node so it won't be torn down
2727             //
2728
2729             lCount = AFSObjectInfoIncrement( pCurrentObject,
2730                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2731
2732             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2733                           AFS_TRACE_LEVEL_VERBOSE,
2734                           "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2735                           pCurrentObject,
2736                           lCount));
2737         }
2738
2739         while( pCurrentObject != NULL)
2740         {
2741
2742             pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2743
2744             if ( pNextObject)
2745             {
2746
2747                 //
2748                 // Reference the node so it won't be torn down
2749                 //
2750
2751                 lCount = AFSObjectInfoIncrement( pNextObject,
2752                                                  AFS_OBJECT_REFERENCE_INVALIDATION);
2753
2754                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2755                               AFS_TRACE_LEVEL_VERBOSE,
2756                               "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2757                               pNextObject,
2758                               lCount));
2759             }
2760
2761             AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2762
2763             AFSInvalidateObject( &pCurrentObject,
2764                                  Reason);
2765
2766             if ( pCurrentObject )
2767             {
2768
2769                 lCount = AFSObjectInfoDecrement( pCurrentObject,
2770                                                  AFS_OBJECT_REFERENCE_INVALIDATION);
2771
2772                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2773                               AFS_TRACE_LEVEL_VERBOSE,
2774                               "AFSInvalidateVolumeObjects Decrement count on object %p Cnt %d\n",
2775                               pCurrentObject,
2776                               lCount));
2777             }
2778
2779             AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2780                               TRUE);
2781
2782             pCurrentObject = pNextObject;
2783         }
2784
2785         AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2786     }
2787
2788     return ntStatus;
2789 }
2790
2791 VOID
2792 AFSInvalidateAllVolumes( VOID)
2793 {
2794     AFSVolumeCB *pVolumeCB = NULL;
2795     AFSVolumeCB *pNextVolumeCB = NULL;
2796     AFSDeviceExt *pRDRDeviceExt = NULL;
2797     LONG lCount;
2798
2799     pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2800
2801     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2802                   AFS_TRACE_LEVEL_VERBOSE,
2803                   "AFSInvalidateAllVolumes Acquiring RDR VolumeListLock lock %p SHARED %08lX\n",
2804                   &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2805                   PsGetCurrentThread()));
2806
2807     AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2808                       TRUE);
2809
2810     pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
2811
2812     if ( pVolumeCB)
2813     {
2814
2815         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2816                       AFS_TRACE_LEVEL_VERBOSE,
2817                       "AFSInvalidateAllVolumes Acquiring VolumeRoot ObjectInfoTree lock %p SHARED %08lX\n",
2818                       pVolumeCB->ObjectInfoTree.TreeLock,
2819                       PsGetCurrentThread()));
2820
2821         lCount = AFSVolumeIncrement( pVolumeCB,
2822                                      AFS_VOLUME_REFERENCE_INVALIDATE);
2823
2824         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2825                       AFS_TRACE_LEVEL_VERBOSE,
2826                       "AFSInvalidateAllVolumes Increment count on volume %p Cnt %d\n",
2827                       pVolumeCB,
2828                       lCount));
2829     }
2830
2831     while( pVolumeCB != NULL)
2832     {
2833
2834         pNextVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2835
2836         if ( pNextVolumeCB)
2837         {
2838
2839             lCount = AFSVolumeIncrement( pNextVolumeCB,
2840                                          AFS_VOLUME_REFERENCE_INVALIDATE);
2841
2842             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2843                           AFS_TRACE_LEVEL_VERBOSE,
2844                           "AFSInvalidateAllVolumes Increment count on volume %p Cnt %d\n",
2845                           pVolumeCB,
2846                           lCount));
2847         }
2848
2849         AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2850
2851         // do I need to hold the volume lock here?
2852
2853         AFSInvalidateVolume( pVolumeCB, AFS_INVALIDATE_EXPIRED);
2854
2855         AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2856                           TRUE);
2857
2858         lCount = AFSVolumeDecrement( pVolumeCB,
2859                                      AFS_VOLUME_REFERENCE_INVALIDATE);
2860
2861         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2862                       AFS_TRACE_LEVEL_VERBOSE,
2863                       "AFSInvalidateAllVolumes Decrement count on volume %p Cnt %d\n",
2864                       pVolumeCB,
2865                       lCount));
2866
2867         pVolumeCB = pNextVolumeCB;
2868     }
2869
2870     AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2871 }
2872
2873 NTSTATUS
2874 AFSVerifyEntry( IN GUID *AuthGroup,
2875                 IN AFSDirectoryCB *DirEntry)
2876 {
2877
2878     NTSTATUS ntStatus = STATUS_SUCCESS;
2879     AFSDirEnumEntry *pDirEnumEntry = NULL;
2880     AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
2881     IO_STATUS_BLOCK stIoStatus;
2882
2883     __Enter
2884     {
2885
2886         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2887                       AFS_TRACE_LEVEL_VERBOSE_2,
2888                       "AFSVerifyEntry Verifying entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2889                       &DirEntry->NameInformation.FileName,
2890                       pObjectInfo->FileId.Cell,
2891                       pObjectInfo->FileId.Volume,
2892                       pObjectInfo->FileId.Vnode,
2893                       pObjectInfo->FileId.Unique));
2894
2895         ntStatus = AFSEvaluateTargetByID( pObjectInfo,
2896                                           AuthGroup,
2897                                           FALSE,
2898                                           &pDirEnumEntry);
2899
2900         if( !NT_SUCCESS( ntStatus))
2901         {
2902
2903             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2904                           AFS_TRACE_LEVEL_ERROR,
2905                           "AFSVerifyEntry Evaluate Target failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2906                           &DirEntry->NameInformation.FileName,
2907                           pObjectInfo->FileId.Cell,
2908                           pObjectInfo->FileId.Volume,
2909                           pObjectInfo->FileId.Vnode,
2910                           pObjectInfo->FileId.Unique,
2911                           ntStatus));
2912
2913             try_return( ntStatus);
2914         }
2915
2916         //
2917         // Check the data version of the file
2918         //
2919
2920         if( pObjectInfo->DataVersion.QuadPart == pDirEnumEntry->DataVersion.QuadPart)
2921         {
2922             if ( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2923             {
2924
2925                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2926                               AFS_TRACE_LEVEL_VERBOSE,
2927                               "AFSVerifyEntry No DV change %I64X for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2928                               pObjectInfo->DataVersion.QuadPart,
2929                               &DirEntry->NameInformation.FileName,
2930                               pObjectInfo->FileId.Cell,
2931                               pObjectInfo->FileId.Volume,
2932                               pObjectInfo->FileId.Vnode,
2933                               pObjectInfo->FileId.Unique));
2934
2935                 //
2936                 // We are ok, just get out
2937                 //
2938
2939                 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2940
2941                 try_return( ntStatus = STATUS_SUCCESS);
2942             }
2943         }
2944
2945         //
2946         // New data version so we will need to process the node based on the type
2947         //
2948
2949         switch( pDirEnumEntry->FileType)
2950         {
2951
2952             case AFS_FILE_TYPE_MOUNTPOINT:
2953             {
2954
2955                 //
2956                 // For a mount point we need to ensure the target is the same
2957                 //
2958
2959                 if( !AFSIsEqualFID( &pObjectInfo->TargetFileId,
2960                                     &pDirEnumEntry->TargetFileId))
2961                 {
2962
2963                 }
2964
2965                 //
2966                 // Update the metadata for the entry
2967                 //
2968
2969                 ntStatus = AFSUpdateMetaData( DirEntry,
2970                                               pDirEnumEntry);
2971
2972                 if( NT_SUCCESS( ntStatus))
2973                 {
2974
2975                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2976                 }
2977
2978                 break;
2979             }
2980
2981             case AFS_FILE_TYPE_SYMLINK:
2982             {
2983
2984                 //
2985                 // Update the metadata for the entry
2986                 //
2987
2988                 ntStatus = AFSUpdateMetaData( DirEntry,
2989                                               pDirEnumEntry);
2990
2991                 if( NT_SUCCESS( ntStatus))
2992                 {
2993
2994                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2995                 }
2996
2997                 break;
2998             }
2999
3000             case AFS_FILE_TYPE_FILE:
3001             {
3002                 FILE_OBJECT * pCCFileObject = NULL;
3003                 BOOLEAN bPurgeExtents = FALSE;
3004
3005                 if ( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
3006                 {
3007
3008                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3009                                   AFS_TRACE_LEVEL_VERBOSE,
3010                                   "AFSVerifyEntry DV Change %wZ FID %08lX-%08lX-%08lX-%08lX (%08lX != %08lX)\n",
3011                                   &DirEntry->NameInformation.FileName,
3012                                   pObjectInfo->FileId.Cell,
3013                                   pObjectInfo->FileId.Volume,
3014                                   pObjectInfo->FileId.Vnode,
3015                                   pObjectInfo->FileId.Unique,
3016                                   pObjectInfo->DataVersion.LowPart,
3017                                   pDirEnumEntry->DataVersion.LowPart));
3018
3019                     bPurgeExtents = TRUE;
3020                 }
3021
3022                 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
3023                 {
3024
3025                     bPurgeExtents = TRUE;
3026
3027                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3028                                   AFS_TRACE_LEVEL_VERBOSE,
3029                                   "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3030                                   &DirEntry->NameInformation.FileName,
3031                                   pObjectInfo->FileId.Cell,
3032                                   pObjectInfo->FileId.Volume,
3033                                   pObjectInfo->FileId.Vnode,
3034                                   pObjectInfo->FileId.Unique));
3035
3036                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
3037                 }
3038
3039                 if( pObjectInfo->Fcb != NULL)
3040                 {
3041
3042                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3043                                   AFS_TRACE_LEVEL_VERBOSE,
3044                                   "AFSVerifyEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3045                                   &DirEntry->NameInformation.FileName,
3046                                   pObjectInfo->FileId.Cell,
3047                                   pObjectInfo->FileId.Volume,
3048                                   pObjectInfo->FileId.Vnode,
3049                                   pObjectInfo->FileId.Unique));
3050
3051                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3052                                     TRUE);
3053
3054                     __try
3055                     {
3056
3057                         CcFlushCache( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
3058                                       NULL,
3059                                       0,
3060                                       &stIoStatus);
3061
3062                         if( !NT_SUCCESS( stIoStatus.Status))
3063                         {
3064
3065                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
3066                                           AFS_TRACE_LEVEL_ERROR,
3067                                           "AFSVerifyEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
3068                                           &DirEntry->NameInformation.FileName,
3069                                           pObjectInfo->FileId.Cell,
3070                                           pObjectInfo->FileId.Volume,
3071                                           pObjectInfo->FileId.Vnode,
3072                                           pObjectInfo->FileId.Unique,
3073                                           stIoStatus.Status,
3074                                           stIoStatus.Information));
3075
3076                             ntStatus = stIoStatus.Status;
3077                         }
3078
3079                         if ( bPurgeExtents &&
3080                              pObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
3081                         {
3082
3083                             if ( !CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
3084                                                        NULL,
3085                                                        0,
3086                                                        FALSE))
3087                             {
3088
3089                                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
3090                                               AFS_TRACE_LEVEL_WARNING,
3091                                               "AFSVerifyEntry CcPurgeCacheSection failure %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3092                                               &DirEntry->NameInformation.FileName,
3093                                               pObjectInfo->FileId.Cell,
3094                                               pObjectInfo->FileId.Volume,
3095                                               pObjectInfo->FileId.Vnode,
3096                                               pObjectInfo->FileId.Unique));
3097
3098                                 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
3099                             }
3100                         }
3101                     }
3102                     __except( EXCEPTION_EXECUTE_HANDLER)
3103                     {
3104                         ntStatus = GetExceptionCode();
3105
3106                         AFSDbgTrace(( 0,
3107                                       0,
3108                                       "EXCEPTION - AFSVerifyEntry CcFlushCache or CcPurgeCacheSection %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
3109                                       &DirEntry->NameInformation.FileName,
3110                                       pObjectInfo->FileId.Cell,
3111                                       pObjectInfo->FileId.Volume,
3112                                       pObjectInfo->FileId.Vnode,
3113                                       pObjectInfo->FileId.Unique,
3114                                       ntStatus));
3115
3116                         SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
3117                     }
3118
3119                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
3120
3121                     if ( bPurgeExtents)
3122                     {
3123                         AFSFlushExtents( pObjectInfo->Fcb,
3124                                          AuthGroup);
3125                     }
3126
3127                     //
3128                     // Reacquire the Fcb to purge the cache
3129                     //
3130
3131                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3132                                   AFS_TRACE_LEVEL_VERBOSE,
3133                                   "AFSVerifyEntry Acquiring Fcb lock %p EXCL %08lX\n",
3134                                   &pObjectInfo->Fcb->NPFcb->Resource,
3135                                   PsGetCurrentThread()));
3136
3137                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
3138                                     TRUE);
3139
3140                     //
3141                     // Update the metadata for the entry
3142                     //
3143
3144                     ntStatus = AFSUpdateMetaData( DirEntry,
3145                                                   pDirEnumEntry);
3146
3147                     if( !NT_SUCCESS( ntStatus))
3148                     {
3149
3150                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3151                                       AFS_TRACE_LEVEL_ERROR,
3152                                       "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
3153                                       &DirEntry->NameInformation.FileName,
3154                                       pObjectInfo->FileId.Cell,
3155                                       pObjectInfo->FileId.Volume,
3156                                       pObjectInfo->FileId.Vnode,
3157                                       pObjectInfo->FileId.Unique,
3158                                       ntStatus));
3159
3160                         break;
3161                     }
3162
3163                     //
3164                     // Update file sizes
3165                     //
3166
3167                     pObjectInfo->Fcb->Header.AllocationSize.QuadPart  = pObjectInfo->AllocationSize.QuadPart;
3168                     pObjectInfo->Fcb->Header.FileSize.QuadPart        = pObjectInfo->EndOfFile.QuadPart;
3169                     pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
3170
3171                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3172                                   AFS_TRACE_LEVEL_VERBOSE,
3173                                   "AFSVerifyEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
3174                                   &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3175                                   PsGetCurrentThread()));
3176
3177                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3178                                     TRUE);
3179
3180                     pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
3181
3182                     if ( pCCFileObject != NULL)
3183                     {
3184                         CcSetFileSizes( pCCFileObject,
3185                                         (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
3186                     }
3187
3188                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3189                                   AFS_TRACE_LEVEL_VERBOSE,
3190                                   "AFSVerifyEntry Releasing Fcb SectionObject lock %p EXCL %08lX\n",
3191                                   &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3192                                   PsGetCurrentThread()));
3193
3194                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
3195
3196                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
3197                 }
3198                 else
3199                 {
3200
3201                     //
3202                     // Update the metadata for the entry
3203                     //
3204
3205                     ntStatus = AFSUpdateMetaData( DirEntry,
3206                                                   pDirEnumEntry);
3207
3208                     if( !NT_SUCCESS( ntStatus))
3209                     {
3210
3211                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3212                                       AFS_TRACE_LEVEL_ERROR,
3213                                       "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
3214                                       &DirEntry->NameInformation.FileName,
3215                                       pObjectInfo->FileId.Cell,
3216                                       pObjectInfo->FileId.Volume,
3217                                       pObjectInfo->FileId.Vnode,
3218                                       pObjectInfo->FileId.Unique,
3219                                       ntStatus));
3220
3221                         break;
3222                     }
3223
3224                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3225                                   AFS_TRACE_LEVEL_WARNING,
3226                                   "AFSVerifyEntry Fcb NULL %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3227                                   &DirEntry->NameInformation.FileName,
3228                                   pObjectInfo->FileId.Cell,
3229                                   pObjectInfo->FileId.Volume,
3230                                   pObjectInfo->FileId.Vnode,
3231                                   pObjectInfo->FileId.Unique));
3232                 }
3233
3234                 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3235
3236                 break;
3237             }
3238
3239             case AFS_FILE_TYPE_DIRECTORY:
3240             {
3241
3242                 //
3243                 // For a directory or root entry flush the content of
3244                 // the directory enumeration.
3245                 //
3246
3247                 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3248                 {
3249
3250                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3251                                   AFS_TRACE_LEVEL_VERBOSE_2,
3252                                   "AFSVerifyEntry Validating directory content for entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3253                                   &DirEntry->NameInformation.FileName,
3254                                   pObjectInfo->FileId.Cell,
3255                                   pObjectInfo->FileId.Volume,
3256                                   pObjectInfo->FileId.Vnode,
3257                                   pObjectInfo->FileId.Unique));
3258
3259                     AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3260                                     TRUE);
3261
3262                     ntStatus = AFSValidateDirectoryCache( pObjectInfo,
3263                                                           AuthGroup);
3264
3265                     AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3266
3267                     if ( !NT_SUCCESS( ntStatus))
3268                     {
3269
3270                         try_return( ntStatus);
3271                     }
3272                 }
3273
3274                 //
3275                 // Update the metadata for the entry
3276                 //
3277
3278                 ntStatus = AFSUpdateMetaData( DirEntry,
3279                                               pDirEnumEntry);
3280
3281                 if( NT_SUCCESS( ntStatus))
3282                 {
3283
3284                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3285                 }
3286
3287                 break;
3288             }
3289
3290             case AFS_FILE_TYPE_DFSLINK:
3291             {
3292
3293                 UNICODE_STRING uniTargetName;
3294
3295                 //
3296                 // For a DFS link need to check the target name has not changed
3297                 //
3298
3299                 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
3300
3301                 uniTargetName.MaximumLength = uniTargetName.Length;
3302
3303                 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
3304
3305                 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3306                                 TRUE);
3307
3308                 if( DirEntry->NameInformation.TargetName.Length == 0 ||
3309                     RtlCompareUnicodeString( &uniTargetName,
3310                                              &DirEntry->NameInformation.TargetName,
3311                                              TRUE) != 0)
3312                 {
3313
3314                     //
3315                     // Update the target name
3316                     //
3317
3318                     ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3319                                                     &DirEntry->Flags,
3320                                                     uniTargetName.Buffer,
3321                                                     uniTargetName.Length);
3322
3323                     if( !NT_SUCCESS( ntStatus))
3324                     {
3325
3326                         AFSReleaseResource( &DirEntry->NonPaged->Lock);
3327
3328                         break;
3329                     }
3330                 }
3331
3332                 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3333
3334                 //
3335                 // Update the metadata for the entry
3336                 //
3337
3338                 ntStatus = AFSUpdateMetaData( DirEntry,
3339                                               pDirEnumEntry);
3340
3341                 if( NT_SUCCESS( ntStatus))
3342                 {
3343
3344                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3345                 }
3346
3347                 break;
3348             }
3349
3350             default:
3351
3352                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3353                               AFS_TRACE_LEVEL_WARNING,
3354                               "AFSVerifyEntry Attempt to verify node of type %d %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3355                               pObjectInfo->FileType,
3356                               &DirEntry->NameInformation.FileName,
3357                               pObjectInfo->FileId.Cell,
3358                               pObjectInfo->FileId.Volume,
3359                               pObjectInfo->FileId.Vnode,
3360                               pObjectInfo->FileId.Unique));
3361
3362                 break;
3363         }
3364
3365  try_exit:
3366
3367         if( pDirEnumEntry != NULL)
3368         {
3369
3370             AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_2_TAG);
3371         }
3372     }
3373
3374     return ntStatus;
3375 }
3376
3377 NTSTATUS
3378 AFSSetVolumeState( IN AFSVolumeStatusCB *VolumeStatus)
3379 {
3380
3381     NTSTATUS ntStatus = STATUS_SUCCESS;
3382     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
3383     ULONGLONG   ullIndex = 0;
3384     AFSVolumeCB *pVolumeCB = NULL;
3385     LONG lCount;
3386
3387     __Enter
3388     {
3389
3390         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3391                       AFS_TRACE_LEVEL_VERBOSE,
3392                       "AFSSetVolumeState Marking volume state %d Volume Cell %08lX Volume %08lX\n",
3393                       VolumeStatus->Online,
3394                       VolumeStatus->FileID.Cell,
3395                       VolumeStatus->FileID.Volume));
3396
3397         //
3398         // Need to locate the Fcb for the directory to purge
3399         //
3400
3401         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3402                       AFS_TRACE_LEVEL_VERBOSE,
3403                       "AFSSetVolumeState Acquiring RDR VolumeTreeLock lock %p SHARED %08lX\n",
3404                       &pDevExt->Specific.RDR.VolumeTreeLock,
3405                       PsGetCurrentThread()));
3406
3407         AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
3408
3409         //
3410         // Locate the volume node
3411         //
3412
3413         ullIndex = AFSCreateHighIndex( &VolumeStatus->FileID);
3414
3415         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
3416                                        ullIndex,
3417                                        (AFSBTreeEntry **)&pVolumeCB);
3418
3419         if( pVolumeCB != NULL)
3420         {
3421
3422             lCount = AFSVolumeIncrement( pVolumeCB,
3423                                          AFS_VOLUME_REFERENCE_INVALIDATE);
3424
3425             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3426                           AFS_TRACE_LEVEL_VERBOSE,
3427                           "AFSSetVolumeState Increment count on volume %p Cnt %d\n",
3428                           pVolumeCB,
3429                           lCount));
3430
3431             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3432
3433             //
3434             // Set the volume state accordingly
3435             //
3436
3437             if( VolumeStatus->Online)
3438             {
3439
3440                 InterlockedAnd( (LONG *)&(pVolumeCB->Flags), ~AFS_VOLUME_FLAGS_OFFLINE);
3441             }
3442             else
3443             {
3444
3445                 InterlockedOr( (LONG *)&(pVolumeCB->Flags), AFS_VOLUME_FLAGS_OFFLINE);
3446             }
3447         }
3448     }
3449
3450     return ntStatus;
3451 }
3452
3453 NTSTATUS
3454 AFSSetNetworkState( IN AFSNetworkStatusCB *NetworkStatus)
3455 {
3456
3457     NTSTATUS ntStatus = STATUS_SUCCESS;
3458
3459     __Enter
3460     {
3461
3462         if( AFSGlobalRoot == NULL)
3463         {
3464
3465             try_return( ntStatus);
3466         }
3467
3468         AFSAcquireExcl( AFSGlobalRoot->VolumeLock,
3469                         TRUE);
3470
3471         //
3472         // Set the network state according to the information
3473         //
3474
3475         if( NetworkStatus->Online)
3476         {
3477
3478             ClearFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3479         }
3480         else
3481         {
3482
3483             SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3484         }
3485
3486         AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3487
3488 try_exit:
3489
3490         NOTHING;
3491     }
3492
3493     return ntStatus;
3494 }
3495
3496 NTSTATUS
3497 AFSValidateDirectoryCache( IN AFSObjectInfoCB *ObjectInfo,
3498                            IN GUID *AuthGroup)
3499 {
3500
3501     NTSTATUS ntStatus = STATUS_SUCCESS;
3502     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3503     BOOLEAN  bAcquiredLock = FALSE;
3504     AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
3505
3506     __Enter
3507     {
3508
3509         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3510                       AFS_TRACE_LEVEL_VERBOSE,
3511                       "AFSValidateDirectoryCache Validating content for FID %08lX-%08lX-%08lX-%08lX\n",
3512                       ObjectInfo->FileId.Cell,
3513                       ObjectInfo->FileId.Volume,
3514                       ObjectInfo->FileId.Vnode,
3515                       ObjectInfo->FileId.Unique));
3516
3517         if( !ExIsResourceAcquiredLite( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock))
3518         {
3519
3520             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3521                           AFS_TRACE_LEVEL_VERBOSE,
3522                           "AFSValidateDirectoryCache Acquiring DirectoryNodeHdr.TreeLock lock %p EXCL %08lX\n",
3523                           ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3524                           PsGetCurrentThread()));
3525
3526             AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3527                             TRUE);
3528
3529             bAcquiredLock = TRUE;
3530         }
3531
3532         //
3533         // Check for inconsistency between DirectoryNodeList and DirectoryNodeCount
3534         //
3535
3536         if ( ObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL &&
3537              ObjectInfo->Specific.Directory.DirectoryNodeCount > 0)
3538         {
3539
3540             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3541                           AFS_TRACE_LEVEL_ERROR,
3542                           "AFSValidateDirectoryCache Empty Node List but Non-Zero Node Count %d for dir FID %08lX-%08lX-%08lX-%08lX\n",
3543                           ObjectInfo->Specific.Directory.DirectoryNodeCount,
3544                           ObjectInfo->FileId.Cell,
3545                           ObjectInfo->FileId.Volume,
3546                           ObjectInfo->FileId.Vnode,
3547                           ObjectInfo->FileId.Unique));
3548         }
3549
3550         //
3551         // Reset the directory list information by clearing all valid entries
3552         //
3553
3554         pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3555
3556         while( pCurrentDirEntry != NULL)
3557         {
3558
3559             pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3560
3561             if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
3562             {
3563
3564                 //
3565                 // If this entry has been deleted then process it here
3566                 //
3567
3568                 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
3569                     pCurrentDirEntry->DirOpenReferenceCount <= 0 &&
3570                     pCurrentDirEntry->NameArrayReferenceCount <= 0)
3571                 {
3572
3573                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3574                                   AFS_TRACE_LEVEL_VERBOSE,
3575                                   "AFSValidateDirectoryCache Deleting dir entry %p name %wZ\n",
3576                                   pCurrentDirEntry,
3577                                   &pCurrentDirEntry->NameInformation.FileName));
3578
3579                     AFSDeleteDirEntry( ObjectInfo,
3580                                        pCurrentDirEntry);
3581                 }
3582                 else
3583                 {
3584
3585                     ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID);
3586
3587                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3588                                   AFS_TRACE_LEVEL_VERBOSE,
3589                                   "AFSValidateDirectoryCache Clear VALID flag on DE %p Reference count %d\n",
3590                                   pCurrentDirEntry,
3591                                   pCurrentDirEntry->DirOpenReferenceCount));
3592
3593                     //
3594                     // We pull the short name from the parent tree since it could change below
3595                     //
3596
3597                     if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
3598                     {
3599
3600                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3601                                       AFS_TRACE_LEVEL_VERBOSE,
3602                                       "AFSValidateDirectoryCache Removing DE %p (%08lX) from shortname tree for %wZ\n",
3603                                       pCurrentDirEntry,
3604                                       pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3605                                       &pCurrentDirEntry->NameInformation.FileName));
3606
3607                         AFSRemoveShortNameDirEntry( &ObjectInfo->Specific.Directory.ShortNameTree,
3608                                                     pCurrentDirEntry);
3609
3610                         ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3611                     }
3612                 }
3613             }
3614
3615             pCurrentDirEntry = pNextDirEntry;
3616         }
3617
3618         //
3619         // Reget the directory contents
3620         //
3621
3622         ntStatus = AFSVerifyDirectoryContent( ObjectInfo,
3623                                               AuthGroup);
3624
3625         if ( !NT_SUCCESS( ntStatus))
3626         {
3627             try_return( ntStatus);
3628         }
3629
3630         //
3631         // Now start again and tear down any entries not valid
3632         //
3633
3634         pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3635
3636         while( pCurrentDirEntry != NULL)
3637         {
3638
3639             pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3640
3641             if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID))
3642             {
3643
3644                 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3645                     !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME) &&
3646                     pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex > 0)
3647                 {
3648
3649                     if( ObjectInfo->Specific.Directory.ShortNameTree == NULL)
3650                     {
3651
3652                         ObjectInfo->Specific.Directory.ShortNameTree = pCurrentDirEntry;
3653
3654                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3655                                       AFS_TRACE_LEVEL_VERBOSE,
3656                                       "AFSValidateDirectoryCache Insert DE %p to head of shortname tree for %wZ\n",
3657                                       pCurrentDirEntry,
3658                                       &pCurrentDirEntry->NameInformation.FileName));
3659
3660                         SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3661                     }
3662                     else
3663                     {
3664
3665                         if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfo->Specific.Directory.ShortNameTree,
3666                                                                      pCurrentDirEntry)))
3667                         {
3668                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3669                                           AFS_TRACE_LEVEL_VERBOSE,
3670                                           "AFSValidateDirectoryCache Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
3671                                           pCurrentDirEntry,
3672                                           pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3673                                           &pCurrentDirEntry->NameInformation.FileName));
3674                         }
3675                         else
3676                         {
3677                             SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3678
3679                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3680                                           AFS_TRACE_LEVEL_VERBOSE,
3681                                           "AFSValidateDirectoryCache Insert DE %p to shortname tree for %wZ\n",
3682                                           pCurrentDirEntry,
3683                                           &pCurrentDirEntry->NameInformation.FileName));
3684                         }
3685                     }
3686                 }
3687
3688                 pCurrentDirEntry = pNextDirEntry;
3689
3690                 continue;
3691             }
3692
3693             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3694                           AFS_TRACE_LEVEL_VERBOSE,
3695                           "AFSValidateDirectoryCache Processing INVALID DE %p Reference count %d\n",
3696                           pCurrentDirEntry,
3697                           pCurrentDirEntry->DirOpenReferenceCount));
3698
3699             if( pCurrentDirEntry->DirOpenReferenceCount <= 0 &&
3700                 pCurrentDirEntry->NameArrayReferenceCount <= 0)
3701             {
3702
3703                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3704                               AFS_TRACE_LEVEL_VERBOSE,
3705                               "AFSValidateDirectoryCache Deleting dir entry %wZ from parent FID %08lX-%08lX-%08lX-%08lX\n",
3706                               &pCurrentDirEntry->NameInformation.FileName,
3707                               ObjectInfo->FileId.Cell,
3708                               ObjectInfo->FileId.Volume,
3709                               ObjectInfo->FileId.Vnode,
3710                               ObjectInfo->FileId.Unique));
3711
3712                 AFSDeleteDirEntry( ObjectInfo,
3713                                    pCurrentDirEntry);
3714             }
3715             else
3716             {
3717
3718                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3719                               AFS_TRACE_LEVEL_VERBOSE,
3720                               "AFSValidateDirectory