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