Windows: AFSDeleteObjectInfo InterlockedCompareExchangePointer
[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             AFSDeleteObjectInfo( &pObjectInfoCB);
693
694             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
695                           AFS_TRACE_LEVEL_ERROR,
696                           "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_TAG allocation failure\n"));
697
698             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
699         }
700
701         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
702                       AFS_TRACE_LEVEL_VERBOSE,
703                       "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_TAG allocated %p\n",
704                       pDirNode));
705
706         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
707                                                                                    sizeof( AFSNonPagedDirectoryCB),
708                                                                                    AFS_DIR_ENTRY_NP_TAG);
709
710         if( pNonPagedDirEntry == NULL)
711         {
712
713             ExFreePool( pDirNode);
714
715             AFSDeleteObjectInfo( &pObjectInfoCB);
716
717             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
718                           AFS_TRACE_LEVEL_ERROR,
719                           "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_NP_TAG allocation failure\n"));
720
721             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
722         }
723
724         RtlZeroMemory( pDirNode,
725                        ulEntryLength);
726
727         RtlZeroMemory( pNonPagedDirEntry,
728                        sizeof( AFSNonPagedDirectoryCB));
729
730         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
731
732         pDirNode->NonPaged = pNonPagedDirEntry;
733
734         pDirNode->ObjectInformation = pObjectInfoCB;
735
736         //
737         // Set valid entry
738         //
739
740         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE | AFS_DIR_ENTRY_FAKE | AFS_DIR_ENTRY_VALID);
741
742         pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_DOT_INDEX;
743
744         //
745         // Setup the names in the entry
746         //
747
748         pDirNode->NameInformation.FileName.Length = sizeof( WCHAR);
749
750         pDirNode->NameInformation.FileName.MaximumLength = sizeof( WCHAR);
751
752         pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
753
754         pDirNode->NameInformation.FileName.Buffer[ 0] = L'.';
755
756         //
757         // Populate the rest of the data
758         //
759
760         pObjectInfoCB->FileType = AFS_FILE_TYPE_DIRECTORY;
761
762         pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
763
764         AFSGlobalDotDirEntry = pDirNode;
765
766         //
767         // Now the .. entry
768         //
769
770         pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
771                                                0);
772
773         if( pObjectInfoCB == NULL)
774         {
775
776             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
777                           AFS_TRACE_LEVEL_ERROR,
778                           "AFSInitializeGlobalDirectory AFSAllocateObjectInfo (2) failure %08lX\n",
779                           ntStatus));
780
781             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
782         }
783
784         lCount = AFSObjectInfoIncrement( pObjectInfoCB,
785                                          AFS_OBJECT_REFERENCE_GLOBAL);
786
787         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
788                       AFS_TRACE_LEVEL_VERBOSE,
789                       "AFSInitializeGlobalDirectoryEntries Increment count on object %p Cnt %d\n",
790                       pObjectInfoCB,
791                       lCount));
792
793         ntStatus = STATUS_SUCCESS;
794
795         ulEntryLength = sizeof( AFSDirectoryCB) +
796                                      ( 2 * sizeof( WCHAR));
797
798         pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
799                                                                   ulEntryLength,
800                                                                   AFS_DIR_ENTRY_TAG);
801
802         if( pDirNode == NULL)
803         {
804
805             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
806                           AFS_TRACE_LEVEL_ERROR,
807                           "AFSInitializeGlobalDirectoryEntries AFS_DIR_ENTRY_TAG allocation failure\n"));
808
809             AFSDeleteObjectInfo( &pObjectInfoCB);
810
811             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
812         }
813
814         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
815                       AFS_TRACE_LEVEL_VERBOSE,
816                       "AFSInitializeGlobalDirectoryEntries AFS_DIR_ENTRY_TAG allocated %p\n",
817                       pDirNode));
818
819         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
820                                                                                    sizeof( AFSNonPagedDirectoryCB),
821                                                                                    AFS_DIR_ENTRY_NP_TAG);
822
823         if( pNonPagedDirEntry == NULL)
824         {
825
826             ExFreePool( pDirNode);
827
828             AFSDeleteObjectInfo( &pObjectInfoCB);
829
830             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
831         }
832
833         RtlZeroMemory( pDirNode,
834                        ulEntryLength);
835
836         RtlZeroMemory( pNonPagedDirEntry,
837                        sizeof( AFSNonPagedDirectoryCB));
838
839         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
840
841         pDirNode->NonPaged = pNonPagedDirEntry;
842
843         pDirNode->ObjectInformation = pObjectInfoCB;
844
845         //
846         // Set valid entry
847         //
848
849         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE | AFS_DIR_ENTRY_FAKE | AFS_DIR_ENTRY_VALID);
850
851         pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX;
852
853         //
854         // Setup the names in the entry
855         //
856
857         pDirNode->NameInformation.FileName.Length = 2 * sizeof( WCHAR);
858
859         pDirNode->NameInformation.FileName.MaximumLength = 2 * sizeof( WCHAR);
860
861         pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
862
863         pDirNode->NameInformation.FileName.Buffer[ 0] = L'.';
864
865         pDirNode->NameInformation.FileName.Buffer[ 1] = L'.';
866
867         //
868         // Populate the rest of the data
869         //
870
871         pObjectInfoCB->FileType = AFS_FILE_TYPE_DIRECTORY;
872
873         pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
874
875         AFSGlobalDotDotDirEntry = pDirNode;
876
877 try_exit:
878
879         if( !NT_SUCCESS( ntStatus))
880         {
881
882             if( AFSGlobalDotDirEntry != NULL)
883             {
884
885                 AFSDeleteObjectInfo( &AFSGlobalDotDirEntry->ObjectInformation);
886
887                 ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
888
889                 ExFreePool( AFSGlobalDotDirEntry->NonPaged);
890
891                 ExFreePool( AFSGlobalDotDirEntry);
892
893                 AFSGlobalDotDirEntry = NULL;
894             }
895
896             if( AFSGlobalDotDotDirEntry != NULL)
897             {
898
899                 AFSDeleteObjectInfo( &AFSGlobalDotDotDirEntry->ObjectInformation);
900
901                 ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
902
903                 ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
904
905                 ExFreePool( AFSGlobalDotDotDirEntry);
906
907                 AFSGlobalDotDotDirEntry = NULL;
908             }
909         }
910     }
911
912     return ntStatus;
913 }
914
915 AFSDirectoryCB *
916 AFSInitDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
917                  IN PUNICODE_STRING FileName,
918                  IN PUNICODE_STRING TargetName,
919                  IN AFSDirEnumEntry *DirEnumEntry,
920                  IN ULONG FileIndex)
921 {
922
923     AFSDirectoryCB *pDirNode = NULL;
924     NTSTATUS ntStatus = STATUS_SUCCESS;
925     ULONG ulEntryLength = 0;
926     AFSObjectInfoCB *pObjectInfoCB = NULL;
927     BOOLEAN bAllocatedObjectCB = FALSE;
928     ULONGLONG ullIndex = 0;
929     AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
930     LONG lCount;
931
932     __Enter
933     {
934
935         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
936                       AFS_TRACE_LEVEL_VERBOSE,
937                       "AFSInitDirEntry Initializing entry %wZ parent FID %08lX-%08lX-%08lX-%08lX\n",
938                       FileName,
939                       ParentObjectInfo->FileId.Cell,
940                       ParentObjectInfo->FileId.Volume,
941                       ParentObjectInfo->FileId.Vnode,
942                       ParentObjectInfo->FileId.Unique));
943
944         //
945         // First thing is to locate/create our object information block
946         // for this entry
947         //
948
949         AFSAcquireExcl( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
950                         TRUE);
951
952         ullIndex = AFSCreateLowIndex( &DirEnumEntry->FileId);
953
954         ntStatus = AFSLocateHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
955                                        ullIndex,
956                                        (AFSBTreeEntry **)&pObjectInfoCB);
957
958         if( !NT_SUCCESS( ntStatus) ||
959             pObjectInfoCB == NULL)
960         {
961
962             //
963             // Allocate our object info cb
964             //
965
966             pObjectInfoCB = AFSAllocateObjectInfo( ParentObjectInfo,
967                                                    ullIndex);
968
969             if( pObjectInfoCB == NULL)
970             {
971
972                 AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
973
974                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
975             }
976
977             bAllocatedObjectCB = TRUE;
978
979             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
980                           AFS_TRACE_LEVEL_VERBOSE,
981                           "AFSInitDirEntry initialized object %p Parent Object %p for %wZ\n",
982                           pObjectInfoCB,
983                           ParentObjectInfo,
984                           FileName));
985         }
986
987         lCount = AFSObjectInfoIncrement( pObjectInfoCB,
988                                          AFS_OBJECT_REFERENCE_DIRENTRY);
989
990         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
991                       AFS_TRACE_LEVEL_VERBOSE,
992                       "AFSInitDirEntry Increment count on object %p Cnt %d\n",
993                       pObjectInfoCB,
994                       lCount));
995
996         AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
997
998         ntStatus = STATUS_SUCCESS;
999
1000         ulEntryLength = sizeof( AFSDirectoryCB) +
1001                                      FileName->Length;
1002
1003         if( TargetName != NULL)
1004         {
1005
1006             ulEntryLength += TargetName->Length;
1007         }
1008
1009         pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
1010                                                                ulEntryLength,
1011                                                                AFS_DIR_ENTRY_TAG);
1012
1013         if( pDirNode == NULL)
1014         {
1015
1016             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1017         }
1018
1019         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1020                       AFS_TRACE_LEVEL_VERBOSE,
1021                       "AFSInitDirEntry AFS_DIR_ENTRY_TAG allocated %p\n",
1022                       pDirNode));
1023
1024         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
1025                                                                                 sizeof( AFSNonPagedDirectoryCB),
1026                                                                                 AFS_DIR_ENTRY_NP_TAG);
1027
1028         if( pNonPagedDirEntry == NULL)
1029         {
1030
1031             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1032         }
1033
1034         RtlZeroMemory( pDirNode,
1035                        ulEntryLength);
1036
1037         RtlZeroMemory( pNonPagedDirEntry,
1038                        sizeof( AFSNonPagedDirectoryCB));
1039
1040         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
1041
1042         pDirNode->NonPaged = pNonPagedDirEntry;
1043
1044         pDirNode->ObjectInformation = pObjectInfoCB;
1045
1046         //
1047         // Set valid entry and NOT_IN_PARENT flag
1048         //
1049
1050         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1051
1052         pDirNode->FileIndex = FileIndex;
1053
1054         //
1055         // Setup the names in the entry
1056         //
1057
1058         if( FileName->Length > 0)
1059         {
1060
1061             pDirNode->NameInformation.FileName.Length = FileName->Length;
1062
1063             pDirNode->NameInformation.FileName.MaximumLength = FileName->Length;
1064
1065             pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
1066
1067             RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
1068                            FileName->Buffer,
1069                            pDirNode->NameInformation.FileName.Length);
1070
1071             //
1072             // Create a CRC for the file
1073             //
1074
1075             pDirNode->CaseSensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1076                                                                          FALSE);
1077
1078             pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1079                                                                            TRUE);
1080         }
1081
1082         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1083                       AFS_TRACE_LEVEL_VERBOSE,
1084                       "AFSInitDirEntry Initialized DE %p for %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1085                       pDirNode,
1086                       FileName,
1087                       ParentObjectInfo->FileId.Cell,
1088                       ParentObjectInfo->FileId.Volume,
1089                       ParentObjectInfo->FileId.Vnode,
1090                       ParentObjectInfo->FileId.Unique));
1091
1092         if( TargetName != NULL &&
1093             TargetName->Length > 0)
1094         {
1095
1096             pDirNode->NameInformation.TargetName.Length = TargetName->Length;
1097
1098             pDirNode->NameInformation.TargetName.MaximumLength = pDirNode->NameInformation.TargetName.Length;
1099
1100             pDirNode->NameInformation.TargetName.Buffer = (WCHAR *)((char *)pDirNode +
1101                                                                             sizeof( AFSDirectoryCB) +
1102                                                                             pDirNode->NameInformation.FileName.Length);
1103
1104             RtlCopyMemory( pDirNode->NameInformation.TargetName.Buffer,
1105                            TargetName->Buffer,
1106                            pDirNode->NameInformation.TargetName.Length);
1107         }
1108
1109         //
1110         // If we allocated the object information cb then update the information
1111         //
1112
1113         if( bAllocatedObjectCB)
1114         {
1115
1116             //
1117             // Populate the rest of the data
1118             //
1119
1120             pObjectInfoCB->FileId = DirEnumEntry->FileId;
1121
1122             pObjectInfoCB->TargetFileId = DirEnumEntry->TargetFileId;
1123
1124             pObjectInfoCB->FileType = DirEnumEntry->FileType;
1125
1126             pObjectInfoCB->CreationTime = DirEnumEntry->CreationTime;
1127
1128             pObjectInfoCB->LastAccessTime = DirEnumEntry->LastAccessTime;
1129
1130             pObjectInfoCB->LastWriteTime = DirEnumEntry->LastWriteTime;
1131
1132             pObjectInfoCB->ChangeTime = DirEnumEntry->ChangeTime;
1133
1134             pObjectInfoCB->EndOfFile = DirEnumEntry->EndOfFile;
1135
1136             pObjectInfoCB->AllocationSize = DirEnumEntry->AllocationSize;
1137
1138             pObjectInfoCB->FileAttributes = DirEnumEntry->FileAttributes;
1139
1140             if( pObjectInfoCB->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1141                 pObjectInfoCB->FileType == AFS_FILE_TYPE_DFSLINK)
1142             {
1143
1144                 pObjectInfoCB->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1145             }
1146
1147             if (pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK)
1148             {
1149
1150                 if ( pObjectInfoCB->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1151                 {
1152
1153                     pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1154                 }
1155                 else
1156                 {
1157
1158                     pObjectInfoCB->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1159                 }
1160             }
1161
1162             pObjectInfoCB->EaSize = DirEnumEntry->EaSize;
1163
1164             //
1165             // Check for the case where we have a filetype of SymLink but both the TargetFid and the
1166             // TargetName are empty. In this case set the filetype to zero so we evaluate it later in
1167             // the code
1168             //
1169
1170             if( pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK &&
1171                 pObjectInfoCB->TargetFileId.Vnode == 0 &&
1172                 pObjectInfoCB->TargetFileId.Unique == 0 &&
1173                 pDirNode->NameInformation.TargetName.Length == 0)
1174             {
1175
1176                 //
1177                 // This will ensure we perform a validation on the node
1178                 //
1179
1180                 pObjectInfoCB->FileType = AFS_FILE_TYPE_UNKNOWN;
1181             }
1182
1183             if( pObjectInfoCB->FileType == AFS_FILE_TYPE_UNKNOWN)
1184             {
1185
1186                 SetFlag( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
1187             }
1188         }
1189
1190         //
1191         // Object specific information
1192         //
1193
1194         pObjectInfoCB->Links = DirEnumEntry->Links;
1195
1196         pObjectInfoCB->Expiration = DirEnumEntry->Expiration;
1197
1198         pObjectInfoCB->DataVersion = DirEnumEntry->DataVersion;
1199
1200 try_exit:
1201
1202         if( !NT_SUCCESS( ntStatus))
1203         {
1204
1205             if( pNonPagedDirEntry != NULL)
1206             {
1207
1208                 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
1209
1210                 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
1211             }
1212
1213             if( pDirNode != NULL)
1214             {
1215
1216                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1217                               AFS_TRACE_LEVEL_VERBOSE,
1218                               "AFSInitDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
1219                               pDirNode));
1220
1221                 AFSExFreePoolWithTag( pDirNode, AFS_DIR_ENTRY_TAG);
1222
1223                 pDirNode = NULL;
1224             }
1225
1226             //
1227             // Dereference our object info block if we have one
1228             //
1229
1230             if( pObjectInfoCB != NULL)
1231             {
1232
1233                 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
1234                                                  AFS_OBJECT_REFERENCE_DIRENTRY);
1235
1236                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1237                               AFS_TRACE_LEVEL_VERBOSE,
1238                               "AFSInitDirEntry Decrement count on object %p Cnt %d\n",
1239                               pObjectInfoCB,
1240                               lCount));
1241
1242                 if( bAllocatedObjectCB)
1243                 {
1244
1245                     ASSERT( pObjectInfoCB->ObjectReferenceCount == 0);
1246
1247                     AFSDeleteObjectInfo( &pObjectInfoCB);
1248                 }
1249             }
1250         }
1251     }
1252
1253     return pDirNode;
1254 }
1255
1256 BOOLEAN
1257 AFSCheckForReadOnlyAccess( IN ACCESS_MASK DesiredAccess,
1258                            IN BOOLEAN DirectoryEntry)
1259 {
1260
1261     BOOLEAN bReturn = TRUE;
1262     ACCESS_MASK stAccessMask = 0;
1263
1264     //
1265     // Get rid of anything we don't know about
1266     //
1267
1268     DesiredAccess = (DesiredAccess   &
1269                           ( DELETE |
1270                             READ_CONTROL |
1271                             WRITE_OWNER |
1272                             WRITE_DAC |
1273                             SYNCHRONIZE |
1274                             ACCESS_SYSTEM_SECURITY |
1275                             FILE_WRITE_DATA |
1276                             FILE_READ_EA |
1277                             FILE_WRITE_EA |
1278                             FILE_READ_ATTRIBUTES |
1279                             FILE_WRITE_ATTRIBUTES |
1280                             FILE_LIST_DIRECTORY |
1281                             FILE_TRAVERSE |
1282                             FILE_DELETE_CHILD |
1283                             FILE_APPEND_DATA));
1284
1285     //
1286     // Our 'read only' access mask. These are the accesses we will
1287     // allow for a read only file
1288     //
1289
1290     stAccessMask = DELETE |
1291                         READ_CONTROL |
1292                         WRITE_OWNER |
1293                         WRITE_DAC |
1294                         SYNCHRONIZE |
1295                         ACCESS_SYSTEM_SECURITY |
1296                         FILE_READ_DATA |
1297                         FILE_READ_EA |
1298                         FILE_WRITE_EA |
1299                         FILE_READ_ATTRIBUTES |
1300                         FILE_WRITE_ATTRIBUTES |
1301                         FILE_EXECUTE |
1302                         FILE_LIST_DIRECTORY |
1303                         FILE_TRAVERSE;
1304
1305     //
1306     // For a directory, add in the directory specific accesses
1307     //
1308
1309     if( DirectoryEntry)
1310     {
1311
1312         stAccessMask |= FILE_ADD_SUBDIRECTORY |
1313                                 FILE_ADD_FILE |
1314                                 FILE_DELETE_CHILD;
1315     }
1316
1317     if( FlagOn( DesiredAccess, ~stAccessMask))
1318     {
1319
1320         //
1321         // A write access is set ...
1322         //
1323
1324         bReturn = FALSE;
1325     }
1326
1327     return bReturn;
1328 }
1329
1330 NTSTATUS
1331 AFSEvaluateNode( IN GUID *AuthGroup,
1332                  IN AFSDirectoryCB *DirEntry)
1333 {
1334
1335     NTSTATUS ntStatus = STATUS_SUCCESS;
1336     AFSDirEnumEntry *pDirEntry = NULL;
1337     UNICODE_STRING uniTargetName;
1338
1339     __Enter
1340     {
1341
1342         ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1343                                           AuthGroup,
1344                                           FALSE,
1345                                           &pDirEntry);
1346
1347         if( !NT_SUCCESS( ntStatus))
1348         {
1349
1350             try_return( ntStatus);
1351         }
1352
1353         DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1354
1355         DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1356
1357         DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1358
1359         DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1360
1361         DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1362
1363         DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1364
1365         DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1366
1367         DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1368
1369         DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1370
1371         DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1372
1373         DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1374
1375         if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1376             pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1377         {
1378
1379             DirEntry->ObjectInformation->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1380         }
1381
1382         if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK)
1383         {
1384
1385             if ( DirEntry->ObjectInformation->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1386             {
1387
1388                 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1389             }
1390             else
1391             {
1392
1393                 DirEntry->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1394             }
1395         }
1396
1397         DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1398
1399         DirEntry->ObjectInformation->Links = pDirEntry->Links;
1400
1401         //
1402         // If we have a target name then see if it needs updating ...
1403         //
1404
1405         if( pDirEntry->TargetNameLength > 0)
1406         {
1407
1408             //
1409             // Update the target name information if needed
1410             //
1411
1412             uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1413
1414             uniTargetName.MaximumLength = uniTargetName.Length;
1415
1416             uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1417
1418             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1419                             TRUE);
1420
1421             if( DirEntry->NameInformation.TargetName.Length == 0 ||
1422                 RtlCompareUnicodeString( &uniTargetName,
1423                                          &DirEntry->NameInformation.TargetName,
1424                                          TRUE) != 0)
1425             {
1426
1427                 //
1428                 // Update the target name
1429                 //
1430
1431                 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1432                                                 &DirEntry->Flags,
1433                                                 uniTargetName.Buffer,
1434                                                 uniTargetName.Length);
1435
1436                 if( !NT_SUCCESS( ntStatus))
1437                 {
1438
1439                     AFSReleaseResource( &DirEntry->NonPaged->Lock);
1440
1441                     try_return( ntStatus);
1442                 }
1443             }
1444
1445             AFSReleaseResource( &DirEntry->NonPaged->Lock);
1446         }
1447
1448 try_exit:
1449
1450         if( pDirEntry != NULL)
1451         {
1452
1453             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
1454         }
1455     }
1456
1457     return ntStatus;
1458 }
1459
1460 NTSTATUS
1461 AFSValidateSymLink( IN GUID *AuthGroup,
1462                     IN AFSDirectoryCB *DirEntry)
1463 {
1464
1465     NTSTATUS ntStatus = STATUS_SUCCESS;
1466     AFSDirEnumEntry *pDirEntry = NULL;
1467     UNICODE_STRING uniTargetName;
1468
1469     __Enter
1470     {
1471
1472         ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1473                                           AuthGroup,
1474                                           FALSE,
1475                                           &pDirEntry);
1476
1477         if( !NT_SUCCESS( ntStatus))
1478         {
1479
1480             try_return( ntStatus);
1481         }
1482
1483         if( pDirEntry->FileType == AFS_FILE_TYPE_UNKNOWN ||
1484             pDirEntry->FileType == AFS_FILE_TYPE_INVALID)
1485         {
1486
1487             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1488                           AFS_TRACE_LEVEL_VERBOSE_2,
1489                           "AFSValidateSymLink Invalid type Status %08lX\n",
1490                           STATUS_OBJECT_NAME_NOT_FOUND));
1491
1492             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
1493         }
1494
1495         DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1496
1497         DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1498
1499         DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1500
1501         //
1502         // Update the target name information if needed
1503         //
1504
1505         uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1506
1507         uniTargetName.MaximumLength = uniTargetName.Length;
1508
1509         uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1510
1511         if( uniTargetName.Length > 0)
1512         {
1513
1514             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1515                             TRUE);
1516
1517             if( DirEntry->NameInformation.TargetName.Length == 0 ||
1518                 RtlCompareUnicodeString( &uniTargetName,
1519                                          &DirEntry->NameInformation.TargetName,
1520                                          TRUE) != 0)
1521             {
1522
1523                 //
1524                 // Update the target name
1525                 //
1526
1527                 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1528                                                 &DirEntry->Flags,
1529                                                 uniTargetName.Buffer,
1530                                                 uniTargetName.Length);
1531
1532                 if( !NT_SUCCESS( ntStatus))
1533                 {
1534
1535                     AFSReleaseResource( &DirEntry->NonPaged->Lock);
1536
1537                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1538                 }
1539             }
1540
1541             AFSReleaseResource( &DirEntry->NonPaged->Lock);
1542         }
1543
1544         //
1545         // If the FileType is the same then nothing to do since it IS
1546         // a SymLink
1547         //
1548
1549         if( pDirEntry->FileType == DirEntry->ObjectInformation->FileType)
1550         {
1551
1552             ASSERT( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK);
1553
1554             try_return( ntStatus = STATUS_SUCCESS);
1555         }
1556
1557         DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1558
1559         DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1560
1561         DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1562
1563         DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1564
1565         DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1566
1567         DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1568
1569         DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1570
1571         DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1572
1573         if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1574             pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1575         {
1576
1577             DirEntry->ObjectInformation->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1578         }
1579
1580         if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK)
1581         {
1582
1583             if ( DirEntry->ObjectInformation->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1584             {
1585
1586                 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1587             }
1588             else
1589             {
1590
1591                 DirEntry->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1592             }
1593         }
1594
1595         DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1596
1597         DirEntry->ObjectInformation->Links = pDirEntry->Links;
1598
1599 try_exit:
1600
1601         if( pDirEntry != NULL)
1602         {
1603
1604             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
1605         }
1606     }
1607
1608     return ntStatus;
1609 }
1610
1611 NTSTATUS
1612 AFSInvalidateObject( IN OUT AFSObjectInfoCB **ppObjectInfo,
1613                      IN     ULONG Reason)
1614 {
1615
1616     NTSTATUS ntStatus = STATUS_SUCCESS;
1617     IO_STATUS_BLOCK stIoStatus;
1618     ULONG ulFilter = 0;
1619     AFSObjectInfoCB * pParentObjectInfo = NULL;
1620
1621     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1622                   AFS_TRACE_LEVEL_VERBOSE,
1623                   "AFSInvalidateObject Invalidation on node type %d for fid %08lX-%08lX-%08lX-%08lX Reason %d\n",
1624                   (*ppObjectInfo)->FileType,
1625                   (*ppObjectInfo)->FileId.Cell,
1626                   (*ppObjectInfo)->FileId.Volume,
1627                   (*ppObjectInfo)->FileId.Vnode,
1628                   (*ppObjectInfo)->FileId.Unique,
1629                   Reason));
1630
1631     if ( BooleanFlagOn( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1632     {
1633
1634         pParentObjectInfo = AFSFindObjectInfo( (*ppObjectInfo)->VolumeCB,
1635                                                &(*ppObjectInfo)->ParentFileId);
1636     }
1637
1638     if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_SYMLINK ||
1639         (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DFSLINK ||
1640         (*ppObjectInfo)->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1641     {
1642         //
1643         // We only act on the mount point itself, not the target. If the
1644         // node has been deleted then mark it as such otherwise indicate
1645         // it requires verification
1646         //
1647
1648         if( Reason == AFS_INVALIDATE_DELETED)
1649         {
1650             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
1651         }
1652         else
1653         {
1654
1655             if( Reason == AFS_INVALIDATE_FLUSHED)
1656             {
1657
1658                 (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1659
1660                 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1661             }
1662
1663             (*ppObjectInfo)->Expiration.QuadPart = 0;
1664
1665             (*ppObjectInfo)->TargetFileId.Vnode = 0;
1666
1667             (*ppObjectInfo)->TargetFileId.Unique = 0;
1668
1669             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1670                           AFS_TRACE_LEVEL_VERBOSE,
1671                           "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1672                           (*ppObjectInfo)->FileId.Cell,
1673                           (*ppObjectInfo)->FileId.Volume,
1674                           (*ppObjectInfo)->FileId.Vnode,
1675                           (*ppObjectInfo)->FileId.Unique));
1676
1677             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1678         }
1679
1680         if ( pParentObjectInfo != NULL)
1681         {
1682
1683             ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1684
1685             if( Reason == AFS_INVALIDATE_CREDS)
1686             {
1687                 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1688             }
1689
1690             if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1691                 Reason == AFS_INVALIDATE_FLUSHED)
1692             {
1693                 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1694             }
1695             else
1696             {
1697                 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1698             }
1699
1700             AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1701                                             NULL,
1702                                             ulFilter,
1703                                             FILE_ACTION_MODIFIED);
1704         }
1705
1706         try_return( ntStatus);
1707     }
1708
1709     //
1710     // Depending on the reason for invalidation then perform work on the node
1711     //
1712
1713     switch( Reason)
1714     {
1715
1716     case AFS_INVALIDATE_DELETED:
1717         {
1718
1719             //
1720             // Mark this node as invalid
1721             //
1722
1723             (*ppObjectInfo)->Links = 0;
1724
1725             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_DELETED);
1726
1727             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1728                           AFS_TRACE_LEVEL_VERBOSE,
1729                           "AFSInvalidateObject Set DELETE flag on fid %08lX-%08lX-%08lX-%08lX\n",
1730                           (*ppObjectInfo)->FileId.Cell,
1731                           (*ppObjectInfo)->FileId.Volume,
1732                           (*ppObjectInfo)->FileId.Vnode,
1733                           (*ppObjectInfo)->FileId.Unique));
1734
1735             if( pParentObjectInfo != NULL)
1736             {
1737
1738                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1739                               AFS_TRACE_LEVEL_VERBOSE,
1740                               "AFSInvalidateObject Set VERIFY flag on parent fid %08lX-%08lX-%08lX-%08lX\n",
1741                               pParentObjectInfo->FileId.Cell,
1742                               pParentObjectInfo->FileId.Volume,
1743                               pParentObjectInfo->FileId.Vnode,
1744                               pParentObjectInfo->FileId.Unique));
1745
1746                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1747
1748                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1749
1750                 pParentObjectInfo->Expiration.QuadPart = 0;
1751
1752                 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1753                 {
1754                     ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1755                 }
1756                 else
1757                 {
1758                     ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1759                 }
1760
1761                 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1762                                                 NULL,
1763                                                 ulFilter,
1764                                                 FILE_ACTION_REMOVED);
1765             }
1766
1767             if( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1768                                                       Reason)))
1769             {
1770                 (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1771             }
1772
1773             break;
1774         }
1775
1776     case AFS_INVALIDATE_FLUSHED:
1777         {
1778
1779             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1780                 (*ppObjectInfo)->Fcb != NULL)
1781             {
1782
1783                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1784                               AFS_TRACE_LEVEL_VERBOSE,
1785                               "AFSInvalidateObject Flush/purge file fid %08lX-%08lX-%08lX-%08lX\n",
1786                               (*ppObjectInfo)->FileId.Cell,
1787                               (*ppObjectInfo)->FileId.Volume,
1788                               (*ppObjectInfo)->FileId.Vnode,
1789                               (*ppObjectInfo)->FileId.Unique));
1790
1791                 AFSAcquireExcl( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectResource,
1792                                 TRUE);
1793
1794                 __try
1795                 {
1796
1797                     CcFlushCache( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1798                                   NULL,
1799                                   0,
1800                                   &stIoStatus);
1801
1802                     if( !NT_SUCCESS( stIoStatus.Status))
1803                     {
1804
1805                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1806                                       AFS_TRACE_LEVEL_ERROR,
1807                                       "AFSInvalidateObject CcFlushCache failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1808                                       (*ppObjectInfo)->FileId.Cell,
1809                                       (*ppObjectInfo)->FileId.Volume,
1810                                       (*ppObjectInfo)->FileId.Vnode,
1811                                       (*ppObjectInfo)->FileId.Unique,
1812                                       stIoStatus.Status,
1813                                       stIoStatus.Information));
1814
1815                         ntStatus = stIoStatus.Status;
1816                     }
1817
1818
1819                     if ( (*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
1820                     {
1821
1822                         if ( !CcPurgeCacheSection( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1823                                                    NULL,
1824                                                    0,
1825                                                    FALSE))
1826                         {
1827
1828                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1829                                           AFS_TRACE_LEVEL_WARNING,
1830                                           "AFSInvalidateObject CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
1831                                           (*ppObjectInfo)->FileId.Cell,
1832                                           (*ppObjectInfo)->FileId.Volume,
1833                                           (*ppObjectInfo)->FileId.Vnode,
1834                                           (*ppObjectInfo)->FileId.Unique));
1835
1836                             SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1837                         }
1838                     }
1839                 }
1840                 __except( EXCEPTION_EXECUTE_HANDLER)
1841                 {
1842
1843                     ntStatus = GetExceptionCode();
1844
1845                     AFSDbgTrace(( 0,
1846                                   0,
1847                                   "EXCEPTION - AFSInvalidateObject Cc FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
1848                                   (*ppObjectInfo)->FileId.Cell,
1849                                   (*ppObjectInfo)->FileId.Volume,
1850                                   (*ppObjectInfo)->FileId.Vnode,
1851                                   (*ppObjectInfo)->FileId.Unique,
1852                                   ntStatus));
1853
1854                     SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1855                 }
1856
1857                 AFSReleaseResource( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectResource);
1858
1859                 //
1860                 // Clear out the extents
1861                 // Get rid of them (note this involves waiting
1862                 // for any writes or reads to the cache to complete)
1863                 //
1864
1865                 AFSTearDownFcbExtents( (*ppObjectInfo)->Fcb,
1866                                        NULL);
1867             }
1868
1869             (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1870
1871
1872             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE)
1873             {
1874
1875                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1876                               AFS_TRACE_LEVEL_VERBOSE,
1877                               "AFSInvalidateObject Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
1878                               (*ppObjectInfo)->FileId.Cell,
1879                               (*ppObjectInfo)->FileId.Volume,
1880                               (*ppObjectInfo)->FileId.Vnode,
1881                               (*ppObjectInfo)->FileId.Unique));
1882
1883                 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1884             }
1885
1886             // Fall through to the default processing
1887         }
1888
1889     default:
1890         {
1891
1892             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1893             {
1894                 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1895             }
1896             else
1897             {
1898                 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1899             }
1900
1901             if( Reason == AFS_INVALIDATE_CREDS)
1902             {
1903                 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1904             }
1905
1906             if( Reason == AFS_INVALIDATE_DATA_VERSION)
1907             {
1908                 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1909             }
1910             else
1911             {
1912                 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1913             }
1914
1915             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1916             {
1917
1918                 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo),
1919                                                 NULL,
1920                                                 ulFilter,
1921                                                 FILE_ACTION_MODIFIED);
1922             }
1923             else if ( pParentObjectInfo != NULL)
1924             {
1925
1926                 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1927                                                 NULL,
1928                                                 ulFilter,
1929                                                 FILE_ACTION_MODIFIED);
1930             }
1931
1932             //
1933             // Indicate this node requires re-evaluation for the remaining reasons
1934             //
1935
1936             (*ppObjectInfo)->Expiration.QuadPart = 0;
1937
1938             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1939                           AFS_TRACE_LEVEL_VERBOSE,
1940                           "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1941                           (*ppObjectInfo)->FileId.Cell,
1942                           (*ppObjectInfo)->FileId.Volume,
1943                           (*ppObjectInfo)->FileId.Vnode,
1944                           (*ppObjectInfo)->FileId.Unique));
1945
1946             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1947
1948             if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1949                 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1950                 ( Reason == AFS_INVALIDATE_CALLBACK ||
1951                   Reason == AFS_INVALIDATE_EXPIRED))
1952             {
1953                 if ( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1954                                                            AFS_INVALIDATE_DATA_VERSION)))
1955                 {
1956
1957                     (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1958                 }
1959             }
1960
1961             break;
1962         }
1963     }
1964
1965   try_exit:
1966
1967     if ( pParentObjectInfo != NULL)
1968     {
1969
1970         AFSReleaseObjectInfo( &pParentObjectInfo);
1971     }
1972
1973     return ntStatus;
1974 }
1975
1976 NTSTATUS
1977 AFSInvalidateCache( IN AFSInvalidateCacheCB *InvalidateCB)
1978 {
1979
1980     NTSTATUS ntStatus = STATUS_SUCCESS;
1981     AFSVolumeCB *pVolumeCB = NULL;
1982     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1983     ULONGLONG   ullIndex = 0;
1984     AFSObjectInfoCB *pObjectInfo = NULL;
1985     LONG lCount;
1986
1987     __Enter
1988     {
1989
1990         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1991                       AFS_TRACE_LEVEL_VERBOSE,
1992                       "AFSInvalidateCache Invalidation FID %08lX-%08lX-%08lX-%08lX Type %d WholeVolume %d Reason %d\n",
1993                       InvalidateCB->FileID.Cell,
1994                       InvalidateCB->FileID.Volume,
1995                       InvalidateCB->FileID.Vnode,
1996                       InvalidateCB->FileID.Unique,
1997                       InvalidateCB->FileType,
1998                       InvalidateCB->WholeVolume,
1999                       InvalidateCB->Reason));
2000
2001         //
2002         // Need to locate the Fcb for the directory to purge
2003         //
2004
2005         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2006                       AFS_TRACE_LEVEL_VERBOSE,
2007                       "AFSInvalidateCache Acquiring RDR VolumeTreeLock lock %p SHARED %08lX\n",
2008                       &pDevExt->Specific.RDR.VolumeTreeLock,
2009                       PsGetCurrentThread()));
2010
2011         //
2012         // Starve any exclusive waiters on this paticular call
2013         //
2014
2015         AFSAcquireSharedStarveExclusive( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2016
2017         //
2018         // Locate the volume node
2019         //
2020
2021         ullIndex = AFSCreateHighIndex( &InvalidateCB->FileID);
2022
2023         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2024                                        ullIndex,
2025                                        (AFSBTreeEntry **)&pVolumeCB);
2026
2027         if( pVolumeCB != NULL)
2028         {
2029
2030             lCount = AFSVolumeIncrement( pVolumeCB,
2031                                          AFS_VOLUME_REFERENCE_INVALIDATE);
2032
2033             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2034                           AFS_TRACE_LEVEL_VERBOSE,
2035                           "AFSInvalidateCache Increment count on volume %p Cnt %d\n",
2036                           pVolumeCB,
2037                           lCount));
2038         }
2039
2040         AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2041
2042         if( !NT_SUCCESS( ntStatus) ||
2043             pVolumeCB == NULL)
2044         {
2045
2046             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2047                           AFS_TRACE_LEVEL_WARNING,
2048                           "AFSInvalidateCache Invalidation FAILURE Unable to locate volume node FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2049                           InvalidateCB->FileID.Cell,
2050                           InvalidateCB->FileID.Volume,
2051                           InvalidateCB->FileID.Vnode,
2052                           InvalidateCB->FileID.Unique,
2053                           ntStatus));
2054
2055             try_return( ntStatus = STATUS_SUCCESS);
2056         }
2057
2058         //
2059         // If this is a whole volume invalidation then go do it now
2060         //
2061
2062         if( InvalidateCB->WholeVolume)
2063         {
2064
2065             ntStatus = AFSInvalidateVolume( pVolumeCB,
2066                                             InvalidateCB->Reason);
2067
2068             try_return( ntStatus);
2069         }
2070
2071         AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2072                           TRUE);
2073
2074         if ( AFSIsVolumeFID( &InvalidateCB->FileID))
2075         {
2076
2077             pObjectInfo = &pVolumeCB->ObjectInformation;
2078         }
2079         else
2080         {
2081
2082             ullIndex = AFSCreateLowIndex( &InvalidateCB->FileID);
2083
2084             ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2085                                            ullIndex,
2086                                            (AFSBTreeEntry **)&pObjectInfo);
2087         }
2088
2089         if( pObjectInfo != NULL)
2090         {
2091
2092             //
2093             // Reference the node so it won't be torn down
2094             //
2095
2096             lCount = AFSObjectInfoIncrement( pObjectInfo,
2097                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2098
2099             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2100                           AFS_TRACE_LEVEL_VERBOSE,
2101                           "AFSInvalidateCache Increment count on object %p Cnt %d\n",
2102                           pObjectInfo,
2103                           lCount));
2104         }
2105
2106         AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2107
2108         if( !NT_SUCCESS( ntStatus) ||
2109             pObjectInfo == NULL)
2110         {
2111
2112             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2113                           AFS_TRACE_LEVEL_VERBOSE,
2114                           "AFSInvalidateCache Invalidation FAILURE Unable to locate object FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2115                           InvalidateCB->FileID.Cell,
2116                           InvalidateCB->FileID.Volume,
2117                           InvalidateCB->FileID.Vnode,
2118                           InvalidateCB->FileID.Unique,
2119                           ntStatus));
2120
2121             try_return( ntStatus = STATUS_SUCCESS);
2122         }
2123
2124         AFSInvalidateObject( &pObjectInfo,
2125                              InvalidateCB->Reason);
2126
2127 try_exit:
2128
2129         if( pObjectInfo != NULL)
2130         {
2131
2132             lCount = AFSObjectInfoDecrement( pObjectInfo,
2133                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2134
2135             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2136                           AFS_TRACE_LEVEL_VERBOSE,
2137                           "AFSInvalidateCache Decrement count on object %p Cnt %d\n",
2138                           pObjectInfo,
2139                           lCount));
2140         }
2141
2142         if ( pVolumeCB != NULL)
2143         {
2144
2145             lCount = AFSVolumeDecrement( pVolumeCB,
2146                                          AFS_VOLUME_REFERENCE_INVALIDATE);
2147
2148             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2149                           AFS_TRACE_LEVEL_VERBOSE,
2150                           "AFSInvalidateCache Decrement count on volume %p Cnt %d\n",
2151                           pVolumeCB,
2152                           lCount));
2153         }
2154     }
2155
2156     return ntStatus;
2157 }
2158
2159 BOOLEAN
2160 AFSIsChildOfParent( IN AFSFcb *Dcb,
2161                     IN AFSFcb *Fcb)
2162 {
2163
2164     BOOLEAN bIsChild = FALSE;
2165     AFSFcb *pCurrentFcb = Fcb;
2166     AFSObjectInfoCB * pParentObjectInfo = NULL;
2167
2168     while( pCurrentFcb != NULL)
2169     {
2170
2171         if( BooleanFlagOn( pCurrentFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
2172             AFSIsEqualFID( &pCurrentFcb->ObjectInformation->ParentFileId, &Dcb->ObjectInformation->FileId))
2173         {
2174
2175             bIsChild = TRUE;
2176
2177             break;
2178         }
2179
2180         pParentObjectInfo = AFSFindObjectInfo( pCurrentFcb->ObjectInformation->VolumeCB,
2181                                                &pCurrentFcb->ObjectInformation->ParentFileId);
2182
2183         if ( pParentObjectInfo != NULL)
2184         {
2185
2186             pCurrentFcb = pParentObjectInfo->Fcb;
2187
2188             AFSReleaseObjectInfo( &pParentObjectInfo);
2189         }
2190         else
2191         {
2192
2193             pCurrentFcb = NULL;
2194         }
2195     }
2196
2197     return bIsChild;
2198 }
2199
2200 inline
2201 ULONGLONG
2202 AFSCreateHighIndex( IN AFSFileID *FileID)
2203 {
2204
2205     ULONGLONG ullIndex = 0;
2206
2207     ullIndex = (((ULONGLONG)FileID->Cell << 32) | FileID->Volume);
2208
2209     return ullIndex;
2210 }
2211
2212 inline
2213 ULONGLONG
2214 AFSCreateLowIndex( IN AFSFileID *FileID)
2215 {
2216
2217     ULONGLONG ullIndex = 0;
2218
2219     ullIndex = (((ULONGLONG)FileID->Vnode << 32) | FileID->Unique);
2220
2221     return ullIndex;
2222 }
2223
2224 BOOLEAN
2225 AFSCheckAccess( IN ACCESS_MASK DesiredAccess,
2226                 IN ACCESS_MASK GrantedAccess,
2227                 IN BOOLEAN DirectoryEntry)
2228 {
2229
2230     BOOLEAN bAccessGranted = TRUE;
2231
2232     //
2233     // Check if we are asking for read/write and granted only read only
2234     // NOTE: There will be more checks here
2235     //
2236
2237     if( !AFSCheckForReadOnlyAccess( DesiredAccess,
2238                                     DirectoryEntry) &&
2239         AFSCheckForReadOnlyAccess( GrantedAccess,
2240                                    DirectoryEntry))
2241     {
2242
2243         bAccessGranted = FALSE;
2244     }
2245
2246     return bAccessGranted;
2247 }
2248
2249 NTSTATUS
2250 AFSGetDriverStatus( IN AFSDriverStatusRespCB *DriverStatus)
2251 {
2252
2253     NTSTATUS         ntStatus = STATUS_SUCCESS;
2254     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2255
2256     //
2257     // Start with read
2258     //
2259
2260     DriverStatus->Status = AFS_DRIVER_STATUS_READY;
2261
2262     if( AFSGlobalRoot == NULL)
2263     {
2264
2265         //
2266         // We are not ready
2267         //
2268
2269         DriverStatus->Status = AFS_DRIVER_STATUS_NOT_READY;
2270     }
2271
2272     if( pControlDevExt->Specific.Control.CommServiceCB.IrpPoolControlFlag != POOL_ACTIVE)
2273     {
2274
2275         //
2276         // No service yet
2277         //
2278
2279         DriverStatus->Status = AFS_DRIVER_STATUS_NO_SERVICE;
2280     }
2281
2282     return ntStatus;
2283 }
2284
2285 NTSTATUS
2286 AFSSubstituteSysName( IN UNICODE_STRING *ComponentName,
2287                       IN UNICODE_STRING *SubstituteName,
2288                       IN ULONG StringIndex)
2289 {
2290
2291     NTSTATUS ntStatus = STATUS_SUCCESS;
2292     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2293     AFSSysNameCB    *pSysName = NULL;
2294     ERESOURCE       *pSysNameLock = NULL;
2295     ULONG            ulIndex = 1;
2296     USHORT           usIndex = 0;
2297     UNICODE_STRING   uniSysName;
2298
2299     __Enter
2300     {
2301
2302 #if defined(_WIN64)
2303
2304         if( IoIs32bitProcess( NULL))
2305         {
2306
2307             pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2308
2309             pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2310         }
2311         else
2312         {
2313
2314             pSysNameLock = &pControlDevExt->Specific.Control.SysName64ListLock;
2315
2316             pSysName = pControlDevExt->Specific.Control.SysName64ListHead;
2317         }
2318 #else
2319
2320         pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2321
2322         pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2323
2324 #endif
2325
2326         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2327                       AFS_TRACE_LEVEL_VERBOSE,
2328                       "AFSSubstituteSysName Acquiring SysName lock %p SHARED %08lX\n",
2329                       pSysNameLock,
2330                       PsGetCurrentThread()));
2331
2332         AFSAcquireShared( pSysNameLock,
2333                           TRUE);
2334
2335         //
2336         // Find where we are in the list
2337         //
2338
2339         while( pSysName != NULL &&
2340             ulIndex < StringIndex)
2341         {
2342
2343             pSysName = pSysName->fLink;
2344
2345             ulIndex++;
2346         }
2347
2348         if( pSysName == NULL)
2349         {
2350
2351             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2352                           AFS_TRACE_LEVEL_VERBOSE_2,
2353                           "AFSSubstituteSysName No sysname %wZ Status %08lX\n",
2354                           &ComponentName,
2355                           STATUS_OBJECT_NAME_NOT_FOUND));
2356
2357             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
2358         }
2359
2360         RtlInitUnicodeString( &uniSysName,
2361                               L"@SYS");
2362         //
2363         // If it is a full component of @SYS then just substitue the
2364         // name in
2365         //
2366
2367         if( RtlCompareUnicodeString( &uniSysName,
2368                                      ComponentName,
2369                                      TRUE) == 0)
2370         {
2371
2372             SubstituteName->Length = pSysName->SysName.Length;
2373             SubstituteName->MaximumLength = SubstituteName->Length;
2374
2375             SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2376                                                                         SubstituteName->Length,
2377                                                                         AFS_SUBST_BUFFER_TAG);
2378
2379             if( SubstituteName->Buffer == NULL)
2380             {
2381
2382                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2383             }
2384
2385             RtlCopyMemory( SubstituteName->Buffer,
2386                            pSysName->SysName.Buffer,
2387                            pSysName->SysName.Length);
2388         }
2389         else
2390         {
2391
2392             usIndex = 0;
2393
2394             while( ComponentName->Buffer[ usIndex] != L'@')
2395             {
2396
2397                 usIndex++;
2398             }
2399
2400             SubstituteName->Length = (usIndex * sizeof( WCHAR)) + pSysName->SysName.Length;
2401             SubstituteName->MaximumLength = SubstituteName->Length;
2402
2403             SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2404                                                                         SubstituteName->Length,
2405                                                                         AFS_SUBST_BUFFER_TAG);
2406
2407             if( SubstituteName->Buffer == NULL)
2408             {
2409
2410                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2411             }
2412
2413             RtlCopyMemory( SubstituteName->Buffer,
2414                            ComponentName->Buffer,
2415                            usIndex * sizeof( WCHAR));
2416
2417             RtlCopyMemory( &SubstituteName->Buffer[ usIndex],
2418                            pSysName->SysName.Buffer,
2419                            pSysName->SysName.Length);
2420         }
2421
2422 try_exit:
2423
2424         AFSReleaseResource( pSysNameLock);
2425     }
2426
2427     return ntStatus;
2428 }
2429
2430 NTSTATUS
2431 AFSSubstituteNameInPath( IN OUT UNICODE_STRING *FullPathName,
2432                          IN OUT UNICODE_STRING *ComponentName,
2433                          IN UNICODE_STRING *SubstituteName,
2434                          IN OUT UNICODE_STRING *RemainingPath,
2435                          IN BOOLEAN FreePathName)
2436 {
2437
2438     NTSTATUS ntStatus = STATUS_SUCCESS;
2439     UNICODE_STRING uniPathName;
2440     USHORT usPrefixNameLen = 0;
2441     SHORT  sNameLenDelta = 0;
2442
2443     __Enter
2444     {
2445
2446         //
2447         // If the passed in name can handle the additional length
2448         // then just moves things around
2449         //
2450
2451         sNameLenDelta = SubstituteName->Length - ComponentName->Length;
2452
2453         usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2454
2455         if( FullPathName->MaximumLength > FullPathName->Length + sNameLenDelta)
2456         {
2457
2458             if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2459             {
2460
2461                 RtlMoveMemory( &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + SubstituteName->Length)/sizeof( WCHAR))],
2462                                &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + ComponentName->Length)/sizeof( WCHAR))],
2463                                FullPathName->Length - usPrefixNameLen*sizeof( WCHAR) - ComponentName->Length);
2464             }
2465
2466             RtlCopyMemory( &FullPathName->Buffer[ usPrefixNameLen],
2467                            SubstituteName->Buffer,
2468                            SubstituteName->Length);
2469
2470             FullPathName->Length += sNameLenDelta;
2471
2472             ComponentName->Length += sNameLenDelta;
2473
2474             ComponentName->MaximumLength = ComponentName->Length;
2475
2476             if ( RemainingPath->Buffer)
2477             {
2478
2479                 RemainingPath->Buffer += sNameLenDelta/sizeof( WCHAR);
2480             }
2481
2482             try_return( ntStatus);
2483         }
2484
2485         //
2486         // Need to re-allocate the buffer
2487         //
2488
2489         uniPathName.Length = FullPathName->Length -
2490                                          ComponentName->Length +
2491                                          SubstituteName->Length;
2492
2493         uniPathName.MaximumLength = FullPathName->MaximumLength + PAGE_SIZE;
2494
2495         uniPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2496                                                                 uniPathName.MaximumLength,
2497                                                                 AFS_NAME_BUFFER_FOUR_TAG);
2498
2499         if( uniPathName.Buffer == NULL)
2500         {
2501
2502             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2503         }
2504
2505         usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2506
2507         usPrefixNameLen *= sizeof( WCHAR);
2508
2509         RtlZeroMemory( uniPathName.Buffer,
2510                        uniPathName.MaximumLength);
2511
2512         RtlCopyMemory( uniPathName.Buffer,
2513                        FullPathName->Buffer,
2514                        usPrefixNameLen);
2515
2516         RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen/sizeof( WCHAR))],
2517                        SubstituteName->Buffer,
2518                        SubstituteName->Length);
2519
2520         if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2521         {
2522
2523             RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen + SubstituteName->Length)/sizeof( WCHAR)],
2524                            &FullPathName->Buffer[ (usPrefixNameLen + ComponentName->Length)/sizeof( WCHAR)],
2525                            FullPathName->Length - usPrefixNameLen - ComponentName->Length);
2526         }
2527
2528         ComponentName->Buffer = uniPathName.Buffer + (ComponentName->Buffer - FullPathName->Buffer);
2529
2530         ComponentName->Length += sNameLenDelta;
2531
2532         ComponentName->MaximumLength = ComponentName->Length;
2533
2534         if ( RemainingPath->Buffer)
2535         {
2536
2537             RemainingPath->Buffer = uniPathName.Buffer
2538                 + (RemainingPath->Buffer - FullPathName->Buffer)
2539                 + sNameLenDelta/sizeof( WCHAR);
2540         }
2541
2542         if( FreePathName)
2543         {
2544             AFSExFreePoolWithTag( FullPathName->Buffer, 0);
2545         }
2546
2547         *FullPathName = uniPathName;
2548
2549 try_exit:
2550
2551         NOTHING;
2552     }
2553
2554     return ntStatus;
2555 }
2556
2557 NTSTATUS
2558 AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
2559                      IN ULONG Reason)
2560 {
2561
2562     NTSTATUS ntStatus = STATUS_SUCCESS;
2563     AFSObjectInfoCB *pCurrentObject = NULL;
2564     AFSObjectInfoCB *pNextObject = NULL;
2565     LONG lCount;
2566
2567     __Enter
2568     {
2569
2570         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2571                       AFS_TRACE_LEVEL_VERBOSE,
2572                       "AFSInvalidateVolume Invalidate volume fid %08lX-%08lX-%08lX-%08lX Reason %08lX\n",
2573                       VolumeCB->ObjectInformation.FileId.Cell,
2574                       VolumeCB->ObjectInformation.FileId.Volume,
2575                       VolumeCB->ObjectInformation.FileId.Vnode,
2576                       VolumeCB->ObjectInformation.FileId.Unique,
2577                       Reason));
2578
2579         //
2580         // Depending on the reason for invalidation then perform work on the node
2581         //
2582
2583         switch( Reason)
2584         {
2585
2586             case AFS_INVALIDATE_DELETED:
2587             {
2588
2589                 //
2590                 // Mark this volume as invalid
2591                 //
2592
2593                 SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
2594
2595                 SetFlag( VolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE);
2596
2597                 break;
2598             }
2599         }
2600
2601         //
2602         // Invalidate the volume root directory
2603         //
2604
2605         pCurrentObject = &VolumeCB->ObjectInformation;
2606
2607         if ( pCurrentObject )
2608         {
2609
2610             lCount = AFSObjectInfoIncrement( pCurrentObject,
2611                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2612
2613             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2614                           AFS_TRACE_LEVEL_VERBOSE,
2615                           "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2616                           pCurrentObject,
2617                           lCount));
2618
2619             AFSInvalidateObject( &pCurrentObject,
2620                                  Reason);
2621
2622             if ( pCurrentObject)
2623             {
2624
2625                 lCount = AFSObjectInfoDecrement( pCurrentObject,
2626                                                  AFS_OBJECT_REFERENCE_INVALIDATION);
2627
2628                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2629                               AFS_TRACE_LEVEL_VERBOSE,
2630                               "AFSInvalidateVolumeObjects Decrement count on object %p Cnt %d\n",
2631                               pCurrentObject,
2632                               lCount));
2633             }
2634         }
2635
2636         //
2637         // Apply invalidation to all other volume objects
2638         //
2639
2640         AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2641                           TRUE);
2642
2643         pCurrentObject = VolumeCB->ObjectInfoListHead;
2644
2645         if ( pCurrentObject)
2646         {
2647
2648             //
2649             // Reference the node so it won't be torn down
2650             //
2651
2652             lCount = AFSObjectInfoIncrement( pCurrentObject,
2653                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2654
2655             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2656                           AFS_TRACE_LEVEL_VERBOSE,
2657                           "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2658                           pCurrentObject,
2659                           lCount));
2660         }
2661
2662         while( pCurrentObject != NULL)
2663         {
2664
2665             pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2666
2667             if ( pNextObject)
2668             {
2669
2670                 //
2671                 // Reference the node so it won't be torn down
2672                 //
2673
2674                 lCount = AFSObjectInfoIncrement( pNextObject,
2675                                                  AFS_OBJECT_REFERENCE_INVALIDATION);
2676
2677                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2678                               AFS_TRACE_LEVEL_VERBOSE,
2679                               "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2680                               pNextObject,
2681                               lCount));
2682             }
2683
2684             AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2685
2686             AFSInvalidateObject( &pCurrentObject,
2687                                  Reason);
2688
2689             if ( pCurrentObject )
2690             {
2691
2692                 lCount = AFSObjectInfoDecrement( pCurrentObject,
2693                                                  AFS_OBJECT_REFERENCE_INVALIDATION);
2694
2695                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2696                               AFS_TRACE_LEVEL_VERBOSE,
2697                               "AFSInvalidateVolumeObjects Decrement count on object %p Cnt %d\n",
2698                               pCurrentObject,
2699                               lCount));
2700             }
2701
2702             AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2703                               TRUE);
2704
2705             pCurrentObject = pNextObject;
2706         }
2707
2708         AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2709     }
2710
2711     return ntStatus;
2712 }
2713
2714 VOID
2715 AFSInvalidateAllVolumes( VOID)
2716 {
2717     AFSVolumeCB *pVolumeCB = NULL;
2718     AFSVolumeCB *pNextVolumeCB = NULL;
2719     AFSDeviceExt *pRDRDeviceExt = NULL;
2720     LONG lCount;
2721
2722     pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2723
2724     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2725                   AFS_TRACE_LEVEL_VERBOSE,
2726                   "AFSInvalidateAllVolumes Acquiring RDR VolumeListLock lock %p SHARED %08lX\n",
2727                   &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2728                   PsGetCurrentThread()));
2729
2730     AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2731                       TRUE);
2732
2733     pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
2734
2735     if ( pVolumeCB)
2736     {
2737
2738         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2739                       AFS_TRACE_LEVEL_VERBOSE,
2740                       "AFSInvalidateAllVolumes Acquiring VolumeRoot ObjectInfoTree lock %p SHARED %08lX\n",
2741                       pVolumeCB->ObjectInfoTree.TreeLock,
2742                       PsGetCurrentThread()));
2743
2744         lCount = AFSVolumeIncrement( pVolumeCB,
2745                                      AFS_VOLUME_REFERENCE_INVALIDATE);
2746
2747         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2748                       AFS_TRACE_LEVEL_VERBOSE,
2749                       "AFSInvalidateAllVolumes Increment count on volume %p Cnt %d\n",
2750                       pVolumeCB,
2751                       lCount));
2752     }
2753
2754     while( pVolumeCB != NULL)
2755     {
2756
2757         pNextVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2758
2759         if ( pNextVolumeCB)
2760         {
2761
2762             lCount = AFSVolumeIncrement( pNextVolumeCB,
2763                                          AFS_VOLUME_REFERENCE_INVALIDATE);
2764
2765             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2766                           AFS_TRACE_LEVEL_VERBOSE,
2767                           "AFSInvalidateAllVolumes Increment count on volume %p Cnt %d\n",
2768                           pVolumeCB,
2769                           lCount));
2770         }
2771
2772         AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2773
2774         // do I need to hold the volume lock here?
2775
2776         AFSInvalidateVolume( pVolumeCB, AFS_INVALIDATE_EXPIRED);
2777
2778         AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2779                           TRUE);
2780
2781         lCount = AFSVolumeDecrement( pVolumeCB,
2782                                      AFS_VOLUME_REFERENCE_INVALIDATE);
2783
2784         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2785                       AFS_TRACE_LEVEL_VERBOSE,
2786                       "AFSInvalidateAllVolumes Decrement count on volume %p Cnt %d\n",
2787                       pVolumeCB,
2788                       lCount));
2789
2790         pVolumeCB = pNextVolumeCB;
2791     }
2792
2793     AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2794 }
2795
2796 NTSTATUS
2797 AFSVerifyEntry( IN GUID *AuthGroup,
2798                 IN AFSDirectoryCB *DirEntry)
2799 {
2800
2801     NTSTATUS ntStatus = STATUS_SUCCESS;
2802     AFSDirEnumEntry *pDirEnumEntry = NULL;
2803     AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
2804     IO_STATUS_BLOCK stIoStatus;
2805
2806     __Enter
2807     {
2808
2809         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2810                       AFS_TRACE_LEVEL_VERBOSE_2,
2811                       "AFSVerifyEntry Verifying entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2812                       &DirEntry->NameInformation.FileName,
2813                       pObjectInfo->FileId.Cell,
2814                       pObjectInfo->FileId.Volume,
2815                       pObjectInfo->FileId.Vnode,
2816                       pObjectInfo->FileId.Unique));
2817
2818         ntStatus = AFSEvaluateTargetByID( pObjectInfo,
2819                                           AuthGroup,
2820                                           FALSE,
2821                                           &pDirEnumEntry);
2822
2823         if( !NT_SUCCESS( ntStatus))
2824         {
2825
2826             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2827                           AFS_TRACE_LEVEL_ERROR,
2828                           "AFSVerifyEntry Evaluate Target failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2829                           &DirEntry->NameInformation.FileName,
2830                           pObjectInfo->FileId.Cell,
2831                           pObjectInfo->FileId.Volume,
2832                           pObjectInfo->FileId.Vnode,
2833                           pObjectInfo->FileId.Unique,
2834                           ntStatus));
2835
2836             try_return( ntStatus);
2837         }
2838
2839         //
2840         // Check the data version of the file
2841         //
2842
2843         if( pObjectInfo->DataVersion.QuadPart == pDirEnumEntry->DataVersion.QuadPart)
2844         {
2845             if ( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2846             {
2847
2848                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2849                               AFS_TRACE_LEVEL_VERBOSE,
2850                               "AFSVerifyEntry No DV change %I64X for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2851                               pObjectInfo->DataVersion.QuadPart,
2852                               &DirEntry->NameInformation.FileName,
2853                               pObjectInfo->FileId.Cell,
2854                               pObjectInfo->FileId.Volume,
2855                               pObjectInfo->FileId.Vnode,
2856                               pObjectInfo->FileId.Unique));
2857
2858                 //
2859                 // We are ok, just get out
2860                 //
2861
2862                 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2863
2864                 try_return( ntStatus = STATUS_SUCCESS);
2865             }
2866         }
2867
2868         //
2869         // New data version so we will need to process the node based on the type
2870         //
2871
2872         switch( pDirEnumEntry->FileType)
2873         {
2874
2875             case AFS_FILE_TYPE_MOUNTPOINT:
2876             {
2877
2878                 //
2879                 // For a mount point we need to ensure the target is the same
2880                 //
2881
2882                 if( !AFSIsEqualFID( &pObjectInfo->TargetFileId,
2883                                     &pDirEnumEntry->TargetFileId))
2884                 {
2885
2886                 }
2887
2888                 //
2889                 // Update the metadata for the entry
2890                 //
2891
2892                 ntStatus = AFSUpdateMetaData( DirEntry,
2893                                               pDirEnumEntry);
2894
2895                 if( NT_SUCCESS( ntStatus))
2896                 {
2897
2898                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2899                 }
2900
2901                 break;
2902             }
2903
2904             case AFS_FILE_TYPE_SYMLINK:
2905             {
2906
2907                 //
2908                 // Update the metadata for the entry
2909                 //
2910
2911                 ntStatus = AFSUpdateMetaData( DirEntry,
2912                                               pDirEnumEntry);
2913
2914                 if( NT_SUCCESS( ntStatus))
2915                 {
2916
2917                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2918                 }
2919
2920                 break;
2921             }
2922
2923             case AFS_FILE_TYPE_FILE:
2924             {
2925                 FILE_OBJECT * pCCFileObject = NULL;
2926                 BOOLEAN bPurgeExtents = FALSE;
2927
2928                 if ( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
2929                 {
2930
2931                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2932                                   AFS_TRACE_LEVEL_VERBOSE,
2933                                   "AFSVerifyEntry DV Change %wZ FID %08lX-%08lX-%08lX-%08lX (%08lX != %08lX)\n",
2934                                   &DirEntry->NameInformation.FileName,
2935                                   pObjectInfo->FileId.Cell,
2936                                   pObjectInfo->FileId.Volume,
2937                                   pObjectInfo->FileId.Vnode,
2938                                   pObjectInfo->FileId.Unique,
2939                                   pObjectInfo->DataVersion.LowPart,
2940                                   pDirEnumEntry->DataVersion.LowPart));
2941
2942                     bPurgeExtents = TRUE;
2943                 }
2944
2945                 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2946                 {
2947
2948                     bPurgeExtents = TRUE;
2949
2950                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2951                                   AFS_TRACE_LEVEL_VERBOSE,
2952                                   "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2953                                   &DirEntry->NameInformation.FileName,
2954                                   pObjectInfo->FileId.Cell,
2955                                   pObjectInfo->FileId.Volume,
2956                                   pObjectInfo->FileId.Vnode,
2957                                   pObjectInfo->FileId.Unique));
2958
2959                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
2960                 }
2961
2962                 if( pObjectInfo->Fcb != NULL)
2963                 {
2964
2965                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2966                                   AFS_TRACE_LEVEL_VERBOSE,
2967                                   "AFSVerifyEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2968                                   &DirEntry->NameInformation.FileName,
2969                                   pObjectInfo->FileId.Cell,
2970                                   pObjectInfo->FileId.Volume,
2971                                   pObjectInfo->FileId.Vnode,
2972                                   pObjectInfo->FileId.Unique));
2973
2974                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
2975                                     TRUE);
2976
2977                     __try
2978                     {
2979
2980                         CcFlushCache( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2981                                       NULL,
2982                                       0,
2983                                       &stIoStatus);
2984
2985                         if( !NT_SUCCESS( stIoStatus.Status))
2986                         {
2987
2988                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2989                                           AFS_TRACE_LEVEL_ERROR,
2990                                           "AFSVerifyEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
2991                                           &DirEntry->NameInformation.FileName,
2992                                           pObjectInfo->FileId.Cell,
2993                                           pObjectInfo->FileId.Volume,
2994                                           pObjectInfo->FileId.Vnode,
2995                                           pObjectInfo->FileId.Unique,
2996                                           stIoStatus.Status,
2997                                           stIoStatus.Information));
2998
2999                             ntStatus = stIoStatus.Status;
3000                         }
3001
3002                         if ( bPurgeExtents &&
3003                              pObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
3004                         {
3005
3006                             if ( !CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
3007                                                        NULL,
3008                                                        0,
3009                                                        FALSE))
3010                             {
3011
3012                                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
3013                                               AFS_TRACE_LEVEL_WARNING,
3014                                               "AFSVerifyEntry CcPurgeCacheSection failure %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3015                                               &DirEntry->NameInformation.FileName,
3016                                               pObjectInfo->FileId.Cell,
3017                                               pObjectInfo->FileId.Volume,
3018                                               pObjectInfo->FileId.Vnode,
3019                                               pObjectInfo->FileId.Unique));
3020
3021                                 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
3022                             }
3023                         }
3024                     }
3025                     __except( EXCEPTION_EXECUTE_HANDLER)
3026                     {
3027                         ntStatus = GetExceptionCode();
3028
3029                         AFSDbgTrace(( 0,
3030                                       0,
3031                                       "EXCEPTION - AFSVerifyEntry CcFlushCache or CcPurgeCacheSection %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
3032                                       &DirEntry->NameInformation.FileName,
3033                                       pObjectInfo->FileId.Cell,
3034                                       pObjectInfo->FileId.Volume,
3035                                       pObjectInfo->FileId.Vnode,
3036                                       pObjectInfo->FileId.Unique,
3037                                       ntStatus));
3038
3039                         SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
3040                     }
3041
3042                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
3043
3044                     if ( bPurgeExtents)
3045                     {
3046                         AFSFlushExtents( pObjectInfo->Fcb,
3047                                          AuthGroup);
3048                     }
3049
3050                     //
3051                     // Reacquire the Fcb to purge the cache
3052                     //
3053
3054                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3055                                   AFS_TRACE_LEVEL_VERBOSE,
3056                                   "AFSVerifyEntry Acquiring Fcb lock %p EXCL %08lX\n",
3057                                   &pObjectInfo->Fcb->NPFcb->Resource,
3058                                   PsGetCurrentThread()));
3059
3060                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
3061                                     TRUE);
3062
3063                     //
3064                     // Update the metadata for the entry
3065                     //
3066
3067                     ntStatus = AFSUpdateMetaData( DirEntry,
3068                                                   pDirEnumEntry);
3069
3070                     if( !NT_SUCCESS( ntStatus))
3071                     {
3072
3073                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3074                                       AFS_TRACE_LEVEL_ERROR,
3075                                       "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
3076                                       &DirEntry->NameInformation.FileName,
3077                                       pObjectInfo->FileId.Cell,
3078                                       pObjectInfo->FileId.Volume,
3079                                       pObjectInfo->FileId.Vnode,
3080                                       pObjectInfo->FileId.Unique,
3081                                       ntStatus));
3082
3083                         break;
3084                     }
3085
3086                     //
3087                     // Update file sizes
3088                     //
3089
3090                     pObjectInfo->Fcb->Header.AllocationSize.QuadPart  = pObjectInfo->AllocationSize.QuadPart;
3091                     pObjectInfo->Fcb->Header.FileSize.QuadPart        = pObjectInfo->EndOfFile.QuadPart;
3092                     pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
3093
3094                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3095                                   AFS_TRACE_LEVEL_VERBOSE,
3096                                   "AFSVerifyEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
3097                                   &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3098                                   PsGetCurrentThread()));
3099
3100                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3101                                     TRUE);
3102
3103                     pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
3104
3105                     if ( pCCFileObject != NULL)
3106                     {
3107                         CcSetFileSizes( pCCFileObject,
3108                                         (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
3109                     }
3110
3111                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3112                                   AFS_TRACE_LEVEL_VERBOSE,
3113                                   "AFSVerifyEntry Releasing Fcb SectionObject lock %p EXCL %08lX\n",
3114                                   &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3115                                   PsGetCurrentThread()));
3116
3117                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
3118
3119                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
3120                 }
3121                 else
3122                 {
3123
3124                     //
3125                     // Update the metadata for the entry
3126                     //
3127
3128                     ntStatus = AFSUpdateMetaData( DirEntry,
3129                                                   pDirEnumEntry);
3130
3131                     if( !NT_SUCCESS( ntStatus))
3132                     {
3133
3134                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3135                                       AFS_TRACE_LEVEL_ERROR,
3136                                       "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
3137                                       &DirEntry->NameInformation.FileName,
3138                                       pObjectInfo->FileId.Cell,
3139                                       pObjectInfo->FileId.Volume,
3140                                       pObjectInfo->FileId.Vnode,
3141                                       pObjectInfo->FileId.Unique,
3142                                       ntStatus));
3143
3144                         break;
3145                     }
3146
3147                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3148                                   AFS_TRACE_LEVEL_WARNING,
3149                                   "AFSVerifyEntry Fcb NULL %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3150                                   &DirEntry->NameInformation.FileName,
3151                                   pObjectInfo->FileId.Cell,
3152                                   pObjectInfo->FileId.Volume,
3153                                   pObjectInfo->FileId.Vnode,
3154                                   pObjectInfo->FileId.Unique));
3155                 }
3156
3157                 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3158
3159                 break;
3160             }
3161
3162             case AFS_FILE_TYPE_DIRECTORY:
3163             {
3164
3165                 //
3166                 // For a directory or root entry flush the content of
3167                 // the directory enumeration.
3168                 //
3169
3170                 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3171                 {
3172
3173                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3174                                   AFS_TRACE_LEVEL_VERBOSE_2,
3175                                   "AFSVerifyEntry Validating directory content for entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3176                                   &DirEntry->NameInformation.FileName,
3177                                   pObjectInfo->FileId.Cell,
3178                                   pObjectInfo->FileId.Volume,
3179                                   pObjectInfo->FileId.Vnode,
3180                                   pObjectInfo->FileId.Unique));
3181
3182                     AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3183                                     TRUE);
3184
3185                     ntStatus = AFSValidateDirectoryCache( pObjectInfo,
3186                                                           AuthGroup);
3187
3188                     AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3189
3190                     if ( !NT_SUCCESS( ntStatus))
3191                     {
3192
3193                         try_return( ntStatus);
3194                     }
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                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3208                 }
3209
3210                 break;
3211             }
3212
3213             case AFS_FILE_TYPE_DFSLINK:
3214             {
3215
3216                 UNICODE_STRING uniTargetName;
3217
3218                 //
3219                 // For a DFS link need to check the target name has not changed
3220                 //
3221
3222                 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
3223
3224                 uniTargetName.MaximumLength = uniTargetName.Length;
3225
3226                 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
3227
3228                 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3229                                 TRUE);
3230
3231                 if( DirEntry->NameInformation.TargetName.Length == 0 ||
3232                     RtlCompareUnicodeString( &uniTargetName,
3233                                              &DirEntry->NameInformation.TargetName,
3234                                              TRUE) != 0)
3235                 {
3236
3237                     //
3238                     // Update the target name
3239                   &n