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