201ca8dfc586719eaaa65bb9842505d28da0fb3f
[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             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1444                           AFS_TRACE_LEVEL_VERBOSE_2,
1445                           "AFSValidateSymLink Invalid type Status %08lX\n",
1446                           STATUS_OBJECT_NAME_NOT_FOUND);
1447
1448             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
1449         }
1450
1451         DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1452
1453         DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1454
1455         DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1456
1457         //
1458         // Update the target name information if needed
1459         //
1460
1461         uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1462
1463         uniTargetName.MaximumLength = uniTargetName.Length;
1464
1465         uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1466
1467         if( uniTargetName.Length > 0)
1468         {
1469
1470             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1471                             TRUE);
1472
1473             if( DirEntry->NameInformation.TargetName.Length == 0 ||
1474                 RtlCompareUnicodeString( &uniTargetName,
1475                                          &DirEntry->NameInformation.TargetName,
1476                                          TRUE) != 0)
1477             {
1478
1479                 //
1480                 // Update the target name
1481                 //
1482
1483                 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1484                                                 &DirEntry->Flags,
1485                                                 uniTargetName.Buffer,
1486                                                 uniTargetName.Length);
1487
1488                 if( !NT_SUCCESS( ntStatus))
1489                 {
1490
1491                     AFSReleaseResource( &DirEntry->NonPaged->Lock);
1492
1493                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1494                 }
1495             }
1496
1497             AFSReleaseResource( &DirEntry->NonPaged->Lock);
1498         }
1499
1500         //
1501         // If the FileType is the same then nothing to do since it IS
1502         // a SymLink
1503         //
1504
1505         if( pDirEntry->FileType == DirEntry->ObjectInformation->FileType)
1506         {
1507
1508             ASSERT( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK);
1509
1510             try_return( ntStatus = STATUS_SUCCESS);
1511         }
1512
1513         DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1514
1515         DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1516
1517         DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1518
1519         DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1520
1521         DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1522
1523         DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1524
1525         DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1526
1527         DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1528
1529         if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1530         {
1531
1532             DirEntry->ObjectInformation->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1533         }
1534
1535         if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK ||
1536             pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1537         {
1538
1539             DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1540         }
1541
1542         DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1543
1544         DirEntry->ObjectInformation->Links = pDirEntry->Links;
1545
1546 try_exit:
1547
1548         if( pDirEntry != NULL)
1549         {
1550
1551             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
1552         }
1553     }
1554
1555     return ntStatus;
1556 }
1557
1558 NTSTATUS
1559 AFSInvalidateObject( IN OUT AFSObjectInfoCB **ppObjectInfo,
1560                      IN     ULONG Reason)
1561 {
1562
1563     NTSTATUS ntStatus = STATUS_SUCCESS;
1564     IO_STATUS_BLOCK stIoStatus;
1565     ULONG ulFilter = 0;
1566
1567     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1568                   AFS_TRACE_LEVEL_VERBOSE,
1569                   "AFSInvalidateObject Invalidation on node type %d for fid %08lX-%08lX-%08lX-%08lX Reason %d\n",
1570                   (*ppObjectInfo)->FileType,
1571                   (*ppObjectInfo)->FileId.Cell,
1572                   (*ppObjectInfo)->FileId.Volume,
1573                   (*ppObjectInfo)->FileId.Vnode,
1574                   (*ppObjectInfo)->FileId.Unique,
1575                   Reason);
1576
1577     if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_SYMLINK ||
1578         (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DFSLINK ||
1579         (*ppObjectInfo)->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1580     {
1581         //
1582         // We only act on the mount point itself, not the target. If the
1583         // node has been deleted then mark it as such otherwise indicate
1584         // it requires verification
1585         //
1586
1587         if( Reason == AFS_INVALIDATE_DELETED)
1588         {
1589             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
1590         }
1591         else
1592         {
1593
1594             if( Reason == AFS_INVALIDATE_FLUSHED)
1595             {
1596
1597                 (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1598
1599                 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1600             }
1601
1602             (*ppObjectInfo)->Expiration.QuadPart = 0;
1603
1604             (*ppObjectInfo)->TargetFileId.Vnode = 0;
1605
1606             (*ppObjectInfo)->TargetFileId.Unique = 0;
1607
1608             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1609                           AFS_TRACE_LEVEL_VERBOSE,
1610                           "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1611                           (*ppObjectInfo)->FileId.Cell,
1612                           (*ppObjectInfo)->FileId.Volume,
1613                           (*ppObjectInfo)->FileId.Vnode,
1614                           (*ppObjectInfo)->FileId.Unique);
1615
1616             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1617         }
1618
1619         ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1620
1621         if( Reason == AFS_INVALIDATE_CREDS)
1622         {
1623             ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1624         }
1625
1626         if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1627             Reason == AFS_INVALIDATE_FLUSHED)
1628         {
1629             ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1630         }
1631         else
1632         {
1633             ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1634         }
1635
1636         AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
1637                                         NULL,
1638                                         ulFilter,
1639                                         FILE_ACTION_MODIFIED);
1640
1641         try_return( ntStatus);
1642     }
1643
1644     //
1645     // Depending on the reason for invalidation then perform work on the node
1646     //
1647
1648     switch( Reason)
1649     {
1650
1651     case AFS_INVALIDATE_DELETED:
1652         {
1653
1654             //
1655             // Mark this node as invalid
1656             //
1657
1658             (*ppObjectInfo)->Links = 0;
1659
1660             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_DELETED);
1661
1662             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1663                           AFS_TRACE_LEVEL_VERBOSE,
1664                           "AFSInvalidateObject Set DELETE flag on fid %08lX-%08lX-%08lX-%08lX\n",
1665                           (*ppObjectInfo)->FileId.Cell,
1666                           (*ppObjectInfo)->FileId.Volume,
1667                           (*ppObjectInfo)->FileId.Vnode,
1668                           (*ppObjectInfo)->FileId.Unique);
1669
1670             if( (*ppObjectInfo)->ParentObjectInformation != NULL)
1671             {
1672
1673                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1674                               AFS_TRACE_LEVEL_VERBOSE,
1675                               "AFSInvalidateObject Set VERIFY flag on parent fid %08lX-%08lX-%08lX-%08lX\n",
1676                               (*ppObjectInfo)->ParentObjectInformation->FileId.Cell,
1677                               (*ppObjectInfo)->ParentObjectInformation->FileId.Volume,
1678                               (*ppObjectInfo)->ParentObjectInformation->FileId.Vnode,
1679                               (*ppObjectInfo)->ParentObjectInformation->FileId.Unique);
1680
1681                 SetFlag( (*ppObjectInfo)->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1682
1683                 (*ppObjectInfo)->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1684
1685                 (*ppObjectInfo)->ParentObjectInformation->Expiration.QuadPart = 0;
1686             }
1687
1688             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1689             {
1690                 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1691             }
1692             else
1693             {
1694                 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1695             }
1696
1697             AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
1698                                             NULL,
1699                                             ulFilter,
1700                                             FILE_ACTION_REMOVED);
1701
1702             if( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1703                                                       Reason)))
1704             {
1705                 (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1706             }
1707
1708             break;
1709         }
1710
1711     case AFS_INVALIDATE_FLUSHED:
1712         {
1713
1714             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1715                 (*ppObjectInfo)->Fcb != NULL)
1716             {
1717
1718                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1719                               AFS_TRACE_LEVEL_VERBOSE,
1720                               "AFSInvalidateObject Flush/purge file fid %08lX-%08lX-%08lX-%08lX\n",
1721                               (*ppObjectInfo)->FileId.Cell,
1722                               (*ppObjectInfo)->FileId.Volume,
1723                               (*ppObjectInfo)->FileId.Vnode,
1724                               (*ppObjectInfo)->FileId.Unique);
1725
1726                 AFSAcquireExcl( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectResource,
1727                                 TRUE);
1728
1729                 __try
1730                 {
1731
1732                     CcFlushCache( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1733                                   NULL,
1734                                   0,
1735                                   &stIoStatus);
1736
1737                     if( !NT_SUCCESS( stIoStatus.Status))
1738                     {
1739
1740                         AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1741                                       AFS_TRACE_LEVEL_ERROR,
1742                                       "AFSInvalidateObject CcFlushCache failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1743                                       (*ppObjectInfo)->FileId.Cell,
1744                                       (*ppObjectInfo)->FileId.Volume,
1745                                       (*ppObjectInfo)->FileId.Vnode,
1746                                       (*ppObjectInfo)->FileId.Unique,
1747                                       stIoStatus.Status,
1748                                       stIoStatus.Information);
1749
1750                         ntStatus = stIoStatus.Status;
1751                     }
1752
1753
1754                     if ( (*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
1755                     {
1756
1757                         if ( !CcPurgeCacheSection( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1758                                                    NULL,
1759                                                    0,
1760                                                    FALSE))
1761                         {
1762
1763                             AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1764                                           AFS_TRACE_LEVEL_WARNING,
1765                                           "AFSInvalidateObject CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
1766                                           (*ppObjectInfo)->FileId.Cell,
1767                                           (*ppObjectInfo)->FileId.Volume,
1768                                           (*ppObjectInfo)->FileId.Vnode,
1769                                           (*ppObjectInfo)->FileId.Unique);
1770
1771                             SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1772                         }
1773                     }
1774                 }
1775                 __except( EXCEPTION_EXECUTE_HANDLER)
1776                 {
1777
1778                     ntStatus = GetExceptionCode();
1779
1780                     AFSDbgLogMsg( 0,
1781                                   0,
1782                                   "EXCEPTION - AFSInvalidateObject Cc FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
1783                                   (*ppObjectInfo)->FileId.Cell,
1784                                   (*ppObjectInfo)->FileId.Volume,
1785                                   (*ppObjectInfo)->FileId.Vnode,
1786                                   (*ppObjectInfo)->FileId.Unique,
1787                                   ntStatus);
1788
1789                     SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1790                 }
1791
1792                 AFSReleaseResource( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectResource);
1793
1794                 //
1795                 // Clear out the extents
1796                 // Get rid of them (note this involves waiting
1797                 // for any writes or reads to the cache to complete)
1798                 //
1799
1800                 AFSTearDownFcbExtents( (*ppObjectInfo)->Fcb,
1801                                        NULL);
1802             }
1803
1804             (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1805
1806
1807             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE)
1808             {
1809
1810                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1811                               AFS_TRACE_LEVEL_VERBOSE,
1812                               "AFSInvalidateObject Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
1813                               (*ppObjectInfo)->FileId.Cell,
1814                               (*ppObjectInfo)->FileId.Volume,
1815                               (*ppObjectInfo)->FileId.Vnode,
1816                               (*ppObjectInfo)->FileId.Unique);
1817
1818                 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1819             }
1820
1821             // Fall through to the default processing
1822         }
1823
1824     default:
1825         {
1826
1827             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1828             {
1829                 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1830             }
1831             else
1832             {
1833                 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1834             }
1835
1836             if( Reason == AFS_INVALIDATE_CREDS)
1837             {
1838                 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1839             }
1840
1841             if( Reason == AFS_INVALIDATE_DATA_VERSION)
1842             {
1843                 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1844             }
1845             else
1846             {
1847                 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1848             }
1849
1850             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1851             {
1852
1853                 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo),
1854                                                 NULL,
1855                                                 ulFilter,
1856                                                 FILE_ACTION_MODIFIED);
1857             }
1858             else
1859             {
1860
1861                 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
1862                                                 NULL,
1863                                                 ulFilter,
1864                                                 FILE_ACTION_MODIFIED);
1865             }
1866
1867             //
1868             // Indicate this node requires re-evaluation for the remaining reasons
1869             //
1870
1871             (*ppObjectInfo)->Expiration.QuadPart = 0;
1872
1873             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1874                           AFS_TRACE_LEVEL_VERBOSE,
1875                           "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1876                           (*ppObjectInfo)->FileId.Cell,
1877                           (*ppObjectInfo)->FileId.Volume,
1878                           (*ppObjectInfo)->FileId.Vnode,
1879                           (*ppObjectInfo)->FileId.Unique);
1880
1881             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1882
1883             if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1884                 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1885                 ( Reason == AFS_INVALIDATE_CALLBACK ||
1886                   Reason == AFS_INVALIDATE_EXPIRED))
1887             {
1888                 if ( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1889                                                            AFS_INVALIDATE_DATA_VERSION)))
1890                 {
1891
1892                     (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1893                 }
1894             }
1895
1896             break;
1897         }
1898     }
1899
1900   try_exit:
1901
1902     return ntStatus;
1903 }
1904
1905 NTSTATUS
1906 AFSInvalidateCache( IN AFSInvalidateCacheCB *InvalidateCB)
1907 {
1908
1909     NTSTATUS ntStatus = STATUS_SUCCESS;
1910     AFSVolumeCB *pVolumeCB = NULL;
1911     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1912     ULONGLONG   ullIndex = 0;
1913     AFSObjectInfoCB *pObjectInfo = NULL;
1914     LONG lCount;
1915
1916     __Enter
1917     {
1918
1919         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1920                       AFS_TRACE_LEVEL_VERBOSE,
1921                       "AFSInvalidateCache Invalidation FID %08lX-%08lX-%08lX-%08lX Type %d WholeVolume %d Reason %d\n",
1922                       InvalidateCB->FileID.Cell,
1923                       InvalidateCB->FileID.Volume,
1924                       InvalidateCB->FileID.Vnode,
1925                       InvalidateCB->FileID.Unique,
1926                       InvalidateCB->FileType,
1927                       InvalidateCB->WholeVolume,
1928                       InvalidateCB->Reason);
1929
1930         //
1931         // Need to locate the Fcb for the directory to purge
1932         //
1933
1934         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1935                       AFS_TRACE_LEVEL_VERBOSE,
1936                       "AFSInvalidateCache Acquiring RDR VolumeTreeLock lock %p SHARED %08lX\n",
1937                       &pDevExt->Specific.RDR.VolumeTreeLock,
1938                       PsGetCurrentThread());
1939
1940         //
1941         // Starve any exclusive waiters on this paticular call
1942         //
1943
1944         AFSAcquireSharedStarveExclusive( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1945
1946         //
1947         // Locate the volume node
1948         //
1949
1950         ullIndex = AFSCreateHighIndex( &InvalidateCB->FileID);
1951
1952         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1953                                        ullIndex,
1954                                        (AFSBTreeEntry **)&pVolumeCB);
1955
1956         if( pVolumeCB != NULL)
1957         {
1958
1959             lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1960
1961             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1962                           AFS_TRACE_LEVEL_VERBOSE,
1963                           "AFSInvalidateCache Increment count on volume %p Cnt %d\n",
1964                           pVolumeCB,
1965                           lCount);
1966         }
1967
1968         AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1969
1970         if( !NT_SUCCESS( ntStatus) ||
1971             pVolumeCB == NULL)
1972         {
1973
1974             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1975                           AFS_TRACE_LEVEL_WARNING,
1976                           "AFSInvalidateCache Invalidation FAILURE Unable to locate volume node FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1977                           InvalidateCB->FileID.Cell,
1978                           InvalidateCB->FileID.Volume,
1979                           InvalidateCB->FileID.Vnode,
1980                           InvalidateCB->FileID.Unique,
1981                           ntStatus);
1982
1983             try_return( ntStatus = STATUS_SUCCESS);
1984         }
1985
1986         //
1987         // If this is a whole volume invalidation then go do it now
1988         //
1989
1990         if( InvalidateCB->WholeVolume)
1991         {
1992
1993             ntStatus = AFSInvalidateVolume( pVolumeCB,
1994                                             InvalidateCB->Reason);
1995
1996             try_return( ntStatus);
1997         }
1998
1999         AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2000                           TRUE);
2001
2002         if ( AFSIsVolumeFID( &InvalidateCB->FileID))
2003         {
2004
2005             pObjectInfo = &pVolumeCB->ObjectInformation;
2006         }
2007         else
2008         {
2009
2010             ullIndex = AFSCreateLowIndex( &InvalidateCB->FileID);
2011
2012             ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2013                                            ullIndex,
2014                                            (AFSBTreeEntry **)&pObjectInfo);
2015         }
2016
2017         if( pObjectInfo != NULL)
2018         {
2019
2020             //
2021             // Reference the node so it won't be torn down
2022             //
2023
2024             lCount = AFSObjectInfoIncrement( pObjectInfo);
2025
2026             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2027                           AFS_TRACE_LEVEL_VERBOSE,
2028                           "AFSInvalidateCache Increment count on object %p Cnt %d\n",
2029                           pObjectInfo,
2030                           lCount);
2031         }
2032
2033         AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2034
2035         if( !NT_SUCCESS( ntStatus) ||
2036             pObjectInfo == NULL)
2037         {
2038
2039             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2040                           AFS_TRACE_LEVEL_VERBOSE,
2041                           "AFSInvalidateCache Invalidation FAILURE Unable to locate object FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2042                           InvalidateCB->FileID.Cell,
2043                           InvalidateCB->FileID.Volume,
2044                           InvalidateCB->FileID.Vnode,
2045                           InvalidateCB->FileID.Unique,
2046                           ntStatus);
2047
2048             try_return( ntStatus = STATUS_SUCCESS);
2049         }
2050
2051         AFSInvalidateObject( &pObjectInfo,
2052                              InvalidateCB->Reason);
2053
2054 try_exit:
2055
2056         if( pObjectInfo != NULL)
2057         {
2058
2059             lCount = AFSObjectInfoDecrement( pObjectInfo);
2060
2061             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2062                           AFS_TRACE_LEVEL_VERBOSE,
2063                           "AFSInvalidateCache Decrement count on object %p Cnt %d\n",
2064                           pObjectInfo,
2065                           lCount);
2066         }
2067
2068         if ( pVolumeCB != NULL)
2069         {
2070
2071             lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2072
2073             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2074                           AFS_TRACE_LEVEL_VERBOSE,
2075                           "AFSInvalidateCache Decrement count on volume %p Cnt %d\n",
2076                           pVolumeCB,
2077                           lCount);
2078         }
2079     }
2080
2081     return ntStatus;
2082 }
2083
2084 BOOLEAN
2085 AFSIsChildOfParent( IN AFSFcb *Dcb,
2086                     IN AFSFcb *Fcb)
2087 {
2088
2089     BOOLEAN bIsChild = FALSE;
2090     AFSFcb *pCurrentFcb = Fcb;
2091
2092     while( pCurrentFcb != NULL)
2093     {
2094
2095         if( pCurrentFcb->ObjectInformation->ParentObjectInformation == Dcb->ObjectInformation)
2096         {
2097
2098             bIsChild = TRUE;
2099
2100             break;
2101         }
2102
2103         pCurrentFcb = pCurrentFcb->ObjectInformation->ParentObjectInformation->Fcb;
2104     }
2105
2106     return bIsChild;
2107 }
2108
2109 inline
2110 ULONGLONG
2111 AFSCreateHighIndex( IN AFSFileID *FileID)
2112 {
2113
2114     ULONGLONG ullIndex = 0;
2115
2116     ullIndex = (((ULONGLONG)FileID->Cell << 32) | FileID->Volume);
2117
2118     return ullIndex;
2119 }
2120
2121 inline
2122 ULONGLONG
2123 AFSCreateLowIndex( IN AFSFileID *FileID)
2124 {
2125
2126     ULONGLONG ullIndex = 0;
2127
2128     ullIndex = (((ULONGLONG)FileID->Vnode << 32) | FileID->Unique);
2129
2130     return ullIndex;
2131 }
2132
2133 BOOLEAN
2134 AFSCheckAccess( IN ACCESS_MASK DesiredAccess,
2135                 IN ACCESS_MASK GrantedAccess,
2136                 IN BOOLEAN DirectoryEntry)
2137 {
2138
2139     BOOLEAN bAccessGranted = TRUE;
2140
2141     //
2142     // Check if we are asking for read/write and granted only read only
2143     // NOTE: There will be more checks here
2144     //
2145
2146     if( !AFSCheckForReadOnlyAccess( DesiredAccess,
2147                                     DirectoryEntry) &&
2148         AFSCheckForReadOnlyAccess( GrantedAccess,
2149                                    DirectoryEntry))
2150     {
2151
2152         bAccessGranted = FALSE;
2153     }
2154
2155     return bAccessGranted;
2156 }
2157
2158 NTSTATUS
2159 AFSGetDriverStatus( IN AFSDriverStatusRespCB *DriverStatus)
2160 {
2161
2162     NTSTATUS         ntStatus = STATUS_SUCCESS;
2163     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2164
2165     //
2166     // Start with read
2167     //
2168
2169     DriverStatus->Status = AFS_DRIVER_STATUS_READY;
2170
2171     if( AFSGlobalRoot == NULL)
2172     {
2173
2174         //
2175         // We are not ready
2176         //
2177
2178         DriverStatus->Status = AFS_DRIVER_STATUS_NOT_READY;
2179     }
2180
2181     if( pControlDevExt->Specific.Control.CommServiceCB.IrpPoolControlFlag != POOL_ACTIVE)
2182     {
2183
2184         //
2185         // No service yet
2186         //
2187
2188         DriverStatus->Status = AFS_DRIVER_STATUS_NO_SERVICE;
2189     }
2190
2191     return ntStatus;
2192 }
2193
2194 NTSTATUS
2195 AFSSubstituteSysName( IN UNICODE_STRING *ComponentName,
2196                       IN UNICODE_STRING *SubstituteName,
2197                       IN ULONG StringIndex)
2198 {
2199
2200     NTSTATUS ntStatus = STATUS_SUCCESS;
2201     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2202     AFSSysNameCB    *pSysName = NULL;
2203     ERESOURCE       *pSysNameLock = NULL;
2204     ULONG            ulIndex = 1;
2205     USHORT           usIndex = 0;
2206     UNICODE_STRING   uniSysName;
2207
2208     __Enter
2209     {
2210
2211 #if defined(_WIN64)
2212
2213         if( IoIs32bitProcess( NULL))
2214         {
2215
2216             pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2217
2218             pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2219         }
2220         else
2221         {
2222
2223             pSysNameLock = &pControlDevExt->Specific.Control.SysName64ListLock;
2224
2225             pSysName = pControlDevExt->Specific.Control.SysName64ListHead;
2226         }
2227 #else
2228
2229         pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2230
2231         pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2232
2233 #endif
2234
2235         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2236                       AFS_TRACE_LEVEL_VERBOSE,
2237                       "AFSSubstituteSysName Acquiring SysName lock %p SHARED %08lX\n",
2238                       pSysNameLock,
2239                       PsGetCurrentThread());
2240
2241         AFSAcquireShared( pSysNameLock,
2242                           TRUE);
2243
2244         //
2245         // Find where we are in the list
2246         //
2247
2248         while( pSysName != NULL &&
2249             ulIndex < StringIndex)
2250         {
2251
2252             pSysName = pSysName->fLink;
2253
2254             ulIndex++;
2255         }
2256
2257         if( pSysName == NULL)
2258         {
2259
2260             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2261                           AFS_TRACE_LEVEL_VERBOSE_2,
2262                           "AFSSubstituteSysName No sysname %wZ Status %08lX\n",
2263                           &ComponentName,
2264                           STATUS_OBJECT_NAME_NOT_FOUND);
2265
2266             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
2267         }
2268
2269         RtlInitUnicodeString( &uniSysName,
2270                               L"@SYS");
2271         //
2272         // If it is a full component of @SYS then just substitue the
2273         // name in
2274         //
2275
2276         if( RtlCompareUnicodeString( &uniSysName,
2277                                      ComponentName,
2278                                      TRUE) == 0)
2279         {
2280
2281             SubstituteName->Length = pSysName->SysName.Length;
2282             SubstituteName->MaximumLength = SubstituteName->Length;
2283
2284             SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2285                                                                         SubstituteName->Length,
2286                                                                         AFS_SUBST_BUFFER_TAG);
2287
2288             if( SubstituteName->Buffer == NULL)
2289             {
2290
2291                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2292             }
2293
2294             RtlCopyMemory( SubstituteName->Buffer,
2295                            pSysName->SysName.Buffer,
2296                            pSysName->SysName.Length);
2297         }
2298         else
2299         {
2300
2301             usIndex = 0;
2302
2303             while( ComponentName->Buffer[ usIndex] != L'@')
2304             {
2305
2306                 usIndex++;
2307             }
2308
2309             SubstituteName->Length = (usIndex * sizeof( WCHAR)) + pSysName->SysName.Length;
2310             SubstituteName->MaximumLength = SubstituteName->Length;
2311
2312             SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2313                                                                         SubstituteName->Length,
2314                                                                         AFS_SUBST_BUFFER_TAG);
2315
2316             if( SubstituteName->Buffer == NULL)
2317             {
2318
2319                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2320             }
2321
2322             RtlCopyMemory( SubstituteName->Buffer,
2323                            ComponentName->Buffer,
2324                            usIndex * sizeof( WCHAR));
2325
2326             RtlCopyMemory( &SubstituteName->Buffer[ usIndex],
2327                            pSysName->SysName.Buffer,
2328                            pSysName->SysName.Length);
2329         }
2330
2331 try_exit:
2332
2333         AFSReleaseResource( pSysNameLock);
2334     }
2335
2336     return ntStatus;
2337 }
2338
2339 NTSTATUS
2340 AFSSubstituteNameInPath( IN OUT UNICODE_STRING *FullPathName,
2341                          IN OUT UNICODE_STRING *ComponentName,
2342                          IN UNICODE_STRING *SubstituteName,
2343                          IN OUT UNICODE_STRING *RemainingPath,
2344                          IN BOOLEAN FreePathName)
2345 {
2346
2347     NTSTATUS ntStatus = STATUS_SUCCESS;
2348     UNICODE_STRING uniPathName;
2349     USHORT usPrefixNameLen = 0;
2350     SHORT  sNameLenDelta = 0;
2351
2352     __Enter
2353     {
2354
2355         //
2356         // If the passed in name can handle the additional length
2357         // then just moves things around
2358         //
2359
2360         sNameLenDelta = SubstituteName->Length - ComponentName->Length;
2361
2362         usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2363
2364         if( FullPathName->MaximumLength > FullPathName->Length + sNameLenDelta)
2365         {
2366
2367             if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2368             {
2369
2370                 RtlMoveMemory( &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + SubstituteName->Length)/sizeof( WCHAR))],
2371                                &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + ComponentName->Length)/sizeof( WCHAR))],
2372                                FullPathName->Length - usPrefixNameLen*sizeof( WCHAR) - ComponentName->Length);
2373             }
2374
2375             RtlCopyMemory( &FullPathName->Buffer[ usPrefixNameLen],
2376                            SubstituteName->Buffer,
2377                            SubstituteName->Length);
2378
2379             FullPathName->Length += sNameLenDelta;
2380
2381             ComponentName->Length += sNameLenDelta;
2382
2383             ComponentName->MaximumLength = ComponentName->Length;
2384
2385             if ( RemainingPath->Buffer)
2386             {
2387
2388                 RemainingPath->Buffer += sNameLenDelta/sizeof( WCHAR);
2389             }
2390
2391             try_return( ntStatus);
2392         }
2393
2394         //
2395         // Need to re-allocate the buffer
2396         //
2397
2398         uniPathName.Length = FullPathName->Length -
2399                                          ComponentName->Length +
2400                                          SubstituteName->Length;
2401
2402         uniPathName.MaximumLength = FullPathName->MaximumLength + PAGE_SIZE;
2403
2404         uniPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2405                                                                 uniPathName.MaximumLength,
2406                                                                 AFS_NAME_BUFFER_FOUR_TAG);
2407
2408         if( uniPathName.Buffer == NULL)
2409         {
2410
2411             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2412         }
2413
2414         usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2415
2416         usPrefixNameLen *= sizeof( WCHAR);
2417
2418         RtlZeroMemory( uniPathName.Buffer,
2419                        uniPathName.MaximumLength);
2420
2421         RtlCopyMemory( uniPathName.Buffer,
2422                        FullPathName->Buffer,
2423                        usPrefixNameLen);
2424
2425         RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen/sizeof( WCHAR))],
2426                        SubstituteName->Buffer,
2427                        SubstituteName->Length);
2428
2429         if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2430         {
2431
2432             RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen + SubstituteName->Length)/sizeof( WCHAR)],
2433                            &FullPathName->Buffer[ (usPrefixNameLen + ComponentName->Length)/sizeof( WCHAR)],
2434                            FullPathName->Length - usPrefixNameLen - ComponentName->Length);
2435         }
2436
2437         ComponentName->Buffer = uniPathName.Buffer + (ComponentName->Buffer - FullPathName->Buffer);
2438
2439         ComponentName->Length += sNameLenDelta;
2440
2441         ComponentName->MaximumLength = ComponentName->Length;
2442
2443         if ( RemainingPath->Buffer)
2444         {
2445
2446             RemainingPath->Buffer = uniPathName.Buffer
2447                 + (RemainingPath->Buffer - FullPathName->Buffer)
2448                 + sNameLenDelta/sizeof( WCHAR);
2449         }
2450
2451         if( FreePathName)
2452         {
2453             AFSExFreePoolWithTag( FullPathName->Buffer, 0);
2454         }
2455
2456         *FullPathName = uniPathName;
2457
2458 try_exit:
2459
2460         NOTHING;
2461     }
2462
2463     return ntStatus;
2464 }
2465
2466 NTSTATUS
2467 AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
2468                      IN ULONG Reason)
2469 {
2470
2471     NTSTATUS ntStatus = STATUS_SUCCESS;
2472     AFSObjectInfoCB *pCurrentObject = NULL;
2473     AFSObjectInfoCB *pNextObject = NULL;
2474     LONG lCount;
2475
2476     __Enter
2477     {
2478
2479         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2480                       AFS_TRACE_LEVEL_VERBOSE,
2481                       "AFSInvalidateVolume Invalidate volume fid %08lX-%08lX-%08lX-%08lX Reason %08lX\n",
2482                       VolumeCB->ObjectInformation.FileId.Cell,
2483                       VolumeCB->ObjectInformation.FileId.Volume,
2484                       VolumeCB->ObjectInformation.FileId.Vnode,
2485                       VolumeCB->ObjectInformation.FileId.Unique,
2486                       Reason);
2487
2488         //
2489         // Depending on the reason for invalidation then perform work on the node
2490         //
2491
2492         switch( Reason)
2493         {
2494
2495             case AFS_INVALIDATE_DELETED:
2496             {
2497
2498                 //
2499                 // Mark this volume as invalid
2500                 //
2501
2502                 SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
2503
2504                 SetFlag( VolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE);
2505
2506                 break;
2507             }
2508         }
2509
2510         //
2511         // Invalidate the volume root directory
2512         //
2513
2514         pCurrentObject = &VolumeCB->ObjectInformation;
2515
2516         if ( pCurrentObject )
2517         {
2518
2519             lCount = AFSObjectInfoIncrement( pCurrentObject);
2520
2521             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2522                           AFS_TRACE_LEVEL_VERBOSE,
2523                           "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2524                           pCurrentObject,
2525                           lCount);
2526
2527             AFSInvalidateObject( &pCurrentObject,
2528                                  Reason);
2529
2530             if ( pCurrentObject)
2531             {
2532
2533                 lCount = AFSObjectInfoDecrement( pCurrentObject);
2534
2535                 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2536                               AFS_TRACE_LEVEL_VERBOSE,
2537                               "AFSInvalidateVolumeObjects Decrement count on object %p Cnt %d\n",
2538                               pCurrentObject,
2539                               lCount);
2540             }
2541         }
2542
2543         //
2544         // Apply invalidation to all other volume objects
2545         //
2546
2547         AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2548                           TRUE);
2549
2550         pCurrentObject = VolumeCB->ObjectInfoListHead;
2551
2552         if ( pCurrentObject)
2553         {
2554
2555             //
2556             // Reference the node so it won't be torn down
2557             //
2558
2559             lCount = AFSObjectInfoIncrement( pCurrentObject);
2560
2561             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2562                           AFS_TRACE_LEVEL_VERBOSE,
2563                           "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2564                           pCurrentObject,
2565                           lCount);
2566         }
2567
2568         while( pCurrentObject != NULL)
2569         {
2570
2571             pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2572
2573             if ( pNextObject)
2574             {
2575
2576                 //
2577                 // Reference the node so it won't be torn down
2578                 //
2579
2580                 lCount = AFSObjectInfoIncrement( pNextObject);
2581
2582                 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2583                               AFS_TRACE_LEVEL_VERBOSE,
2584                               "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2585                               pNextObject,
2586                               lCount);
2587             }
2588
2589             AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2590
2591             AFSInvalidateObject( &pCurrentObject,
2592                                  Reason);
2593
2594             if ( pCurrentObject )
2595             {
2596
2597                 lCount = AFSObjectInfoDecrement( pCurrentObject);
2598
2599                 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2600                               AFS_TRACE_LEVEL_VERBOSE,
2601                               "AFSInvalidateVolumeObjects Decrement count on object %p Cnt %d\n",
2602                               pCurrentObject,
2603                               lCount);
2604             }
2605
2606             AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2607                               TRUE);
2608
2609             pCurrentObject = pNextObject;
2610         }
2611
2612         AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2613     }
2614
2615     return ntStatus;
2616 }
2617
2618 VOID
2619 AFSInvalidateAllVolumes( VOID)
2620 {
2621     AFSVolumeCB *pVolumeCB = NULL;
2622     AFSVolumeCB *pNextVolumeCB = NULL;
2623     AFSDeviceExt *pRDRDeviceExt = NULL;
2624     LONG lCount;
2625
2626     pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2627
2628     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2629                   AFS_TRACE_LEVEL_VERBOSE,
2630                   "AFSInvalidateAllVolumes Acquiring RDR VolumeListLock lock %p SHARED %08lX\n",
2631                   &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2632                   PsGetCurrentThread());
2633
2634     AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2635                       TRUE);
2636
2637     pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
2638
2639     if ( pVolumeCB)
2640     {
2641
2642         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2643                       AFS_TRACE_LEVEL_VERBOSE,
2644                       "AFSInvalidateAllVolumes Acquiring VolumeRoot ObjectInfoTree lock %p SHARED %08lX\n",
2645                       pVolumeCB->ObjectInfoTree.TreeLock,
2646                       PsGetCurrentThread());
2647
2648         lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2649
2650         AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2651                       AFS_TRACE_LEVEL_VERBOSE,
2652                       "AFSInvalidateAllVolumes Increment count on volume %p Cnt %d\n",
2653                       pVolumeCB,
2654                       lCount);
2655     }
2656
2657     while( pVolumeCB != NULL)
2658     {
2659
2660         pNextVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2661
2662         if ( pNextVolumeCB)
2663         {
2664
2665             lCount = InterlockedIncrement( &pNextVolumeCB->VolumeReferenceCount);
2666
2667             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2668                           AFS_TRACE_LEVEL_VERBOSE,
2669                           "AFSInvalidateAllVolumes Increment count on volume %p Cnt %d\n",
2670                           pVolumeCB,
2671                           lCount);
2672         }
2673
2674         AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2675
2676         // do I need to hold the volume lock here?
2677
2678         AFSInvalidateVolume( pVolumeCB, AFS_INVALIDATE_EXPIRED);
2679
2680         AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2681                           TRUE);
2682
2683         lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2684
2685         AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2686                       AFS_TRACE_LEVEL_VERBOSE,
2687                       "AFSInvalidateAllVolumes Decrement count on volume %p Cnt %d\n",
2688                       pVolumeCB,
2689                       lCount);
2690
2691         pVolumeCB = pNextVolumeCB;
2692     }
2693
2694     AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2695 }
2696
2697 NTSTATUS
2698 AFSVerifyEntry( IN GUID *AuthGroup,
2699                 IN AFSDirectoryCB *DirEntry)
2700 {
2701
2702     NTSTATUS ntStatus = STATUS_SUCCESS;
2703     AFSDirEnumEntry *pDirEnumEntry = NULL;
2704     AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
2705     IO_STATUS_BLOCK stIoStatus;
2706
2707     __Enter
2708     {
2709
2710         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2711                       AFS_TRACE_LEVEL_VERBOSE_2,
2712                       "AFSVerifyEntry Verifying entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2713                       &DirEntry->NameInformation.FileName,
2714                       pObjectInfo->FileId.Cell,
2715                       pObjectInfo->FileId.Volume,
2716                       pObjectInfo->FileId.Vnode,
2717                       pObjectInfo->FileId.Unique);
2718
2719         ntStatus = AFSEvaluateTargetByID( pObjectInfo,
2720                                           AuthGroup,
2721                                           FALSE,
2722                                           &pDirEnumEntry);
2723
2724         if( !NT_SUCCESS( ntStatus))
2725         {
2726
2727             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2728                           AFS_TRACE_LEVEL_ERROR,
2729                           "AFSVerifyEntry Evaluate Target failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2730                           &DirEntry->NameInformation.FileName,
2731                           pObjectInfo->FileId.Cell,
2732                           pObjectInfo->FileId.Volume,
2733                           pObjectInfo->FileId.Vnode,
2734                           pObjectInfo->FileId.Unique,
2735                           ntStatus);
2736
2737             try_return( ntStatus);
2738         }
2739
2740         //
2741         // Check the data version of the file
2742         //
2743
2744         if( pObjectInfo->DataVersion.QuadPart == pDirEnumEntry->DataVersion.QuadPart)
2745         {
2746             if ( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2747             {
2748
2749                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2750                               AFS_TRACE_LEVEL_VERBOSE,
2751                               "AFSVerifyEntry No DV change %I64X for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2752                               pObjectInfo->DataVersion.QuadPart,
2753                               &DirEntry->NameInformation.FileName,
2754                               pObjectInfo->FileId.Cell,
2755                               pObjectInfo->FileId.Volume,
2756                               pObjectInfo->FileId.Vnode,
2757                               pObjectInfo->FileId.Unique);
2758
2759                 //
2760                 // We are ok, just get out
2761                 //
2762
2763                 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2764
2765                 try_return( ntStatus = STATUS_SUCCESS);
2766             }
2767         }
2768
2769         //
2770         // New data version so we will need to process the node based on the type
2771         //
2772
2773         switch( pDirEnumEntry->FileType)
2774         {
2775
2776             case AFS_FILE_TYPE_MOUNTPOINT:
2777             {
2778
2779                 //
2780                 // For a mount point we need to ensure the target is the same
2781                 //
2782
2783                 if( !AFSIsEqualFID( &pObjectInfo->TargetFileId,
2784                                     &pDirEnumEntry->TargetFileId))
2785                 {
2786
2787                 }
2788
2789                 //
2790                 // Update the metadata for the entry
2791                 //
2792
2793                 ntStatus = AFSUpdateMetaData( DirEntry,
2794                                               pDirEnumEntry);
2795
2796                 if( NT_SUCCESS( ntStatus))
2797                 {
2798
2799                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2800                 }
2801
2802                 break;
2803             }
2804
2805             case AFS_FILE_TYPE_SYMLINK:
2806             {
2807
2808                 //
2809                 // Update the metadata for the entry
2810                 //
2811
2812                 ntStatus = AFSUpdateMetaData( DirEntry,
2813                                               pDirEnumEntry);
2814
2815                 if( NT_SUCCESS( ntStatus))
2816                 {
2817
2818                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2819                 }
2820
2821                 break;
2822             }
2823
2824             case AFS_FILE_TYPE_FILE:
2825             {
2826                 FILE_OBJECT * pCCFileObject = NULL;
2827                 BOOLEAN bPurgeExtents = FALSE;
2828
2829                 if ( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
2830                 {
2831
2832                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2833                                   AFS_TRACE_LEVEL_VERBOSE,
2834                                   "AFSVerifyEntry DV Change %wZ FID %08lX-%08lX-%08lX-%08lX (%08lX != %08lX)\n",
2835                                   &DirEntry->NameInformation.FileName,
2836                                   pObjectInfo->FileId.Cell,
2837                                   pObjectInfo->FileId.Volume,
2838                                   pObjectInfo->FileId.Vnode,
2839                                   pObjectInfo->FileId.Unique,
2840                                   pObjectInfo->DataVersion.LowPart,
2841                                   pDirEnumEntry->DataVersion.LowPart
2842                                   );
2843
2844                     bPurgeExtents = TRUE;
2845                 }
2846
2847                 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2848                 {
2849
2850                     bPurgeExtents = TRUE;
2851
2852                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2853                                   AFS_TRACE_LEVEL_VERBOSE,
2854                                   "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2855                                   &DirEntry->NameInformation.FileName,
2856                                   pObjectInfo->FileId.Cell,
2857                                   pObjectInfo->FileId.Volume,
2858                                   pObjectInfo->FileId.Vnode,
2859                                   pObjectInfo->FileId.Unique);
2860
2861                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
2862                 }
2863
2864                 if( pObjectInfo->Fcb != NULL)
2865                 {
2866
2867                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2868                                   AFS_TRACE_LEVEL_VERBOSE,
2869                                   "AFSVerifyEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2870                                   &DirEntry->NameInformation.FileName,
2871                                   pObjectInfo->FileId.Cell,
2872                                   pObjectInfo->FileId.Volume,
2873                                   pObjectInfo->FileId.Vnode,
2874                                   pObjectInfo->FileId.Unique);
2875
2876                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
2877                                     TRUE);
2878
2879                     __try
2880                     {
2881
2882                         CcFlushCache( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2883                                       NULL,
2884                                       0,
2885                                       &stIoStatus);
2886
2887                         if( !NT_SUCCESS( stIoStatus.Status))
2888                         {
2889
2890                             AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2891                                           AFS_TRACE_LEVEL_ERROR,
2892                                           "AFSVerifyEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
2893                                           &DirEntry->NameInformation.FileName,
2894                                           pObjectInfo->FileId.Cell,
2895                                           pObjectInfo->FileId.Volume,
2896                                           pObjectInfo->FileId.Vnode,
2897                                           pObjectInfo->FileId.Unique,
2898                                           stIoStatus.Status,
2899                                           stIoStatus.Information);
2900
2901                             ntStatus = stIoStatus.Status;
2902                         }
2903
2904                         if ( bPurgeExtents &&
2905                              pObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
2906                         {
2907
2908                             if ( !CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2909                                                        NULL,
2910                                                        0,
2911                                                        FALSE))
2912                             {
2913
2914                                 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2915                                               AFS_TRACE_LEVEL_WARNING,
2916                                               "AFSVerifyEntry CcPurgeCacheSection failure %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2917                                               &DirEntry->NameInformation.FileName,
2918                                               pObjectInfo->FileId.Cell,
2919                                               pObjectInfo->FileId.Volume,
2920                                               pObjectInfo->FileId.Vnode,
2921                                               pObjectInfo->FileId.Unique);
2922
2923                                 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
2924                             }
2925                         }
2926                     }
2927                     __except( EXCEPTION_EXECUTE_HANDLER)
2928                     {
2929                         ntStatus = GetExceptionCode();
2930
2931                         AFSDbgLogMsg( 0,
2932                                       0,
2933                                       "EXCEPTION - AFSVerifyEntry CcFlushCache or CcPurgeCacheSection %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2934                                       &DirEntry->NameInformation.FileName,
2935                                       pObjectInfo->FileId.Cell,
2936                                       pObjectInfo->FileId.Volume,
2937                                       pObjectInfo->FileId.Vnode,
2938                                       pObjectInfo->FileId.Unique,
2939                                       ntStatus);
2940
2941                         SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
2942                     }
2943
2944                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
2945
2946                     if ( bPurgeExtents)
2947                     {
2948                         AFSFlushExtents( pObjectInfo->Fcb,
2949                                          AuthGroup);
2950                     }
2951
2952                     //
2953                     // Reacquire the Fcb to purge the cache
2954                     //
2955
2956                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2957                                   AFS_TRACE_LEVEL_VERBOSE,
2958                                   "AFSVerifyEntry Acquiring Fcb lock %p EXCL %08lX\n",
2959                                   &pObjectInfo->Fcb->NPFcb->Resource,
2960                                   PsGetCurrentThread());
2961
2962                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
2963                                     TRUE);
2964
2965                     //
2966                     // Update the metadata for the entry
2967                     //
2968
2969                     ntStatus = AFSUpdateMetaData( DirEntry,
2970                                                   pDirEnumEntry);
2971
2972                     if( !NT_SUCCESS( ntStatus))
2973                     {
2974
2975                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2976                                       AFS_TRACE_LEVEL_ERROR,
2977                                       "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
2978                                       &DirEntry->NameInformation.FileName,
2979                                       pObjectInfo->FileId.Cell,
2980                                       pObjectInfo->FileId.Volume,
2981                                       pObjectInfo->FileId.Vnode,
2982                                       pObjectInfo->FileId.Unique,
2983                                       ntStatus);
2984
2985                         break;
2986                     }
2987
2988                     //
2989                     // Update file sizes
2990                     //
2991
2992                     pObjectInfo->Fcb->Header.AllocationSize.QuadPart  = pObjectInfo->AllocationSize.QuadPart;
2993                     pObjectInfo->Fcb->Header.FileSize.QuadPart        = pObjectInfo->EndOfFile.QuadPart;
2994                     pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
2995
2996                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2997                                   AFS_TRACE_LEVEL_VERBOSE,
2998                                   "AFSVerifyEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
2999                                   &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3000                                   PsGetCurrentThread());
3001
3002                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3003                                     TRUE);
3004
3005                     pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
3006
3007                     if ( pCCFileObject != NULL)
3008                     {
3009                         CcSetFileSizes( pCCFileObject,
3010                                         (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
3011                     }
3012
3013                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3014                                   AFS_TRACE_LEVEL_VERBOSE,
3015                                   "AFSVerifyEntry Releasing Fcb SectionObject lock %p EXCL %08lX\n",
3016                                   &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3017                                   PsGetCurrentThread());
3018
3019                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
3020
3021                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
3022                 }
3023                 else
3024                 {
3025
3026                     //
3027                     // Update the metadata for the entry
3028                     //
3029
3030                     ntStatus = AFSUpdateMetaData( DirEntry,
3031                                                   pDirEnumEntry);
3032
3033                     if( !NT_SUCCESS( ntStatus))
3034                     {
3035
3036                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3037                                       AFS_TRACE_LEVEL_ERROR,
3038                                       "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
3039                                       &DirEntry->NameInformation.FileName,
3040                                       pObjectInfo->FileId.Cell,
3041                                       pObjectInfo->FileId.Volume,
3042                                       pObjectInfo->FileId.Vnode,
3043                                       pObjectInfo->FileId.Unique,
3044                                       ntStatus);
3045
3046                         break;
3047                     }
3048
3049                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3050                                   AFS_TRACE_LEVEL_WARNING,
3051                                   "AFSVerifyEntry Fcb NULL %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3052                                   &DirEntry->NameInformation.FileName,
3053                                   pObjectInfo->FileId.Cell,
3054                                   pObjectInfo->FileId.Volume,
3055                                   pObjectInfo->FileId.Vnode,
3056                                   pObjectInfo->FileId.Unique);
3057                 }
3058
3059                 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3060
3061                 break;
3062             }
3063
3064             case AFS_FILE_TYPE_DIRECTORY:
3065             {
3066
3067                 //
3068                 // For a directory or root entry flush the content of
3069                 // the directory enumeration.
3070                 //
3071
3072                 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3073                 {
3074
3075                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3076                                   AFS_TRACE_LEVEL_VERBOSE_2,
3077                                   "AFSVerifyEntry Validating directory content for entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3078                                   &DirEntry->NameInformation.FileName,
3079                                   pObjectInfo->FileId.Cell,
3080                                   pObjectInfo->FileId.Volume,
3081                                   pObjectInfo->FileId.Vnode,
3082                                   pObjectInfo->FileId.Unique);
3083
3084                     AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3085                                     TRUE);
3086
3087                     ntStatus = AFSValidateDirectoryCache( pObjectInfo,
3088                                                           AuthGroup);
3089
3090                     AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3091
3092                     if ( !NT_SUCCESS( ntStatus))
3093                     {
3094
3095                         try_return( ntStatus);
3096                     }
3097                 }
3098
3099                 //
3100                 // Update the metadata for the entry
3101                 //
3102
3103                 ntStatus = AFSUpdateMetaData( DirEntry,
3104                                               pDirEnumEntry);
3105
3106                 if( NT_SUCCESS( ntStatus))
3107                 {
3108
3109                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3110                 }
3111
3112                 break;
3113             }
3114
3115             case AFS_FILE_TYPE_DFSLINK:
3116             {
3117
3118                 UNICODE_STRING uniTargetName;
3119
3120                 //
3121                 // For a DFS link need to check the target name has not changed
3122                 //
3123
3124                 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
3125
3126                 uniTargetName.MaximumLength = uniTargetName.Length;
3127
3128                 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
3129
3130                 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3131                                 TRUE);
3132
3133                 if( DirEntry->NameInformation.TargetName.Length == 0 ||
3134                     RtlCompareUnicodeString( &uniTargetName,
3135                                              &DirEntry->NameInformation.TargetName,
3136                                              TRUE) != 0)
3137                 {
3138
3139                     //
3140                     // Update the target name
3141                     //
3142
3143                     ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3144                                                     &DirEntry->Flags,
3145                                                     uniTargetName.Buffer,
3146                                                     uniTargetName.Length);
3147
3148                     if( !NT_SUCCESS( ntStatus))
3149                     {
3150
3151                         AFSReleaseResource( &DirEntry->NonPaged->Lock);
3152
3153                         break;
3154                     }
3155                 }
3156
3157                 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3158
3159                 //
3160                 // Update the metadata for the entry
3161                 //
3162
3163                 ntStatus = AFSUpdateMetaData( DirEntry,
3164                                               pDirEnumEntry);
3165
3166                 if( NT_SUCCESS( ntStatus))
3167                 {
3168
3169                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3170                 }
3171
3172                 break;
3173             }
3174
3175             default:
3176
3177                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3178                               AFS_TRACE_LEVEL_WARNING,
3179                               "AFSVerifyEntry Attempt to verify node of type %d %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3180                               pObjectInfo->FileType,
3181                               &DirEntry->NameInformation.FileName,
3182                               pObjectInfo->FileId.Cell,
3183                               pObjectInfo->FileId.Volume,
3184                               pObjectInfo->FileId.Vnode,
3185                               pObjectInfo->FileId.Unique);
3186
3187                 break;
3188         }
3189
3190  try_exit:
3191
3192         if( pDirEnumEntry != NULL)
3193         {
3194
3195             AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_2_TAG);
3196         }
3197     }
3198
3199     return ntStatus;
3200 }
3201
3202 NTSTATUS
3203 AFSSetVolumeState( IN AFSVolumeStatusCB *VolumeStatus)
3204 {
3205
3206     NTSTATUS ntStatus = STATUS_SUCCESS;
3207     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
3208     ULONGLONG   ullIndex = 0;
3209     AFSVolumeCB *pVolumeCB = NULL;
3210     LONG lCount;
3211
3212     __Enter
3213     {
3214
3215         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3216                       AFS_TRACE_LEVEL_VERBOSE,
3217                       "AFSSetVolumeState Marking volume state %d Volume Cell %08lX Volume %08lX\n",
3218                       VolumeStatus->Online,
3219                       VolumeStatus->FileID.Cell,
3220                       VolumeStatus->FileID.Volume);
3221
3222         //
3223         // Need to locate the Fcb for the directory to purge
3224         //
3225
3226         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3227                       AFS_TRACE_LEVEL_VERBOSE,
3228                       "AFSSetVolumeState Acquiring RDR VolumeTreeLock lock %p SHARED %08lX\n",
3229                       &pDevExt->Specific.RDR.VolumeTreeLock,
3230                       PsGetCurrentThread());
3231
3232         AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
3233
3234         //
3235         // Locate the volume node
3236         //
3237
3238         ullIndex = AFSCreateHighIndex( &VolumeStatus->FileID);
3239
3240         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
3241                                        ullIndex,
3242                                        (AFSBTreeEntry **)&pVolumeCB);
3243
3244         if( pVolumeCB != NULL)
3245         {
3246
3247             lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
3248
3249             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3250                           AFS_TRACE_LEVEL_VERBOSE,
3251                           "AFSSetVolumeState Increment count on volume %p Cnt %d\n",
3252                           pVolumeCB,
3253                           lCount);
3254
3255             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3256
3257             //
3258             // Set the volume state accordingly
3259             //
3260
3261             if( VolumeStatus->Online)
3262             {
3263
3264                 InterlockedAnd( (LONG *)&(pVolumeCB->Flags), ~AFS_VOLUME_FLAGS_OFFLINE);
3265             }
3266             else
3267             {
3268
3269                 InterlockedOr( (LONG *)&(pVolumeCB->Flags), AFS_VOLUME_FLAGS_OFFLINE);
3270             }
3271         }
3272     }
3273
3274     return ntStatus;
3275 }
3276
3277 NTSTATUS
3278 AFSSetNetworkState( IN AFSNetworkStatusCB *NetworkStatus)
3279 {
3280
3281     NTSTATUS ntStatus = STATUS_SUCCESS;
3282
3283     __Enter
3284     {
3285
3286         if( AFSGlobalRoot == NULL)
3287         {
3288
3289             try_return( ntStatus);
3290         }
3291
3292         AFSAcquireExcl( AFSGlobalRoot->VolumeLock,
3293                         TRUE);
3294
3295         //
3296         // Set the network state according to the information
3297         //
3298
3299         if( NetworkStatus->Online)
3300         {
3301
3302             ClearFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3303         }
3304         else
3305         {
3306
3307             SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3308         }
3309
3310         AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3311
3312 try_exit:
3313
3314         NOTHING;
3315     }
3316
3317     return ntStatus;
3318 }
3319
3320 NTSTATUS
3321 AFSValidateDirectoryCache( IN AFSObjectInfoCB *ObjectInfo,
3322                            IN GUID *AuthGroup)
3323 {
3324
3325     NTSTATUS ntStatus = STATUS_SUCCESS;
3326     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3327     BOOLEAN  bAcquiredLock = FALSE;
3328     AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
3329
3330     __Enter
3331     {
3332
3333         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3334                       AFS_TRACE_LEVEL_VERBOSE,
3335                       "AFSValidateDirectoryCache Validating content for FID %08lX-%08lX-%08lX-%08lX\n",
3336                       ObjectInfo->FileId.Cell,
3337                       ObjectInfo->FileId.Volume,
3338                       ObjectInfo->FileId.Vnode,
3339                       ObjectInfo->FileId.Unique);
3340
3341         if( !ExIsResourceAcquiredLite( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock))
3342         {
3343
3344             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3345                           AFS_TRACE_LEVEL_VERBOSE,
3346                           "AFSValidateDirectoryCache Acquiring DirectoryNodeHdr.TreeLock lock %p EXCL %08lX\n",
3347                           ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3348                           PsGetCurrentThread());
3349
3350             AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3351                             TRUE);
3352
3353             bAcquiredLock = TRUE;
3354         }
3355
3356         //
3357         // Check for inconsistency between DirectoryNodeList and DirectoryNodeCount
3358         //
3359
3360         if ( ObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL &&
3361              ObjectInfo->Specific.Directory.DirectoryNodeCount > 0)
3362         {
3363
3364             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3365                           AFS_TRACE_LEVEL_ERROR,
3366                           "AFSValidateDirectoryCache Empty Node List but Non-Zero Node Count %d for dir FID %08lX-%08lX-%08lX-%08lX\n",
3367                           ObjectInfo->Specific.Directory.DirectoryNodeCount,
3368                           ObjectInfo->FileId.Cell,
3369                           ObjectInfo->FileId.Volume,
3370                           ObjectInfo->FileId.Vnode,
3371                           ObjectInfo->FileId.Unique);
3372         }
3373
3374         //
3375         // Reset the directory list information by clearing all valid entries
3376         //
3377
3378         pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3379
3380         while( pCurrentDirEntry != NULL)
3381         {
3382
3383             pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3384
3385             if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
3386             {
3387
3388                 //
3389                 // If this entry has been deleted then process it here
3390                 //
3391
3392                 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
3393                     pCurrentDirEntry->DirOpenReferenceCount <= 0)
3394                 {
3395
3396                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3397                                   AFS_TRACE_LEVEL_VERBOSE,
3398                                   "AFSValidateDirectoryCache Deleting dir entry %p name %wZ\n",
3399                                   pCurrentDirEntry,
3400                                   &pCurrentDirEntry->NameInformation.FileName);
3401
3402                     AFSDeleteDirEntry( ObjectInfo,
3403                                        pCurrentDirEntry);
3404                 }
3405                 else
3406                 {
3407
3408                     ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID);
3409
3410                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3411                                   AFS_TRACE_LEVEL_VERBOSE,
3412                                   "AFSValidateDirectoryCache Clear VALID flag on DE %p Reference count %08lX\n",
3413                                   pCurrentDirEntry,
3414                                   pCurrentDirEntry->DirOpenReferenceCount);
3415
3416                     //
3417                     // We pull the short name from the parent tree since it could change below
3418                     //
3419
3420                     if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
3421                     {
3422
3423                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3424                                       AFS_TRACE_LEVEL_VERBOSE,
3425                                       "AFSValidateDirectoryCache Removing DE %p (%08lX) from shortname tree for %wZ\n",
3426                                       pCurrentDirEntry,
3427                                       pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3428                                       &pCurrentDirEntry->NameInformation.FileName);
3429
3430                         AFSRemoveShortNameDirEntry( &ObjectInfo->Specific.Directory.ShortNameTree,
3431                                                     pCurrentDirEntry);
3432
3433                         ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3434                     }
3435                 }
3436             }
3437
3438             pCurrentDirEntry = pNextDirEntry;
3439         }
3440
3441         //
3442         // Reget the directory contents
3443         //
3444
3445         ntStatus = AFSVerifyDirectoryContent( ObjectInfo,
3446                                               AuthGroup);
3447
3448         if ( !NT_SUCCESS( ntStatus))
3449         {
3450             try_return( ntStatus);
3451         }
3452
3453         //
3454         // Now start again and tear down any entries not valid
3455         //
3456
3457         pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3458
3459         while( pCurrentDirEntry != NULL)
3460         {
3461
3462             pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3463
3464             if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID))
3465             {
3466
3467                 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3468                     !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME) &&
3469                     pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex > 0)
3470                 {
3471
3472                     if( ObjectInfo->Specific.Directory.ShortNameTree == NULL)
3473                     {
3474
3475                         ObjectInfo->Specific.Directory.ShortNameTree = pCurrentDirEntry;
3476
3477                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3478                                       AFS_TRACE_LEVEL_VERBOSE,
3479                                       "AFSValidateDirectoryCache Insert DE %p to head of shortname tree for %wZ\n",
3480                                       pCurrentDirEntry,
3481                                       &pCurrentDirEntry->NameInformation.FileName);
3482
3483                         SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3484                     }
3485                     else
3486                     {
3487
3488                         if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfo->Specific.Directory.ShortNameTree,
3489                                                                      pCurrentDirEntry)))
3490                         {
3491                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3492                                           AFS_TRACE_LEVEL_VERBOSE,
3493                                           "AFSValidateDirectoryCache Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
3494                                           pCurrentDirEntry,
3495                                           pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3496                                           &pCurrentDirEntry->NameInformation.FileName);
3497                         }
3498                         else
3499                         {
3500                             SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3501
3502                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3503                                           AFS_TRACE_LEVEL_VERBOSE,
3504                                           "AFSValidateDirectoryCache Insert DE %p to shortname tree for %wZ\n",
3505                                           pCurrentDirEntry,
3506                                           &pCurrentDirEntry->NameInformation.FileName);
3507                         }
3508                     }
3509                 }
3510
3511                 pCurrentDirEntry = pNextDirEntry;
3512
3513                 continue;
3514             }
3515
3516             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3517                           AFS_TRACE_LEVEL_VERBOSE,
3518                           "AFSValidateDirectoryCache Processing INVALID DE %p Reference count %08lX\n",
3519                           pCurrentDirEntry,
3520                           pCurrentDirEntry->DirOpenReferenceCount);
3521
3522             if( pCurrentDirEntry->DirOpenReferenceCount <= 0)
3523             {
3524
3525                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3526                               AFS_TRACE_LEVEL_VERBOSE,
3527                               "AFSValidateDirectoryCache Deleting dir entry %wZ from parent FID %08lX-%08lX-%08lX-%08lX\n",
3528                               &pCurrentDirEntry->NameInformation.FileName,
3529                               ObjectInfo->FileId.Cell,
3530                               ObjectInfo->FileId.Volume,
3531                               ObjectInfo->FileId.Vnode,
3532                               ObjectInfo->FileId.Unique);
3533
3534                 AFSDeleteDirEntry( ObjectInfo,
3535                                    pCurrentDirEntry);
3536             }
3537             else
3538             {
3539
3540                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3541                               AFS_TRACE_LEVEL_VERBOSE,
3542                               "AFSValidateDirectoryCache Setting dir entry %p Name %wZ DELETED in parent FID %08lX-%08lX-%08lX-%08lX\n",
3543                               pCurrentDirEntry,
3544                               &pCurrentDirEntry->NameInformation.FileName,
3545                               ObjectInfo->FileId.Cell,
3546                               ObjectInfo->FileId.Volume,
3547                               ObjectInfo->FileId.Vnode,
3548                               ObjectInfo->FileId.Unique);
3549
3550                 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
3551
3552                 AFSRemoveNameEntry( ObjectInfo,
3553                                     pCurrentDirEntry);
3554             }
3555
3556             pCurrentDirEntry = pNextDirEntry;
3557         }
3558
3559 #if DBG
3560         if( !AFSValidateDirList( ObjectInfo))
3561         {
3562
3563             AFSPrint("AFSValidateDirectoryCache Invalid count ...\n");
3564         }
3565 #endif
3566
3567 try_exit:
3568
3569         if( bAcquiredLock)
3570         {
3571
3572             AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3573         }
3574     }
3575
3576     return ntStatus;
3577 }
3578
3579 BOOLEAN
3580 AFSIsVolumeFID( IN AFSFileID *FileID)
3581 {
3582
3583     BOOLEAN bIsVolume = FALSE;
3584
3585     if( FileID->Vnode == 1 &&
3586         FileID->Unique == 1)
3587     {
3588
3589         bIsVolume = TRUE;
3590     }
3591
3592     return bIsVolume;
3593 }
3594
3595 BOOLEAN
3596 AFSIsFinalNode( IN AFSFcb *Fcb)
3597 {
3598
3599     BOOLEAN bIsFinalNode = FALSE;
3600
3601     if( Fcb->Header.NodeTypeCode == AFS_ROOT_FCB ||
3602         Fcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB ||
3603         Fcb->Header.NodeTypeCode == AFS_FILE_FCB ||
3604         Fcb->Header.NodeTypeCode == AFS_DFS_LINK_FCB ||
3605         Fcb->Header.NodeTypeCode == AFS_INVALID_FCB )
3606     {
3607
3608         bIsFinalNode = TRUE;
3609     }
3610     else
3611     {
3612
3613         ASSERT( Fcb->Header.NodeTypeCode == AFS_MOUNT_POINT_FCB ||
3614                 Fcb->Header.NodeTypeCode == AFS_SYMBOLIC_LINK_FCB);
3615     }
3616
3617     return bIsFinalNode;
3618 }
3619
3620 NTSTATUS
3621 AFSUpdateMetaData( IN AFSDirectoryCB *DirEntry,
3622                    IN AFSDirEnumEntry *DirEnumEntry)
3623 {
3624
3625     NTSTATUS ntStatus = STATUS_SUCCESS;
3626     UNICODE_STRING uniTargetName;
3627     AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
3628
3629     __Enter
3630     {
3631
3632         pObjectInfo->TargetFileId = DirEnumEntry->TargetFileId;
3633
3634         pObjectInfo->Expiration = DirEnumEntry->Expiration;
3635
3636         pObjectInfo->DataVersion = DirEnumEntry->DataVersion;
3637
3638         pObjectInfo->FileType = DirEnumEntry->FileType;
3639
3640         pObjectInfo->CreationTime = DirEnumEntry->CreationTime;
3641
3642         pObjectInfo->LastAccessTime = DirEnumEntry->LastAccessTime;
3643
3644         pObjectInfo->LastWriteTime = DirEnumEntry->LastWriteTime;
3645
3646         pObjectInfo->ChangeTime = DirEnumEntry->ChangeTime;
3647
3648         pObjectInfo->EndOfFile = DirEnumEntry->EndOfFile;
3649
3650         pObjectInfo->AllocationSize = DirEnumEntry->AllocationSize;
3651
3652         pObjectInfo->FileAttributes = DirEnumEntry->FileAttributes;
3653
3654         if( pObjectInfo->FileType == AFS_FILE_TYPE_MOUNTPOINT)
3655         {
3656
3657             pObjectInfo->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
3658         }
3659
3660         if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK ||
3661             pObjectInfo->FileType == AFS_FILE_TYPE_DFSLINK)
3662         {
3663
3664             pObjectInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
3665         }
3666
3667         pObjectInfo->EaSize = DirEnumEntry->EaSize;
3668
3669         pObjectInfo->Links = DirEnumEntry->Links;
3670
3671         if( DirEnumEntry->TargetNameLength > 0 &&
3672             ( DirEntry->NameInformation.TargetName.Length != DirEnumEntry->TargetNameLength ||
3673               DirEntry->ObjectInformation->DataVersion.QuadPart != DirEnumEntry->DataVersion.QuadPart))
3674         {
3675
3676             //
3677             // Update the target name information if needed
3678             //
3679
3680             uniTargetName.Length = (USHORT)DirEnumEntry->TargetNameLength;
3681
3682             uniTargetName.MaximumLength = uniTargetName.Length;
3683
3684             uniTargetName.Buffer = (WCHAR *)((char *)DirEnumEntry + DirEnumEntry->TargetNameOffset);
3685
3686             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3687                             TRUE);
3688
3689             if( DirEntry->NameInformation.TargetName.Length == 0 ||
3690                 RtlCompareUnicodeString( &uniTargetName,
3691                                          &DirEntry->NameInformation.TargetName,
3692                                          TRUE) != 0)
3693             {
3694
3695                 //
3696                 // Update the target name
3697                 //
3698
3699                 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3700                                                 &DirEntry->Flags,
3701                                                 uniTargetName.Buffer,
3702                                                 uniTargetName.Length);
3703
3704                 if( !NT_SUCCESS( ntStatus))
3705                 {
3706
3707                     AFSReleaseResource( &DirEntry->NonPaged->Lock);
3708
3709                     try_return( ntStatus);
3710                 }
3711             }
3712
3713             AFSReleaseResource( &DirEntry->NonPaged->Lock);
3714         }
3715         else if( DirEntry->NameInformation.TargetName.Length > 0 &&
3716                  DirEntry->ObjectInformation->DataVersion.QuadPart != DirEnumEntry->DataVersion.QuadPart)
3717         {
3718
3719             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3720                             TRUE);
3721
3722             if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER) &&
3723                 DirEntry->NameInformation.TargetName.Buffer != NULL)
3724             {
3725                 AFSExFreePoolWithTag( DirEntry->NameInformation.TargetName.Buffer, AFS_NAME_BUFFER_FIVE_TAG);
3726             }
3727
3728             ClearFlag( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER);
3729
3730             DirEntry->NameInformation.TargetName.Length = 0;
3731             DirEntry->NameInformation.TargetName.MaximumLength = 0;
3732             DirEntry->NameInformation.TargetName.Buffer = NULL;
3733
3734             AFSReleaseResource( &DirEntry->NonPaged->Lock);
3735         }
3736
3737 try_exit:
3738
3739         NOTHING;
3740     }
3741
3742     return ntStatus;
3743 }
3744
3745 NTSTATUS
3746 AFSValidateEntry( IN AFSDirectoryCB *DirEntry,
3747                   IN GUID *AuthGroup,
3748                   IN BOOLEAN FastCall,
3749                   IN BOOLEAN bSafeToPurge)
3750 {
3751
3752     NTSTATUS ntStatus = STATUS_SUCCESS;
3753     LARGE_INTEGER liSystemTime;
3754     AFSDirEnumEntry *pDirEnumEntry = NULL;
3755     AFSFcb *pCurrentFcb = NULL;
3756     BOOLEAN bReleaseFcb = FALSE;
3757     AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
3758
3759     __Enter
3760     {
3761
3762         //
3763         // If we have an Fcb hanging off the directory entry then be sure to acquire the locks in the