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