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