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