Windows: AFSTearDownExtents may experience active extents
[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 = InterlockedIncrement( &pObjectInfoCB->ObjectReferenceCount);
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 = InterlockedIncrement( &pObjectInfoCB->ObjectReferenceCount);
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 = InterlockedIncrement( &pObjectInfoCB->ObjectReferenceCount);
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                 AFSExFreePool( pNonPagedDirEntry);
1188             }
1189
1190             if( pDirNode != NULL)
1191             {
1192
1193                 AFSExFreePool( pDirNode);
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 = InterlockedDecrement( &pObjectInfoCB->ObjectReferenceCount);
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             AFSExFreePool( pDirEntry);
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             AFSExFreePool( pDirEntry);
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             AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
1847                                             NULL,
1848                                             ulFilter,
1849                                             FILE_ACTION_MODIFIED);
1850
1851             //
1852             // Indicate this node requires re-evaluation for the remaining reasons
1853             //
1854
1855             (*ppObjectInfo)->Expiration.QuadPart = 0;
1856
1857             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1858                           AFS_TRACE_LEVEL_VERBOSE,
1859                           "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1860                           (*ppObjectInfo)->FileId.Cell,
1861                           (*ppObjectInfo)->FileId.Volume,
1862                           (*ppObjectInfo)->FileId.Vnode,
1863                           (*ppObjectInfo)->FileId.Unique);
1864
1865             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1866
1867             if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1868                 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1869                 ( Reason == AFS_INVALIDATE_CALLBACK ||
1870                   Reason == AFS_INVALIDATE_EXPIRED))
1871             {
1872                 if ( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1873                                                            AFS_INVALIDATE_DATA_VERSION)))
1874                 {
1875
1876                     (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1877                 }
1878             }
1879
1880             break;
1881         }
1882     }
1883
1884   try_exit:
1885
1886     return ntStatus;
1887 }
1888
1889 NTSTATUS
1890 AFSInvalidateCache( IN AFSInvalidateCacheCB *InvalidateCB)
1891 {
1892
1893     NTSTATUS ntStatus = STATUS_SUCCESS;
1894     AFSFcb      *pDcb = NULL, *pFcb = NULL, *pNextFcb = NULL;
1895     AFSVolumeCB *pVolumeCB = NULL;
1896     AFSFcb      *pTargetDcb = NULL;
1897     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1898     AFSDirectoryCB *pCurrentDirEntry = NULL;
1899     BOOLEAN     bIsChild = FALSE;
1900     ULONGLONG   ullIndex = 0;
1901     AFSObjectInfoCB *pObjectInfo = NULL;
1902     LONG lCount;
1903
1904     __Enter
1905     {
1906
1907         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1908                       AFS_TRACE_LEVEL_VERBOSE,
1909                       "AFSInvalidateCache Invalidation FID %08lX-%08lX-%08lX-%08lX Type %d WholeVolume %d Reason %d\n",
1910                       InvalidateCB->FileID.Cell,
1911                       InvalidateCB->FileID.Volume,
1912                       InvalidateCB->FileID.Vnode,
1913                       InvalidateCB->FileID.Unique,
1914                       InvalidateCB->FileType,
1915                       InvalidateCB->WholeVolume,
1916                       InvalidateCB->Reason);
1917
1918         //
1919         // Need to locate the Fcb for the directory to purge
1920         //
1921
1922         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1923                       AFS_TRACE_LEVEL_VERBOSE,
1924                       "AFSInvalidateCache Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1925                       &pDevExt->Specific.RDR.VolumeTreeLock,
1926                       PsGetCurrentThread());
1927
1928         //
1929         // Starve any exclusive waiters on this paticular call
1930         //
1931
1932         AFSAcquireSharedStarveExclusive( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1933
1934         //
1935         // Locate the volume node
1936         //
1937
1938         ullIndex = AFSCreateHighIndex( &InvalidateCB->FileID);
1939
1940         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1941                                        ullIndex,
1942                                        (AFSBTreeEntry **)&pVolumeCB);
1943
1944         if( pVolumeCB != NULL)
1945         {
1946
1947             lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1948
1949             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1950                           AFS_TRACE_LEVEL_VERBOSE,
1951                           "AFSInvalidateCache Increment count on volume %08lX Cnt %d\n",
1952                           pVolumeCB,
1953                           lCount);
1954         }
1955
1956         AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1957
1958         if( !NT_SUCCESS( ntStatus) ||
1959             pVolumeCB == NULL)
1960         {
1961
1962             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1963                           AFS_TRACE_LEVEL_WARNING,
1964                           "AFSInvalidateCache Invalidation FAILURE Unable to locate volume node FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1965                           InvalidateCB->FileID.Cell,
1966                           InvalidateCB->FileID.Volume,
1967                           InvalidateCB->FileID.Vnode,
1968                           InvalidateCB->FileID.Unique,
1969                           ntStatus);
1970
1971             try_return( ntStatus = STATUS_SUCCESS);
1972         }
1973
1974         //
1975         // If this is a whole volume invalidation then go do it now
1976         //
1977
1978         if( InvalidateCB->WholeVolume)
1979         {
1980
1981             ntStatus = AFSInvalidateVolume( pVolumeCB,
1982                                             InvalidateCB->Reason);
1983
1984             lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1985
1986             try_return( ntStatus);
1987         }
1988
1989         AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1990                           TRUE);
1991
1992         if ( AFSIsVolumeFID( &InvalidateCB->FileID))
1993         {
1994
1995             pObjectInfo = &pVolumeCB->ObjectInformation;
1996         }
1997         else
1998         {
1999
2000             lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2001
2002             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2003                           AFS_TRACE_LEVEL_VERBOSE,
2004                           "AFSInvalidateCache Decrement count on volume %08lX Cnt %d\n",
2005                           pVolumeCB,
2006                           pVolumeCB->VolumeReferenceCount);
2007
2008             ullIndex = AFSCreateLowIndex( &InvalidateCB->FileID);
2009
2010             ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2011                                            ullIndex,
2012                                            (AFSBTreeEntry **)&pObjectInfo);
2013         }
2014
2015         if( pObjectInfo != NULL)
2016         {
2017
2018             //
2019             // Reference the node so it won't be torn down
2020             //
2021
2022             lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
2023
2024             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2025                           AFS_TRACE_LEVEL_VERBOSE,
2026                           "AFSInvalidateCache Increment count on object %08lX Cnt %d\n",
2027                           pObjectInfo,
2028                           lCount);
2029         }
2030
2031         AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2032
2033         if( !NT_SUCCESS( ntStatus) ||
2034             pObjectInfo == NULL)
2035         {
2036
2037             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2038                           AFS_TRACE_LEVEL_VERBOSE,
2039                           "AFSInvalidateCache Invalidation FAILURE Unable to locate object FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2040                           InvalidateCB->FileID.Cell,
2041                           InvalidateCB->FileID.Volume,
2042                           InvalidateCB->FileID.Vnode,
2043                           InvalidateCB->FileID.Unique,
2044                           ntStatus);
2045
2046             try_return( ntStatus = STATUS_SUCCESS);
2047         }
2048
2049         AFSInvalidateObject( &pObjectInfo,
2050                              InvalidateCB->Reason);
2051
2052 try_exit:
2053
2054         if( pObjectInfo != NULL)
2055         {
2056
2057             lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2058
2059             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2060                           AFS_TRACE_LEVEL_VERBOSE,
2061                           "AFSInvalidateCache Decrement count on object %08lX Cnt %d\n",
2062                           pObjectInfo,
2063                           lCount);
2064         }
2065     }
2066
2067     return ntStatus;
2068 }
2069
2070 BOOLEAN
2071 AFSIsChildOfParent( IN AFSFcb *Dcb,
2072                     IN AFSFcb *Fcb)
2073 {
2074
2075     BOOLEAN bIsChild = FALSE;
2076     AFSFcb *pCurrentFcb = Fcb;
2077
2078     while( pCurrentFcb != NULL)
2079     {
2080
2081         if( pCurrentFcb->ObjectInformation->ParentObjectInformation == Dcb->ObjectInformation)
2082         {
2083
2084             bIsChild = TRUE;
2085
2086             break;
2087         }
2088
2089         pCurrentFcb = pCurrentFcb->ObjectInformation->ParentObjectInformation->Fcb;
2090     }
2091
2092     return bIsChild;
2093 }
2094
2095 inline
2096 ULONGLONG
2097 AFSCreateHighIndex( IN AFSFileID *FileID)
2098 {
2099
2100     ULONGLONG ullIndex = 0;
2101
2102     ullIndex = (((ULONGLONG)FileID->Cell << 32) | FileID->Volume);
2103
2104     return ullIndex;
2105 }
2106
2107 inline
2108 ULONGLONG
2109 AFSCreateLowIndex( IN AFSFileID *FileID)
2110 {
2111
2112     ULONGLONG ullIndex = 0;
2113
2114     ullIndex = (((ULONGLONG)FileID->Vnode << 32) | FileID->Unique);
2115
2116     return ullIndex;
2117 }
2118
2119 BOOLEAN
2120 AFSCheckAccess( IN ACCESS_MASK DesiredAccess,
2121                 IN ACCESS_MASK GrantedAccess,
2122                 IN BOOLEAN DirectoryEntry)
2123 {
2124
2125     BOOLEAN bAccessGranted = TRUE;
2126
2127     //
2128     // Check if we are asking for read/write and granted only read only
2129     // NOTE: There will be more checks here
2130     //
2131
2132     if( !AFSCheckForReadOnlyAccess( DesiredAccess,
2133                                     DirectoryEntry) &&
2134         AFSCheckForReadOnlyAccess( GrantedAccess,
2135                                    DirectoryEntry))
2136     {
2137
2138         bAccessGranted = FALSE;
2139     }
2140
2141     return bAccessGranted;
2142 }
2143
2144 NTSTATUS
2145 AFSGetDriverStatus( IN AFSDriverStatusRespCB *DriverStatus)
2146 {
2147
2148     NTSTATUS         ntStatus = STATUS_SUCCESS;
2149     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2150
2151     //
2152     // Start with read
2153     //
2154
2155     DriverStatus->Status = AFS_DRIVER_STATUS_READY;
2156
2157     if( AFSGlobalRoot == NULL)
2158     {
2159
2160         //
2161         // We are not ready
2162         //
2163
2164         DriverStatus->Status = AFS_DRIVER_STATUS_NOT_READY;
2165     }
2166
2167     if( pControlDevExt->Specific.Control.CommServiceCB.IrpPoolControlFlag != POOL_ACTIVE)
2168     {
2169
2170         //
2171         // No service yet
2172         //
2173
2174         DriverStatus->Status = AFS_DRIVER_STATUS_NO_SERVICE;
2175     }
2176
2177     return ntStatus;
2178 }
2179
2180 NTSTATUS
2181 AFSSubstituteSysName( IN UNICODE_STRING *ComponentName,
2182                       IN UNICODE_STRING *SubstituteName,
2183                       IN ULONG StringIndex)
2184 {
2185
2186     NTSTATUS ntStatus = STATUS_SUCCESS;
2187     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2188     AFSSysNameCB    *pSysName = NULL;
2189     ERESOURCE       *pSysNameLock = NULL;
2190     ULONG            ulIndex = 1;
2191     USHORT           usIndex = 0;
2192     UNICODE_STRING   uniSysName;
2193
2194     __Enter
2195     {
2196
2197 #if defined(_WIN64)
2198
2199         if( IoIs32bitProcess( NULL))
2200         {
2201
2202             pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2203
2204             pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2205         }
2206         else
2207         {
2208
2209             pSysNameLock = &pControlDevExt->Specific.Control.SysName64ListLock;
2210
2211             pSysName = pControlDevExt->Specific.Control.SysName64ListHead;
2212         }
2213 #else
2214
2215         pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2216
2217         pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2218
2219 #endif
2220
2221         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2222                       AFS_TRACE_LEVEL_VERBOSE,
2223                       "AFSSubstituteSysName Acquiring SysName lock %08lX SHARED %08lX\n",
2224                       pSysNameLock,
2225                       PsGetCurrentThread());
2226
2227         AFSAcquireShared( pSysNameLock,
2228                           TRUE);
2229
2230         //
2231         // Find where we are in the list
2232         //
2233
2234         while( pSysName != NULL &&
2235             ulIndex < StringIndex)
2236         {
2237
2238             pSysName = pSysName->fLink;
2239
2240             ulIndex++;
2241         }
2242
2243         if( pSysName == NULL)
2244         {
2245
2246             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
2247         }
2248
2249         RtlInitUnicodeString( &uniSysName,
2250                               L"@SYS");
2251         //
2252         // If it is a full component of @SYS then just substitue the
2253         // name in
2254         //
2255
2256         if( RtlCompareUnicodeString( &uniSysName,
2257                                      ComponentName,
2258                                      TRUE) == 0)
2259         {
2260
2261             SubstituteName->Length = pSysName->SysName.Length;
2262             SubstituteName->MaximumLength = SubstituteName->Length;
2263
2264             SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2265                                                                         SubstituteName->Length,
2266                                                                         AFS_SUBST_BUFFER_TAG);
2267
2268             if( SubstituteName->Buffer == NULL)
2269             {
2270
2271                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2272             }
2273
2274             RtlCopyMemory( SubstituteName->Buffer,
2275                            pSysName->SysName.Buffer,
2276                            pSysName->SysName.Length);
2277         }
2278         else
2279         {
2280
2281             usIndex = 0;
2282
2283             while( ComponentName->Buffer[ usIndex] != L'@')
2284             {
2285
2286                 usIndex++;
2287             }
2288
2289             SubstituteName->Length = (usIndex * sizeof( WCHAR)) + pSysName->SysName.Length;
2290             SubstituteName->MaximumLength = SubstituteName->Length;
2291
2292             SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2293                                                                         SubstituteName->Length,
2294                                                                         AFS_SUBST_BUFFER_TAG);
2295
2296             if( SubstituteName->Buffer == NULL)
2297             {
2298
2299                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2300             }
2301
2302             RtlCopyMemory( SubstituteName->Buffer,
2303                            ComponentName->Buffer,
2304                            usIndex * sizeof( WCHAR));
2305
2306             RtlCopyMemory( &SubstituteName->Buffer[ usIndex],
2307                            pSysName->SysName.Buffer,
2308                            pSysName->SysName.Length);
2309         }
2310
2311 try_exit:
2312
2313         AFSReleaseResource( pSysNameLock);
2314     }
2315
2316     return ntStatus;
2317 }
2318
2319 NTSTATUS
2320 AFSSubstituteNameInPath( IN OUT UNICODE_STRING *FullPathName,
2321                          IN OUT UNICODE_STRING *ComponentName,
2322                          IN UNICODE_STRING *SubstituteName,
2323                          IN OUT UNICODE_STRING *RemainingPath,
2324                          IN BOOLEAN FreePathName)
2325 {
2326
2327     NTSTATUS ntStatus = STATUS_SUCCESS;
2328     UNICODE_STRING uniPathName;
2329     USHORT usPrefixNameLen = 0;
2330     SHORT  sNameLenDelta = 0;
2331
2332     __Enter
2333     {
2334
2335         //
2336         // If the passed in name can handle the additional length
2337         // then just moves things around
2338         //
2339
2340         sNameLenDelta = SubstituteName->Length - ComponentName->Length;
2341
2342         usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2343
2344         if( FullPathName->MaximumLength > FullPathName->Length + sNameLenDelta)
2345         {
2346
2347             if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2348             {
2349
2350                 RtlMoveMemory( &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + SubstituteName->Length)/sizeof( WCHAR))],
2351                                &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + ComponentName->Length)/sizeof( WCHAR))],
2352                                FullPathName->Length - usPrefixNameLen*sizeof( WCHAR) - ComponentName->Length);
2353             }
2354
2355             RtlCopyMemory( &FullPathName->Buffer[ usPrefixNameLen],
2356                            SubstituteName->Buffer,
2357                            SubstituteName->Length);
2358
2359             FullPathName->Length += sNameLenDelta;
2360
2361             ComponentName->Length += sNameLenDelta;
2362
2363             ComponentName->MaximumLength = ComponentName->Length;
2364
2365             if ( RemainingPath->Buffer)
2366             {
2367
2368                 RemainingPath->Buffer += sNameLenDelta/sizeof( WCHAR);
2369             }
2370
2371             try_return( ntStatus);
2372         }
2373
2374         //
2375         // Need to re-allocate the buffer
2376         //
2377
2378         uniPathName.Length = FullPathName->Length -
2379                                          ComponentName->Length +
2380                                          SubstituteName->Length;
2381
2382         uniPathName.MaximumLength = FullPathName->MaximumLength + PAGE_SIZE;
2383
2384         uniPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2385                                                                 uniPathName.MaximumLength,
2386                                                                 AFS_NAME_BUFFER_FOUR_TAG);
2387
2388         if( uniPathName.Buffer == NULL)
2389         {
2390
2391             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2392         }
2393
2394         usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2395
2396         usPrefixNameLen *= sizeof( WCHAR);
2397
2398         RtlZeroMemory( uniPathName.Buffer,
2399                        uniPathName.MaximumLength);
2400
2401         RtlCopyMemory( uniPathName.Buffer,
2402                        FullPathName->Buffer,
2403                        usPrefixNameLen);
2404
2405         RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen/sizeof( WCHAR))],
2406                        SubstituteName->Buffer,
2407                        SubstituteName->Length);
2408
2409         if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2410         {
2411
2412             RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen + SubstituteName->Length)/sizeof( WCHAR)],
2413                            &FullPathName->Buffer[ (usPrefixNameLen + ComponentName->Length)/sizeof( WCHAR)],
2414                            FullPathName->Length - usPrefixNameLen - ComponentName->Length);
2415         }
2416
2417         ComponentName->Buffer = uniPathName.Buffer + (ComponentName->Buffer - FullPathName->Buffer);
2418
2419         ComponentName->Length += sNameLenDelta;
2420
2421         ComponentName->MaximumLength = ComponentName->Length;
2422
2423         if ( RemainingPath->Buffer)
2424         {
2425
2426             RemainingPath->Buffer = uniPathName.Buffer
2427                 + (RemainingPath->Buffer - FullPathName->Buffer)
2428                 + sNameLenDelta/sizeof( WCHAR);
2429         }
2430
2431         if( FreePathName)
2432         {
2433             AFSExFreePool( FullPathName->Buffer);
2434         }
2435
2436         *FullPathName = uniPathName;
2437
2438 try_exit:
2439
2440         NOTHING;
2441     }
2442
2443     return ntStatus;
2444 }
2445
2446 NTSTATUS
2447 AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
2448                      IN ULONG Reason)
2449 {
2450
2451     NTSTATUS ntStatus = STATUS_SUCCESS;
2452     AFSObjectInfoCB *pCurrentObject = NULL;
2453     AFSObjectInfoCB *pNextObject = NULL;
2454     LONG lCount;
2455     AFSFcb *pFcb = NULL;
2456     ULONG ulFilter = 0;
2457
2458     __Enter
2459     {
2460
2461         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2462                       AFS_TRACE_LEVEL_VERBOSE,
2463                       "AFSInvalidateVolume Invalidate volume fid %08lX-%08lX-%08lX-%08lX Reason %08lX\n",
2464                       VolumeCB->ObjectInformation.FileId.Cell,
2465                       VolumeCB->ObjectInformation.FileId.Volume,
2466                       VolumeCB->ObjectInformation.FileId.Vnode,
2467                       VolumeCB->ObjectInformation.FileId.Unique,
2468                       Reason);
2469
2470         //
2471         // Depending on the reason for invalidation then perform work on the node
2472         //
2473
2474         switch( Reason)
2475         {
2476
2477             case AFS_INVALIDATE_DELETED:
2478             {
2479
2480                 //
2481                 // Mark this volume as invalid
2482                 //
2483
2484                 SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
2485
2486                 SetFlag( VolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE);
2487
2488                 break;
2489             }
2490         }
2491
2492         //
2493         // Invalidate the volume root directory
2494         //
2495
2496         pCurrentObject = &VolumeCB->ObjectInformation;
2497
2498         if ( pCurrentObject )
2499         {
2500
2501             lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
2502
2503             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2504                           AFS_TRACE_LEVEL_VERBOSE,
2505                           "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2506                           pCurrentObject,
2507                           lCount);
2508
2509             AFSInvalidateObject( &pCurrentObject,
2510                                  Reason);
2511
2512             if ( pCurrentObject)
2513             {
2514
2515                 lCount = InterlockedDecrement( &pCurrentObject->ObjectReferenceCount);
2516
2517                 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2518                               AFS_TRACE_LEVEL_VERBOSE,
2519                               "AFSInvalidateVolumeObjects Decrement count on object %08lX Cnt %d\n",
2520                               pCurrentObject,
2521                               lCount);
2522             }
2523         }
2524
2525         //
2526         // Apply invalidation to all other volume objects
2527         //
2528
2529         AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2530                           TRUE);
2531
2532         pCurrentObject = VolumeCB->ObjectInfoListHead;
2533
2534         if ( pCurrentObject)
2535         {
2536
2537             //
2538             // Reference the node so it won't be torn down
2539             //
2540
2541             lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
2542
2543             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2544                           AFS_TRACE_LEVEL_VERBOSE,
2545                           "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2546                           pCurrentObject,
2547                           lCount);
2548         }
2549
2550         while( pCurrentObject != NULL)
2551         {
2552
2553             pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2554
2555             if ( pNextObject)
2556             {
2557
2558                 //
2559                 // Reference the node so it won't be torn down
2560                 //
2561
2562                 lCount = InterlockedIncrement( &pNextObject->ObjectReferenceCount);
2563
2564                 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2565                               AFS_TRACE_LEVEL_VERBOSE,
2566                               "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2567                               pNextObject,
2568                               lCount);
2569             }
2570
2571             AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2572
2573             AFSInvalidateObject( &pCurrentObject,
2574                                  Reason);
2575
2576             if ( pCurrentObject )
2577             {
2578
2579                 lCount = InterlockedDecrement( &pCurrentObject->ObjectReferenceCount);
2580
2581                 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2582                               AFS_TRACE_LEVEL_VERBOSE,
2583                               "AFSInvalidateVolumeObjects Decrement count on object %08lX Cnt %d\n",
2584                               pCurrentObject,
2585                               lCount);
2586             }
2587
2588             AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2589                               TRUE);
2590
2591             pCurrentObject = pNextObject;
2592         }
2593
2594         AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2595     }
2596
2597     return ntStatus;
2598 }
2599
2600 VOID
2601 AFSInvalidateAllVolumes( VOID)
2602 {
2603     AFSVolumeCB *pVolumeCB = NULL;
2604     AFSVolumeCB *pNextVolumeCB = NULL;
2605     AFSDeviceExt *pRDRDeviceExt = NULL;
2606     LONG lCount;
2607
2608     pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2609
2610     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2611                   AFS_TRACE_LEVEL_VERBOSE,
2612                   "AFSInvalidateAllVolumes Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
2613                   &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2614                   PsGetCurrentThread());
2615
2616     AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2617                       TRUE);
2618
2619     pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
2620
2621     if ( pVolumeCB)
2622     {
2623
2624         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2625                       AFS_TRACE_LEVEL_VERBOSE,
2626                       "AFSInvalidateAllVolumes Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
2627                       pVolumeCB->ObjectInfoTree.TreeLock,
2628                       PsGetCurrentThread());
2629
2630         lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2631     }
2632
2633     while( pVolumeCB != NULL)
2634     {
2635
2636         pNextVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2637
2638         if ( pNextVolumeCB)
2639         {
2640
2641             lCount = InterlockedIncrement( &pNextVolumeCB->VolumeReferenceCount);
2642         }
2643
2644         AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2645
2646         // do I need to hold the volume lock here?
2647
2648         AFSInvalidateVolume( pVolumeCB, AFS_INVALIDATE_EXPIRED);
2649
2650         AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2651                           TRUE);
2652
2653         lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2654
2655         pVolumeCB = pNextVolumeCB;
2656     }
2657
2658     AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2659 }
2660
2661 NTSTATUS
2662 AFSVerifyEntry( IN GUID *AuthGroup,
2663                 IN AFSDirectoryCB *DirEntry)
2664 {
2665
2666     NTSTATUS ntStatus = STATUS_SUCCESS;
2667     AFSDirEnumEntry *pDirEnumEntry = NULL;
2668     AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
2669     IO_STATUS_BLOCK stIoStatus;
2670
2671     __Enter
2672     {
2673
2674         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2675                       AFS_TRACE_LEVEL_VERBOSE_2,
2676                       "AFSVerifyEntry Verifying entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2677                       &DirEntry->NameInformation.FileName,
2678                       pObjectInfo->FileId.Cell,
2679                       pObjectInfo->FileId.Volume,
2680                       pObjectInfo->FileId.Vnode,
2681                       pObjectInfo->FileId.Unique);
2682
2683         ntStatus = AFSEvaluateTargetByID( pObjectInfo,
2684                                           AuthGroup,
2685                                           FALSE,
2686                                           &pDirEnumEntry);
2687
2688         if( !NT_SUCCESS( ntStatus))
2689         {
2690
2691             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2692                           AFS_TRACE_LEVEL_ERROR,
2693                           "AFSVerifyEntry Evaluate Target failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2694                           &DirEntry->NameInformation.FileName,
2695                           pObjectInfo->FileId.Cell,
2696                           pObjectInfo->FileId.Volume,
2697                           pObjectInfo->FileId.Vnode,
2698                           pObjectInfo->FileId.Unique,
2699                           ntStatus);
2700
2701             try_return( ntStatus);
2702         }
2703
2704         //
2705         // Check the data version of the file
2706         //
2707
2708         if( pObjectInfo->DataVersion.QuadPart == pDirEnumEntry->DataVersion.QuadPart)
2709         {
2710             if ( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2711             {
2712
2713                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2714                               AFS_TRACE_LEVEL_VERBOSE,
2715                               "AFSVerifyEntry No DV change %I64X for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2716                               pObjectInfo->DataVersion.QuadPart,
2717                               &DirEntry->NameInformation.FileName,
2718                               pObjectInfo->FileId.Cell,
2719                               pObjectInfo->FileId.Volume,
2720                               pObjectInfo->FileId.Vnode,
2721                               pObjectInfo->FileId.Unique);
2722
2723                 //
2724                 // We are ok, just get out
2725                 //
2726
2727                 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2728
2729                 try_return( ntStatus = STATUS_SUCCESS);
2730             }
2731         }
2732
2733         //
2734         // New data version so we will need to process the node based on the type
2735         //
2736
2737         switch( pDirEnumEntry->FileType)
2738         {
2739
2740             case AFS_FILE_TYPE_MOUNTPOINT:
2741             {
2742
2743                 //
2744                 // For a mount point we need to ensure the target is the same
2745                 //
2746
2747                 if( !AFSIsEqualFID( &pObjectInfo->TargetFileId,
2748                                     &pDirEnumEntry->TargetFileId))
2749                 {
2750
2751                 }
2752
2753                 //
2754                 // Update the metadata for the entry
2755                 //
2756
2757                 ntStatus = AFSUpdateMetaData( DirEntry,
2758                                               pDirEnumEntry);
2759
2760                 if( NT_SUCCESS( ntStatus))
2761                 {
2762
2763                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2764                 }
2765
2766                 break;
2767             }
2768
2769             case AFS_FILE_TYPE_SYMLINK:
2770             {
2771
2772                 ASSERT( pDirEnumEntry->TargetNameLength > 0);
2773
2774                 //
2775                 // Update the metadata for the entry
2776                 //
2777
2778                 ntStatus = AFSUpdateMetaData( DirEntry,
2779                                               pDirEnumEntry);
2780
2781                 if( NT_SUCCESS( ntStatus))
2782                 {
2783
2784                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2785                 }
2786
2787                 break;
2788             }
2789
2790             case AFS_FILE_TYPE_FILE:
2791             {
2792                 FILE_OBJECT * pCCFileObject = NULL;
2793                 BOOLEAN bPurgeExtents = FALSE;
2794
2795                 if ( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
2796                 {
2797
2798                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2799                                   AFS_TRACE_LEVEL_VERBOSE,
2800                                   "AFSVerifyEntry DV Change %wZ FID %08lX-%08lX-%08lX-%08lX (%08lX != %08lX)\n",
2801                                   &DirEntry->NameInformation.FileName,
2802                                   pObjectInfo->FileId.Cell,
2803                                   pObjectInfo->FileId.Volume,
2804                                   pObjectInfo->FileId.Vnode,
2805                                   pObjectInfo->FileId.Unique,
2806                                   pObjectInfo->DataVersion.LowPart,
2807                                   pDirEnumEntry->DataVersion.LowPart
2808                                   );
2809
2810                     bPurgeExtents = TRUE;
2811                 }
2812
2813                 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2814                 {
2815
2816                     bPurgeExtents = TRUE;
2817
2818                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2819                                   AFS_TRACE_LEVEL_VERBOSE,
2820                                   "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2821                                   &DirEntry->NameInformation.FileName,
2822                                   pObjectInfo->FileId.Cell,
2823                                   pObjectInfo->FileId.Volume,
2824                                   pObjectInfo->FileId.Vnode,
2825                                   pObjectInfo->FileId.Unique);
2826
2827                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
2828                 }
2829
2830                 if( pObjectInfo->Fcb != NULL)
2831                 {
2832
2833                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2834                                   AFS_TRACE_LEVEL_VERBOSE,
2835                                   "AFSVerifyEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2836                                   &DirEntry->NameInformation.FileName,
2837                                   pObjectInfo->FileId.Cell,
2838                                   pObjectInfo->FileId.Volume,
2839                                   pObjectInfo->FileId.Vnode,
2840                                   pObjectInfo->FileId.Unique);
2841
2842                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
2843                                     TRUE);
2844
2845                     __try
2846                     {
2847
2848                         CcFlushCache( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2849                                       NULL,
2850                                       0,
2851                                       &stIoStatus);
2852
2853                         if( !NT_SUCCESS( stIoStatus.Status))
2854                         {
2855
2856                             AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2857                                           AFS_TRACE_LEVEL_ERROR,
2858                                           "AFSVerifyEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
2859                                           &DirEntry->NameInformation.FileName,
2860                                           pObjectInfo->FileId.Cell,
2861                                           pObjectInfo->FileId.Volume,
2862                                           pObjectInfo->FileId.Vnode,
2863                                           pObjectInfo->FileId.Unique,
2864                                           stIoStatus.Status,
2865                                           stIoStatus.Information);
2866
2867                             ntStatus = stIoStatus.Status;
2868                         }
2869
2870                         if ( bPurgeExtents)
2871                         {
2872
2873                             if ( !CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2874                                                        NULL,
2875                                                        0,
2876                                                        FALSE))
2877                             {
2878
2879                                 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2880                                               AFS_TRACE_LEVEL_WARNING,
2881                                               "AFSVerifyEntry CcPurgeCacheSection failure %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2882                                               &DirEntry->NameInformation.FileName,
2883                                               pObjectInfo->FileId.Cell,
2884                                               pObjectInfo->FileId.Volume,
2885                                               pObjectInfo->FileId.Vnode,
2886                                               pObjectInfo->FileId.Unique);
2887
2888                                 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
2889                             }
2890                         }
2891                     }
2892                     __except( EXCEPTION_EXECUTE_HANDLER)
2893                     {
2894                         ntStatus = GetExceptionCode();
2895
2896                         AFSDbgLogMsg( 0,
2897                                       0,
2898                                       "EXCEPTION - AFSVerifyEntry CcFlushCache or CcPurgeCacheSection %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2899                                       &DirEntry->NameInformation.FileName,
2900                                       pObjectInfo->FileId.Cell,
2901                                       pObjectInfo->FileId.Volume,
2902                                       pObjectInfo->FileId.Vnode,
2903                                       pObjectInfo->FileId.Unique,
2904                                       ntStatus);
2905
2906                         SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
2907                     }
2908
2909                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
2910
2911                     if ( bPurgeExtents)
2912                     {
2913                         AFSFlushExtents( pObjectInfo->Fcb,
2914                                          AuthGroup);
2915                     }
2916
2917                     //
2918                     // Reacquire the Fcb to purge the cache
2919                     //
2920
2921                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2922                                   AFS_TRACE_LEVEL_VERBOSE,
2923                                   "AFSVerifyEntry Acquiring Fcb lock %08lX EXCL %08lX\n",
2924                                   &pObjectInfo->Fcb->NPFcb->Resource,
2925                                   PsGetCurrentThread());
2926
2927                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
2928                                     TRUE);
2929
2930                     //
2931                     // Update the metadata for the entry
2932                     //
2933
2934                     ntStatus = AFSUpdateMetaData( DirEntry,
2935                                                   pDirEnumEntry);
2936
2937                     if( !NT_SUCCESS( ntStatus))
2938                     {
2939
2940                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2941                                       AFS_TRACE_LEVEL_ERROR,
2942                                       "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
2943                                       &DirEntry->NameInformation.FileName,
2944                                       pObjectInfo->FileId.Cell,
2945                                       pObjectInfo->FileId.Volume,
2946                                       pObjectInfo->FileId.Vnode,
2947                                       pObjectInfo->FileId.Unique,
2948                                       ntStatus);
2949
2950                         break;
2951                     }
2952
2953                     //
2954                     // Update file sizes
2955                     //
2956
2957                     pObjectInfo->Fcb->Header.AllocationSize.QuadPart  = pObjectInfo->AllocationSize.QuadPart;
2958                     pObjectInfo->Fcb->Header.FileSize.QuadPart        = pObjectInfo->EndOfFile.QuadPart;
2959                     pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
2960
2961                     pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
2962
2963                     if ( pCCFileObject != NULL)
2964                     {
2965                         CcSetFileSizes( pCCFileObject,
2966                                         (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
2967                     }
2968
2969                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
2970                 }
2971                 else
2972                 {
2973
2974                     //
2975                     // Update the metadata for the entry
2976                     //
2977
2978                     ntStatus = AFSUpdateMetaData( DirEntry,
2979                                                   pDirEnumEntry);
2980
2981                     if( !NT_SUCCESS( ntStatus))
2982                     {
2983
2984                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2985                                       AFS_TRACE_LEVEL_ERROR,
2986                                       "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
2987                                       &DirEntry->NameInformation.FileName,
2988                                       pObjectInfo->FileId.Cell,
2989                                       pObjectInfo->FileId.Volume,
2990                                       pObjectInfo->FileId.Vnode,
2991                                       pObjectInfo->FileId.Unique,
2992                                       ntStatus);
2993
2994                         break;
2995                     }
2996
2997                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2998                                   AFS_TRACE_LEVEL_WARNING,
2999                                   "AFSVerifyEntry Fcb NULL %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3000                                   &DirEntry->NameInformation.FileName,
3001                                   pObjectInfo->FileId.Cell,
3002                                   pObjectInfo->FileId.Volume,
3003                                   pObjectInfo->FileId.Vnode,
3004                                   pObjectInfo->FileId.Unique);
3005                 }
3006
3007                 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3008
3009                 break;
3010             }
3011
3012             case AFS_FILE_TYPE_DIRECTORY:
3013             {
3014
3015                 AFSFcb *pCurrentFcb = NULL;
3016                 AFSDirectoryCB *pCurrentDirEntry = NULL;
3017
3018                 //
3019                 // For a directory or root entry flush the content of
3020                 // the directory enumeration.
3021                 //
3022
3023                 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3024                 {
3025
3026                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3027                                   AFS_TRACE_LEVEL_VERBOSE_2,
3028                                   "AFSVerifyEntry Validating directory content for entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3029                                   &DirEntry->NameInformation.FileName,
3030                                   pObjectInfo->FileId.Cell,
3031                                   pObjectInfo->FileId.Volume,
3032                                   pObjectInfo->FileId.Vnode,
3033                                   pObjectInfo->FileId.Unique);
3034
3035                     AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3036                                     TRUE);
3037
3038                     ntStatus = AFSValidateDirectoryCache( pObjectInfo,
3039                                                           AuthGroup);
3040
3041                     AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3042
3043                     if ( !NT_SUCCESS( ntStatus))
3044                     {
3045
3046                         try_return( ntStatus);
3047                     }
3048                 }
3049
3050                 //
3051                 // Update the metadata for the entry
3052                 //
3053
3054                 ntStatus = AFSUpdateMetaData( DirEntry,
3055                                               pDirEnumEntry);
3056
3057                 if( NT_SUCCESS( ntStatus))
3058                 {
3059
3060                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3061                 }
3062
3063                 break;
3064             }
3065
3066             case AFS_FILE_TYPE_DFSLINK:
3067             {
3068
3069                 UNICODE_STRING uniTargetName;
3070
3071                 //
3072                 // For a DFS link need to check the target name has not changed
3073                 //
3074
3075                 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
3076
3077                 uniTargetName.MaximumLength = uniTargetName.Length;
3078
3079                 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
3080
3081                 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3082                                 TRUE);
3083
3084                 if( DirEntry->NameInformation.TargetName.Length == 0 ||
3085                     RtlCompareUnicodeString( &uniTargetName,
3086                                              &DirEntry->NameInformation.TargetName,
3087                                              TRUE) != 0)
3088                 {
3089
3090                     //
3091                     // Update the target name
3092                     //
3093
3094                     ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3095                                                     &DirEntry->Flags,
3096                                                     uniTargetName.Buffer,
3097                                                     uniTargetName.Length);
3098
3099                     if( !NT_SUCCESS( ntStatus))
3100                     {
3101
3102                         AFSReleaseResource( &DirEntry->NonPaged->Lock);
3103
3104                         break;
3105                     }
3106                 }
3107
3108                 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3109
3110                 //
3111                 // Update the metadata for the entry
3112                 //
3113
3114                 ntStatus = AFSUpdateMetaData( DirEntry,
3115                                               pDirEnumEntry);
3116
3117                 if( NT_SUCCESS( ntStatus))
3118                 {
3119
3120                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3121                 }
3122
3123                 break;
3124             }
3125
3126             default:
3127
3128                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3129                               AFS_TRACE_LEVEL_WARNING,
3130                               "AFSVerifyEntry Attempt to verify node of type %d %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3131                               pObjectInfo->FileType,
3132                               &DirEntry->NameInformation.FileName,
3133                               pObjectInfo->FileId.Cell,
3134                               pObjectInfo->FileId.Volume,
3135                               pObjectInfo->FileId.Vnode,
3136                               pObjectInfo->FileId.Unique);
3137
3138                 break;
3139         }
3140
3141  try_exit:
3142
3143         if( pDirEnumEntry != NULL)
3144         {
3145
3146             AFSExFreePool( pDirEnumEntry);
3147         }
3148     }
3149
3150     return ntStatus;
3151 }
3152
3153 NTSTATUS
3154 AFSSetVolumeState( IN AFSVolumeStatusCB *VolumeStatus)
3155 {
3156
3157     NTSTATUS ntStatus = STATUS_SUCCESS;
3158     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
3159     ULONGLONG   ullIndex = 0;
3160     AFSVolumeCB *pVolumeCB = NULL;
3161     AFSFcb *pFcb = NULL;
3162     AFSObjectInfoCB *pCurrentObject = NULL;
3163     LONG lCount;
3164
3165     __Enter
3166     {
3167
3168         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3169                       AFS_TRACE_LEVEL_VERBOSE,
3170                       "AFSSetVolumeState Marking volume state %d Volume Cell %08lX Volume %08lX\n",
3171                       VolumeStatus->Online,
3172                       VolumeStatus->FileID.Cell,
3173                       VolumeStatus->FileID.Volume);
3174
3175         //
3176         // Need to locate the Fcb for the directory to purge
3177         //
3178
3179         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3180                       AFS_TRACE_LEVEL_VERBOSE,
3181                       "AFSSetVolumeState Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
3182                       &pDevExt->Specific.RDR.VolumeTreeLock,
3183                       PsGetCurrentThread());
3184
3185         AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
3186
3187         //
3188         // Locate the volume node
3189         //
3190
3191         ullIndex = AFSCreateHighIndex( &VolumeStatus->FileID);
3192
3193         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
3194                                        ullIndex,
3195                                        (AFSBTreeEntry **)&pVolumeCB);
3196
3197         if( pVolumeCB != NULL)
3198         {
3199
3200             lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
3201
3202             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3203
3204             //
3205             // Set the volume state accordingly
3206             //
3207
3208             if( VolumeStatus->Online)
3209             {
3210
3211                 InterlockedAnd( (LONG *)&(pVolumeCB->Flags), ~AFS_VOLUME_FLAGS_OFFLINE);
3212             }
3213             else
3214             {
3215
3216                 InterlockedOr( (LONG *)&(pVolumeCB->Flags), AFS_VOLUME_FLAGS_OFFLINE);
3217             }
3218
3219             AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
3220                               TRUE);
3221
3222             pCurrentObject = pVolumeCB->ObjectInfoListHead;;
3223
3224             while( pCurrentObject != NULL)
3225             {
3226
3227                 if( VolumeStatus->Online)
3228                 {
3229
3230                     ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
3231
3232                     SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
3233
3234                     pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
3235                 }
3236                 else
3237                 {
3238
3239                     SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
3240                 }
3241
3242                 pFcb = pCurrentObject->Fcb;
3243
3244                 if( pFcb != NULL &&
3245                     !(VolumeStatus->Online) &&
3246                     pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
3247                 {
3248
3249                     AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3250                                   AFS_TRACE_LEVEL_ERROR,
3251                                   "AFSSetVolumeState Marking volume offline and canceling extents Volume Cell %08lX Volume %08lX\n",
3252                                   VolumeStatus->FileID.Cell,
3253                                   VolumeStatus->FileID.Volume);
3254
3255                     //
3256                     // Clear out the extents
3257                     //
3258
3259                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,