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