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