fbdfa31042efc3241071bbbca45a6a44754a5430
[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 ULONG Code,
55                     IN PEXCEPTION_POINTERS ExceptPtrs)
56 {
57
58     PEXCEPTION_RECORD ExceptRec;
59     PCONTEXT Context;
60
61     __try
62     {
63
64         ExceptRec = ExceptPtrs->ExceptionRecord;
65
66         Context = ExceptPtrs->ContextRecord;
67
68         AFSDbgLogMsg( 0,
69                       0,
70                       "AFSExceptionFilter (Library) - EXR %p CXR %p Code %08lX Address %p Routine %p\n",
71                       ExceptRec,
72                       Context,
73                       ExceptRec->ExceptionCode,
74                       ExceptRec->ExceptionAddress,
75                       (void *)AFSExceptionFilter);
76
77         DbgPrint("**** Exception Caught in AFS Redirector Library ****\n");
78
79         DbgPrint("\n\nPerform the following WnDbg Cmds:\n");
80         DbgPrint("\n\t.exr %p ;  .cxr %p\n\n", ExceptRec, Context);
81
82         DbgPrint("**** Exception Complete from AFS Redirector Library ****\n");
83
84         if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION))
85         {
86
87             KeBugCheck( (ULONG)-2);
88         }
89         else
90         {
91
92             AFSBreakPoint();
93         }
94     }
95     __except( EXCEPTION_EXECUTE_HANDLER)
96     {
97
98         NOTHING;
99     }
100
101     return EXCEPTION_EXECUTE_HANDLER;
102 }
103
104 //
105 // Function: AFSLibExAllocatePoolWithTag()
106 //
107 // Purpose: Allocate Pool Memory.  If BugCheck Exception flag
108 //          is configured on, then bugcheck the system if
109 //          a memory allocation fails.  The routine should be
110 //          used for all memory allocations that are to be freed
111 //          when the library is unloaded.  Memory allocations that
112 //          are to survive library unload and reload should be
113 //          performed using AFSExAllocatePoolWithTag() which is
114 //          provided by the AFS Framework.
115 //
116 // Parameters:
117 //                POOL_TYPE PoolType - Paged or NonPaged
118 //                SIZE_T NumberOfBytes - requested allocation size
119 //                ULONG  Tag - Pool Allocation Tag to be applied for tracking
120 //
121 // Return:
122 //                void * - the memory allocation
123 //
124
125 void *
126 AFSLibExAllocatePoolWithTag( IN POOL_TYPE  PoolType,
127                              IN SIZE_T  NumberOfBytes,
128                              IN ULONG  Tag)
129 {
130
131     void *pBuffer = NULL;
132
133     pBuffer = ExAllocatePoolWithTag( PoolType,
134                                      NumberOfBytes,
135                                      Tag);
136
137     if( pBuffer == NULL)
138     {
139
140         if( BooleanFlagOn( AFSDebugFlags, AFS_DBG_BUGCHECK_EXCEPTION))
141         {
142
143             KeBugCheck( (ULONG)-2);
144         }
145         else
146         {
147
148             AFSDbgLogMsg( 0,
149                           0,
150                           "AFSLibExAllocatePoolWithTag failure Type %08lX Size %08lX Tag %08lX %08lX\n",
151                           PoolType,
152                           NumberOfBytes,
153                           Tag,
154                           PsGetCurrentThread());
155
156             AFSBreakPoint();
157         }
158     }
159
160     return pBuffer;
161 }
162
163 //
164 // Function: AFSAcquireExcl()
165 //
166 // Purpose: Called to acquire a resource exclusive with optional wait
167 //
168 // Parameters:
169 //                PERESOURCE Resource - Resource to acquire
170 //                BOOLEAN Wait - Whether to block
171 //
172 // Return:
173 //                BOOLEAN - Whether the mask was acquired
174 //
175
176 BOOLEAN
177 AFSAcquireExcl( IN PERESOURCE Resource,
178                 IN BOOLEAN wait)
179 {
180
181     BOOLEAN bStatus = FALSE;
182
183     //
184     // Normal kernel APCs must be disabled before calling
185     // ExAcquireResourceExclusiveLite. Otherwise a bugcheck occurs.
186     //
187
188     KeEnterCriticalRegion();
189
190     bStatus = ExAcquireResourceExclusiveLite( Resource,
191                                               wait);
192
193     if( !bStatus)
194     {
195
196         KeLeaveCriticalRegion();
197     }
198
199     return bStatus;
200 }
201
202 BOOLEAN
203 AFSAcquireSharedStarveExclusive( IN PERESOURCE Resource,
204                                  IN BOOLEAN Wait)
205 {
206
207     BOOLEAN bStatus = FALSE;
208
209     KeEnterCriticalRegion();
210
211     bStatus = ExAcquireSharedStarveExclusive( Resource,
212                                               Wait);
213
214     if( !bStatus)
215     {
216
217         KeLeaveCriticalRegion();
218     }
219
220     return bStatus;
221 }
222
223 //
224 // Function: AFSAcquireShared()
225 //
226 // Purpose: Called to acquire a resource shared with optional wait
227 //
228 // Parameters:
229 //                PERESOURCE Resource - Resource to acquire
230 //                BOOLEAN Wait - Whether to block
231 //
232 // Return:
233 //                BOOLEAN - Whether the mask was acquired
234 //
235
236 BOOLEAN
237 AFSAcquireShared( IN PERESOURCE Resource,
238                   IN BOOLEAN wait)
239 {
240
241     BOOLEAN bStatus = FALSE;
242
243     KeEnterCriticalRegion();
244
245     bStatus = ExAcquireResourceSharedLite( Resource,
246                                            wait);
247
248     if( !bStatus)
249     {
250
251         KeLeaveCriticalRegion();
252     }
253
254     return bStatus;
255 }
256
257 //
258 // Function: AFSReleaseResource()
259 //
260 // Purpose: Called to release a resource
261 //
262 // Parameters:
263 //                PERESOURCE Resource - Resource to release
264 //
265 // Return:
266 //                None
267 //
268
269 void
270 AFSReleaseResource( IN PERESOURCE Resource)
271 {
272
273     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
274                   AFS_TRACE_LEVEL_VERBOSE,
275                   "AFSReleaseResource Releasing lock %08lX Thread %08lX\n",
276                   Resource,
277                   PsGetCurrentThread());
278
279     ExReleaseResourceLite( Resource);
280
281     KeLeaveCriticalRegion();
282
283     return;
284 }
285
286 void
287 AFSConvertToShared( IN PERESOURCE Resource)
288 {
289
290     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
291                   AFS_TRACE_LEVEL_VERBOSE,
292                   "AFSConvertToShared Converting lock %08lX Thread %08lX\n",
293                   Resource,
294                   PsGetCurrentThread());
295
296     ExConvertExclusiveToSharedLite( Resource);
297
298     return;
299 }
300
301 //
302 // Function: AFSCompleteRequest
303 //
304 // Description:
305 //
306 //      This function completes irps
307 //
308 // Return:
309 //
310 //      A status is returned for the function
311 //
312
313 void
314 AFSCompleteRequest( IN PIRP Irp,
315                     IN ULONG Status)
316 {
317
318     Irp->IoStatus.Status = Status;
319
320     IoCompleteRequest( Irp,
321                        IO_NO_INCREMENT);
322
323     return;
324 }
325
326 //
327 // Function: AFSGenerateCRC
328 //
329 // Description:
330 //
331 //      Given a device and filename this function generates a CRC
332 //
333 // Return:
334 //
335 //      A status is returned for the function
336 //
337
338 ULONG
339 AFSGenerateCRC( IN PUNICODE_STRING FileName,
340                 IN BOOLEAN UpperCaseName)
341 {
342
343     ULONG ulCRC = 0;
344     NTSTATUS ntStatus = STATUS_SUCCESS;
345
346     ntStatus = RtlHashUnicodeString( FileName,
347                                      UpperCaseName,
348                                      HASH_STRING_ALGORITHM_DEFAULT,
349                                      &ulCRC);
350
351     if( !NT_SUCCESS( ntStatus))
352     {
353         ulCRC = 0;
354     }
355
356     return ulCRC;
357 }
358
359 void *
360 AFSLockSystemBuffer( IN PIRP Irp,
361                      IN ULONG Length)
362 {
363
364     NTSTATUS Status = STATUS_SUCCESS;
365     void *pAddress = NULL;
366
367     if( Irp->MdlAddress != NULL)
368     {
369
370         pAddress = MmGetSystemAddressForMdlSafe( Irp->MdlAddress,
371                                                  NormalPagePriority);
372     }
373     else if( Irp->AssociatedIrp.SystemBuffer != NULL)
374     {
375
376         pAddress = Irp->AssociatedIrp.SystemBuffer;
377     }
378     else if( Irp->UserBuffer != NULL)
379     {
380
381         Irp->MdlAddress = IoAllocateMdl( Irp->UserBuffer,
382                                          Length,
383                                          FALSE,
384                                          FALSE,
385                                          Irp);
386
387         if( Irp->MdlAddress != NULL)
388         {
389
390             //
391             //  Lock the new Mdl in memory.
392             //
393
394             __try
395             {
396                 PIO_STACK_LOCATION pIoStack;
397                 pIoStack = IoGetCurrentIrpStackLocation( Irp);
398
399
400                 MmProbeAndLockPages( Irp->MdlAddress, KernelMode,
401                                      (pIoStack->MajorFunction == IRP_MJ_READ) ? IoWriteAccess : IoReadAccess);
402
403                 pAddress = MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority );
404
405             }
406             __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
407             {
408
409                 IoFreeMdl( Irp->MdlAddress );
410                 Irp->MdlAddress = NULL;
411                 pAddress = NULL;
412             }
413         }
414     }
415
416     return pAddress;
417 }
418
419 void *
420 AFSLockUserBuffer( IN void *UserBuffer,
421                    IN ULONG BufferLength,
422                                    OUT MDL ** Mdl)
423 {
424
425     NTSTATUS ntStatus = STATUS_SUCCESS;
426     void *pAddress = NULL;
427     MDL *pMdl = NULL;
428
429     __Enter
430     {
431
432         pMdl = IoAllocateMdl( UserBuffer,
433                               BufferLength,
434                               FALSE,
435                               FALSE,
436                               NULL);
437
438             if( pMdl == NULL)
439             {
440
441                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
442             }
443
444         //
445         //  Lock the new Mdl in memory.
446         //
447
448         __try
449         {
450
451             MmProbeAndLockPages( pMdl,
452                                  KernelMode,
453                                  IoWriteAccess);
454
455             pAddress = MmGetSystemAddressForMdlSafe( pMdl,
456                                                      NormalPagePriority);
457         }
458         __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
459         {
460
461             IoFreeMdl( pMdl);
462             pMdl = NULL;
463             pAddress = NULL;
464         }
465
466         if( pMdl != NULL)
467         {
468
469             *Mdl = pMdl;
470         }
471
472 try_exit:
473
474         NOTHING;
475     }
476
477     return pAddress;
478 }
479
480 void *
481 AFSMapToService( IN PIRP Irp,
482                  IN ULONG ByteCount)
483 {
484
485     NTSTATUS ntStatus = STATUS_SUCCESS;
486     void *pMappedBuffer = NULL;
487     AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
488     KAPC stApcState;
489
490     __Enter
491     {
492
493         if( pDevExt->Specific.Control.ServiceProcess == NULL)
494         {
495
496             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
497         }
498
499         if( Irp->MdlAddress == NULL)
500         {
501
502             if( AFSLockSystemBuffer( Irp,
503                                      ByteCount) == NULL)
504             {
505
506                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
507             }
508         }
509
510         //
511         // Attach to the service process for mapping
512         //
513
514         KeStackAttachProcess( pDevExt->Specific.Control.ServiceProcess,
515                               (PRKAPC_STATE)&stApcState);
516
517         pMappedBuffer = MmMapLockedPagesSpecifyCache( Irp->MdlAddress,
518                                                       UserMode,
519                                                       MmCached,
520                                                       NULL,
521                                                       FALSE,
522                                                       NormalPagePriority);
523
524         KeUnstackDetachProcess( (PRKAPC_STATE)&stApcState);
525
526 try_exit:
527
528         NOTHING;
529     }
530
531     return pMappedBuffer;
532 }
533
534 NTSTATUS
535 AFSUnmapServiceMappedBuffer( IN void *MappedBuffer,
536                              IN PMDL Mdl)
537 {
538
539     NTSTATUS ntStatus = STATUS_SUCCESS;
540     void *pMappedBuffer = NULL;
541     AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
542     KAPC stApcState;
543
544     __Enter
545     {
546
547         if( pDevExt->Specific.Control.ServiceProcess == NULL)
548         {
549
550             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
551         }
552
553         if( Mdl != NULL)
554         {
555
556             //
557             // Attach to the service process for mapping
558             //
559
560             KeStackAttachProcess( pDevExt->Specific.Control.ServiceProcess,
561                                   (PRKAPC_STATE)&stApcState);
562
563             MmUnmapLockedPages( MappedBuffer,
564                                 Mdl);
565
566             KeUnstackDetachProcess( (PRKAPC_STATE)&stApcState);
567         }
568
569 try_exit:
570
571         NOTHING;
572     }
573
574     return ntStatus;
575 }
576
577 NTSTATUS
578 AFSInitializeLibraryDevice()
579 {
580
581     NTSTATUS ntStatus = STATUS_SUCCESS;
582     AFSDeviceExt *pDeviceExt = NULL;
583
584     __Enter
585     {
586
587         pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
588
589         //
590         // The PIOCtl file name
591         //
592
593         RtlInitUnicodeString( &AFSPIOCtlName,
594                               AFS_PIOCTL_FILE_INTERFACE_NAME);
595
596         //
597         // And the global root share name
598         //
599
600         RtlInitUnicodeString( &AFSGlobalRootName,
601                               AFS_GLOBAL_ROOT_SHARE_NAME);
602
603     }
604
605     return ntStatus;
606 }
607
608 NTSTATUS
609 AFSRemoveLibraryDevice()
610 {
611
612     NTSTATUS ntStatus = STATUS_SUCCESS;
613
614     __Enter
615     {
616
617     }
618
619     return ntStatus;
620 }
621
622 NTSTATUS
623 AFSDefaultDispatch( IN PDEVICE_OBJECT DeviceObject,
624                     IN PIRP Irp)
625 {
626
627     NTSTATUS            ntStatus = STATUS_INVALID_DEVICE_REQUEST;
628     PIO_STACK_LOCATION  pIrpSp = IoGetCurrentIrpStackLocation( Irp);
629
630     AFSCompleteRequest( Irp,
631                         ntStatus);
632
633     return ntStatus;
634 }
635
636 NTSTATUS
637 AFSInitializeGlobalDirectoryEntries()
638 {
639
640     NTSTATUS ntStatus = STATUS_SUCCESS;
641     AFSDirectoryCB *pDirNode = NULL;
642     ULONG ulEntryLength = 0;
643     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
644     AFSObjectInfoCB *pObjectInfoCB = NULL;
645     AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
646     LONG lCount;
647
648     __Enter
649     {
650
651         //
652         // Initialize the global . entry
653         //
654
655         pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
656                                                0);
657
658         if( pObjectInfoCB == NULL)
659         {
660
661             AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
662                           AFS_TRACE_LEVEL_ERROR,
663                           "AFSInitializeGlobalDirectory AFSAllocateObjectInfo failure %08lX\n",
664                           ntStatus);
665
666             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
667         }
668
669         lCount = InterlockedIncrement( &pObjectInfoCB->ObjectReferenceCount);
670
671         AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
672                       AFS_TRACE_LEVEL_VERBOSE,
673                       "AFSInitializeGlobalDirectoryEntries Increment count on object %08lX Cnt %d\n",
674                       pObjectInfoCB,
675                       lCount);
676
677         ntStatus = STATUS_SUCCESS;
678
679         ulEntryLength = sizeof( AFSDirectoryCB) +
680                                      sizeof( WCHAR);
681
682         pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
683                                                                   ulEntryLength,
684                                                                   AFS_DIR_ENTRY_TAG);
685
686         if( pDirNode == NULL)
687         {
688
689             AFSDeleteObjectInfo( pObjectInfoCB);
690
691             AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
692                           AFS_TRACE_LEVEL_ERROR,
693                           "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_TAG allocation failure\n");
694
695             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
696         }
697
698         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
699                                                                                    sizeof( AFSNonPagedDirectoryCB),
700                                                                                    AFS_DIR_ENTRY_NP_TAG);
701
702         if( pNonPagedDirEntry == NULL)
703         {
704
705             ExFreePool( pDirNode);
706
707             AFSDeleteObjectInfo( pObjectInfoCB);
708
709             AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
710                           AFS_TRACE_LEVEL_ERROR,
711                           "AFSInitializeGlobalDirectory AFS_DIR_ENTRY_NP_TAG allocation failure\n");
712
713             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
714         }
715
716         RtlZeroMemory( pDirNode,
717                        ulEntryLength);
718
719         RtlZeroMemory( pNonPagedDirEntry,
720                        sizeof( AFSNonPagedDirectoryCB));
721
722         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
723
724         pDirNode->NonPaged = pNonPagedDirEntry;
725
726         pDirNode->ObjectInformation = pObjectInfoCB;
727
728         //
729         // Set valid entry
730         //
731
732         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE | AFS_DIR_ENTRY_FAKE | AFS_DIR_ENTRY_VALID);
733
734         pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_DOT_INDEX;
735
736         //
737         // Setup the names in the entry
738         //
739
740         pDirNode->NameInformation.FileName.Length = sizeof( WCHAR);
741
742         pDirNode->NameInformation.FileName.MaximumLength = sizeof( WCHAR);
743
744         pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
745
746         pDirNode->NameInformation.FileName.Buffer[ 0] = L'.';
747
748         //
749         // Populate the rest of the data
750         //
751
752         pObjectInfoCB->FileType = AFS_FILE_TYPE_DIRECTORY;
753
754         pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
755
756         AFSGlobalDotDirEntry = pDirNode;
757
758         //
759         // Now the .. entry
760         //
761
762         pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
763                                                0);
764
765         if( pObjectInfoCB == NULL)
766         {
767
768             AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
769                           AFS_TRACE_LEVEL_ERROR,
770                           "AFSInitializeGlobalDirectory AFSAllocateObjectInfo (2) failure %08lX\n",
771                           ntStatus);
772
773             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
774         }
775
776         lCount = InterlockedIncrement( &pObjectInfoCB->ObjectReferenceCount);
777
778         AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
779                       AFS_TRACE_LEVEL_VERBOSE,
780                       "AFSInitializeGlobalDirectoryEntries Increment count on object %08lX Cnt %d\n",
781                       pObjectInfoCB,
782                       lCount);
783
784         ntStatus = STATUS_SUCCESS;
785
786         ulEntryLength = sizeof( AFSDirectoryCB) +
787                                      ( 2 * sizeof( WCHAR));
788
789         pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
790                                                                   ulEntryLength,
791                                                                   AFS_DIR_ENTRY_TAG);
792
793         if( pDirNode == NULL)
794         {
795
796             AFSDeleteObjectInfo( pObjectInfoCB);
797
798             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
799         }
800
801         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
802                                                                                    sizeof( AFSNonPagedDirectoryCB),
803                                                                                    AFS_DIR_ENTRY_NP_TAG);
804
805         if( pNonPagedDirEntry == NULL)
806         {
807
808             ExFreePool( pDirNode);
809
810             AFSDeleteObjectInfo( pObjectInfoCB);
811
812             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
813         }
814
815         RtlZeroMemory( pDirNode,
816                        ulEntryLength);
817
818         RtlZeroMemory( pNonPagedDirEntry,
819                        sizeof( AFSNonPagedDirectoryCB));
820
821         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
822
823         pDirNode->NonPaged = pNonPagedDirEntry;
824
825         pDirNode->ObjectInformation = pObjectInfoCB;
826
827         //
828         // Set valid entry
829         //
830
831         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE | AFS_DIR_ENTRY_FAKE | AFS_DIR_ENTRY_VALID);
832
833         pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_DOT_DOT_INDEX;
834
835         //
836         // Setup the names in the entry
837         //
838
839         pDirNode->NameInformation.FileName.Length = 2 * sizeof( WCHAR);
840
841         pDirNode->NameInformation.FileName.MaximumLength = 2 * sizeof( WCHAR);
842
843         pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
844
845         pDirNode->NameInformation.FileName.Buffer[ 0] = L'.';
846
847         pDirNode->NameInformation.FileName.Buffer[ 1] = L'.';
848
849         //
850         // Populate the rest of the data
851         //
852
853         pObjectInfoCB->FileType = AFS_FILE_TYPE_DIRECTORY;
854
855         pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
856
857         AFSGlobalDotDotDirEntry = pDirNode;
858
859 try_exit:
860
861         if( !NT_SUCCESS( ntStatus))
862         {
863
864             if( AFSGlobalDotDirEntry != NULL)
865             {
866
867                 AFSDeleteObjectInfo( AFSGlobalDotDirEntry->ObjectInformation);
868
869                 ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
870
871                 ExFreePool( AFSGlobalDotDirEntry->NonPaged);
872
873                 ExFreePool( AFSGlobalDotDirEntry);
874
875                 AFSGlobalDotDirEntry = NULL;
876             }
877
878             if( AFSGlobalDotDotDirEntry != NULL)
879             {
880
881                 AFSDeleteObjectInfo( AFSGlobalDotDotDirEntry->ObjectInformation);
882
883                 ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
884
885                 ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
886
887                 ExFreePool( AFSGlobalDotDotDirEntry);
888
889                 AFSGlobalDotDotDirEntry = NULL;
890             }
891         }
892     }
893
894     return ntStatus;
895 }
896
897 AFSDirectoryCB *
898 AFSInitDirEntry( IN AFSObjectInfoCB *ParentObjectInfo,
899                  IN PUNICODE_STRING FileName,
900                  IN PUNICODE_STRING TargetName,
901                  IN AFSDirEnumEntry *DirEnumEntry,
902                  IN ULONG FileIndex)
903 {
904
905     AFSDirectoryCB *pDirNode = NULL;
906     NTSTATUS ntStatus = STATUS_SUCCESS;
907     ULONG ulEntryLength = 0;
908     AFSDirEnumEntry *pDirEnumCB = NULL;
909     AFSFileID stTargetFileID;
910     AFSFcb *pVcb = NULL;
911     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
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 %08lX Parent Object %08lX for %wZ\n",
968                           pObjectInfoCB,
969                           ParentObjectInfo,
970                           FileName);
971         }
972
973         lCount = InterlockedIncrement( &pObjectInfoCB->ObjectReferenceCount);
974
975         AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
976                       AFS_TRACE_LEVEL_VERBOSE,
977                       "AFSInitDirEntry Increment count on object %08lX 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             // Object specific information
1137             //
1138
1139             pObjectInfoCB->Links = DirEnumEntry->Links;
1140
1141             pObjectInfoCB->Expiration = DirEnumEntry->Expiration;
1142
1143             pObjectInfoCB->DataVersion = DirEnumEntry->DataVersion;
1144
1145             //
1146             // Check for the case where we have a filetype of SymLink but both the TargetFid and the
1147             // TargetName are empty. In this case set the filetype to zero so we evaluate it later in
1148             // the code
1149             //
1150
1151             if( pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK &&
1152                 pObjectInfoCB->TargetFileId.Vnode == 0 &&
1153                 pObjectInfoCB->TargetFileId.Unique == 0 &&
1154                 pDirNode->NameInformation.TargetName.Length == 0)
1155             {
1156
1157                 //
1158                 // This will ensure we perform a validation on the node
1159                 //
1160
1161                 pObjectInfoCB->FileType = AFS_FILE_TYPE_UNKNOWN;
1162             }
1163
1164             if( pObjectInfoCB->FileType == AFS_FILE_TYPE_UNKNOWN)
1165             {
1166
1167                 SetFlag( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
1168             }
1169         }
1170
1171 try_exit:
1172
1173         if( !NT_SUCCESS( ntStatus))
1174         {
1175
1176             if( pNonPagedDirEntry != NULL)
1177             {
1178
1179                 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
1180
1181                 AFSExFreePool( pNonPagedDirEntry);
1182             }
1183
1184             if( pDirNode != NULL)
1185             {
1186
1187                 AFSExFreePool( pDirNode);
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 = InterlockedDecrement( &pObjectInfoCB->ObjectReferenceCount);
1200
1201                 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1202                               AFS_TRACE_LEVEL_VERBOSE,
1203                               "AFSInitDirEntry Decrement count on object %08lX 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     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1301     NTSTATUS ntStatus = STATUS_SUCCESS;
1302     AFSDirEnumEntry *pDirEntry = NULL;
1303     UNICODE_STRING uniTargetName;
1304
1305     __Enter
1306     {
1307
1308         ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1309                                           AuthGroup,
1310                                           FALSE,
1311                                           &pDirEntry);
1312
1313         if( !NT_SUCCESS( ntStatus))
1314         {
1315
1316             try_return( ntStatus);
1317         }
1318
1319         DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1320
1321         DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1322
1323         DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1324
1325         DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1326
1327         DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1328
1329         DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1330
1331         DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1332
1333         DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1334
1335         DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1336
1337         DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1338
1339         DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1340
1341         if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1342         {
1343
1344             DirEntry->ObjectInformation->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1345         }
1346
1347         if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK ||
1348             pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1349         {
1350
1351             DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1352         }
1353
1354         DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1355
1356         DirEntry->ObjectInformation->Links = pDirEntry->Links;
1357
1358         //
1359         // If we have a target name then see if it needs updating ...
1360         //
1361
1362         if( pDirEntry->TargetNameLength > 0)
1363         {
1364
1365             //
1366             // Update the target name information if needed
1367             //
1368
1369             uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1370
1371             uniTargetName.MaximumLength = uniTargetName.Length;
1372
1373             uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1374
1375             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1376                             TRUE);
1377
1378             if( DirEntry->NameInformation.TargetName.Length == 0 ||
1379                 RtlCompareUnicodeString( &uniTargetName,
1380                                          &DirEntry->NameInformation.TargetName,
1381                                          TRUE) != 0)
1382             {
1383
1384                 //
1385                 // Update the target name
1386                 //
1387
1388                 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1389                                                 &DirEntry->Flags,
1390                                                 uniTargetName.Buffer,
1391                                                 uniTargetName.Length);
1392
1393                 if( !NT_SUCCESS( ntStatus))
1394                 {
1395
1396                     AFSReleaseResource( &DirEntry->NonPaged->Lock);
1397
1398                     try_return( ntStatus);
1399                 }
1400             }
1401
1402             AFSReleaseResource( &DirEntry->NonPaged->Lock);
1403         }
1404
1405 try_exit:
1406
1407         if( pDirEntry != NULL)
1408         {
1409
1410             AFSExFreePool( pDirEntry);
1411         }
1412     }
1413
1414     return ntStatus;
1415 }
1416
1417 NTSTATUS
1418 AFSValidateSymLink( IN GUID *AuthGroup,
1419                     IN AFSDirectoryCB *DirEntry)
1420 {
1421
1422     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1423     NTSTATUS ntStatus = STATUS_SUCCESS;
1424     AFSDirEnumEntry *pDirEntry = NULL;
1425     UNICODE_STRING uniTargetName;
1426
1427     __Enter
1428     {
1429
1430         ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1431                                           AuthGroup,
1432                                           FALSE,
1433                                           &pDirEntry);
1434
1435         if( !NT_SUCCESS( ntStatus))
1436         {
1437
1438             try_return( ntStatus);
1439         }
1440
1441         if( pDirEntry->FileType == AFS_FILE_TYPE_UNKNOWN ||
1442             pDirEntry->FileType == AFS_FILE_TYPE_INVALID)
1443         {
1444
1445             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
1446         }
1447
1448         DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1449
1450         DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1451
1452         DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1453
1454         //
1455         // Update the target name information if needed
1456         //
1457
1458         uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1459
1460         uniTargetName.MaximumLength = uniTargetName.Length;
1461
1462         uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1463
1464         if( uniTargetName.Length > 0)
1465         {
1466
1467             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1468                             TRUE);
1469
1470             if( DirEntry->NameInformation.TargetName.Length == 0 ||
1471                 RtlCompareUnicodeString( &uniTargetName,
1472                                          &DirEntry->NameInformation.TargetName,
1473                                          TRUE) != 0)
1474             {
1475
1476                 //
1477                 // Update the target name
1478                 //
1479
1480                 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1481                                                 &DirEntry->Flags,
1482                                                 uniTargetName.Buffer,
1483                                                 uniTargetName.Length);
1484
1485                 if( !NT_SUCCESS( ntStatus))
1486                 {
1487
1488                     AFSReleaseResource( &DirEntry->NonPaged->Lock);
1489
1490                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1491                 }
1492             }
1493
1494             AFSReleaseResource( &DirEntry->NonPaged->Lock);
1495         }
1496
1497         //
1498         // If the FileType is the same then nothing to do since it IS
1499         // a SymLink
1500         //
1501
1502         if( pDirEntry->FileType == DirEntry->ObjectInformation->FileType)
1503         {
1504
1505             ASSERT( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK);
1506
1507             try_return( ntStatus = STATUS_SUCCESS);
1508         }
1509
1510         DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1511
1512         DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1513
1514         DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1515
1516         DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1517
1518         DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1519
1520         DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1521
1522         DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1523
1524         DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1525
1526         if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1527         {
1528
1529             DirEntry->ObjectInformation->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1530         }
1531
1532         if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK ||
1533             pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1534         {
1535
1536             DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1537         }
1538
1539         DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1540
1541         DirEntry->ObjectInformation->Links = pDirEntry->Links;
1542
1543 try_exit:
1544
1545         if( pDirEntry != NULL)
1546         {
1547
1548             AFSExFreePool( pDirEntry);
1549         }
1550     }
1551
1552     return ntStatus;
1553 }
1554
1555 NTSTATUS
1556 AFSInvalidateObject( IN OUT AFSObjectInfoCB **ppObjectInfo,
1557                      IN     ULONG Reason)
1558 {
1559
1560     NTSTATUS ntStatus = STATUS_SUCCESS;
1561     IO_STATUS_BLOCK stIoStatus;
1562     ULONG ulFilter = 0;
1563
1564     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1565                   AFS_TRACE_LEVEL_VERBOSE,
1566                   "AFSInvalidateObject Invalidation on node type %d for fid %08lX-%08lX-%08lX-%08lX Reason %d\n",
1567                   (*ppObjectInfo)->FileType,
1568                   (*ppObjectInfo)->FileId.Cell,
1569                   (*ppObjectInfo)->FileId.Volume,
1570                   (*ppObjectInfo)->FileId.Vnode,
1571                   (*ppObjectInfo)->FileId.Unique,
1572                   Reason);
1573
1574     if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_SYMLINK ||
1575         (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DFSLINK ||
1576         (*ppObjectInfo)->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1577     {
1578         //
1579         // We only act on the mount point itself, not the target. If the
1580         // node has been deleted then mark it as such otherwise indicate
1581         // it requires verification
1582         //
1583
1584         if( Reason == AFS_INVALIDATE_DELETED)
1585         {
1586             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
1587         }
1588         else
1589         {
1590
1591             if( Reason == AFS_INVALIDATE_FLUSHED)
1592             {
1593
1594                 (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1595
1596                 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1597             }
1598
1599             (*ppObjectInfo)->Expiration.QuadPart = 0;
1600
1601             (*ppObjectInfo)->TargetFileId.Vnode = 0;
1602
1603             (*ppObjectInfo)->TargetFileId.Unique = 0;
1604
1605             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1606                           AFS_TRACE_LEVEL_VERBOSE,
1607                           "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1608                           (*ppObjectInfo)->FileId.Cell,
1609                           (*ppObjectInfo)->FileId.Volume,
1610                           (*ppObjectInfo)->FileId.Vnode,
1611                           (*ppObjectInfo)->FileId.Unique);
1612
1613             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1614         }
1615
1616         ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1617
1618         if( Reason == AFS_INVALIDATE_CREDS)
1619         {
1620             ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1621         }
1622
1623         if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1624             Reason == AFS_INVALIDATE_FLUSHED)
1625         {
1626             ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1627         }
1628         else
1629         {
1630             ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1631         }
1632
1633         AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
1634                                         NULL,
1635                                         FILE_NOTIFY_CHANGE_FILE_NAME |
1636                                         FILE_NOTIFY_CHANGE_ATTRIBUTES,
1637                                         FILE_ACTION_MODIFIED);
1638
1639         try_return( ntStatus);
1640     }
1641
1642     //
1643     // Depending on the reason for invalidation then perform work on the node
1644     //
1645
1646     switch( Reason)
1647     {
1648
1649     case AFS_INVALIDATE_DELETED:
1650         {
1651
1652             //
1653             // Mark this node as invalid
1654             //
1655
1656             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_DELETED);
1657
1658             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1659                           AFS_TRACE_LEVEL_VERBOSE,
1660                           "AFSInvalidateObject Set DELETE flag on fid %08lX-%08lX-%08lX-%08lX\n",
1661                           (*ppObjectInfo)->FileId.Cell,
1662                           (*ppObjectInfo)->FileId.Volume,
1663                           (*ppObjectInfo)->FileId.Vnode,
1664                           (*ppObjectInfo)->FileId.Unique);
1665
1666             if( (*ppObjectInfo)->ParentObjectInformation != NULL)
1667             {
1668
1669                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1670                               AFS_TRACE_LEVEL_VERBOSE,
1671                               "AFSInvalidateObject Set VERIFY flag on parent fid %08lX-%08lX-%08lX-%08lX\n",
1672                               (*ppObjectInfo)->ParentObjectInformation->FileId.Cell,
1673                               (*ppObjectInfo)->ParentObjectInformation->FileId.Volume,
1674                               (*ppObjectInfo)->ParentObjectInformation->FileId.Vnode,
1675                               (*ppObjectInfo)->ParentObjectInformation->FileId.Unique);
1676
1677                 SetFlag( (*ppObjectInfo)->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1678
1679                 (*ppObjectInfo)->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1680
1681                 (*ppObjectInfo)->ParentObjectInformation->Expiration.QuadPart = 0;
1682             }
1683
1684             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1685             {
1686                 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1687             }
1688             else
1689             {
1690                 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1691             }
1692
1693             AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
1694                                             NULL,
1695                                             ulFilter,
1696                                             FILE_ACTION_REMOVED);
1697
1698             if( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1699                                                       Reason)))
1700             {
1701                 (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1702             }
1703
1704             break;
1705         }
1706
1707     case AFS_INVALIDATE_FLUSHED:
1708         {
1709
1710             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1711                 (*ppObjectInfo)->Fcb != NULL)
1712             {
1713
1714                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1715                               AFS_TRACE_LEVEL_VERBOSE,
1716                               "AFSInvalidateObject Flush/purge file fid %08lX-%08lX-%08lX-%08lX\n",
1717                               (*ppObjectInfo)->FileId.Cell,
1718                               (*ppObjectInfo)->FileId.Volume,
1719                               (*ppObjectInfo)->FileId.Vnode,
1720                               (*ppObjectInfo)->FileId.Unique);
1721
1722                 AFSAcquireExcl( &(*ppObjectInfo)->Fcb->NPFcb->Resource,
1723                                 TRUE);
1724
1725                 __try
1726                 {
1727
1728                     CcFlushCache( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1729                                   NULL,
1730                                   0,
1731                                   &stIoStatus);
1732
1733                     if( !NT_SUCCESS( stIoStatus.Status))
1734                     {
1735
1736                         AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1737                                       AFS_TRACE_LEVEL_ERROR,
1738                                       "AFSInvalidateObject CcFlushCache failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1739                                       (*ppObjectInfo)->FileId.Cell,
1740                                       (*ppObjectInfo)->FileId.Volume,
1741                                       (*ppObjectInfo)->FileId.Vnode,
1742                                       (*ppObjectInfo)->FileId.Unique,
1743                                       stIoStatus.Status,
1744                                       stIoStatus.Information);
1745
1746                         ntStatus = stIoStatus.Status;
1747                     }
1748
1749                     CcPurgeCacheSection( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1750                                          NULL,
1751                                          0,
1752                                          FALSE);
1753                 }
1754                 __except( EXCEPTION_EXECUTE_HANDLER)
1755                 {
1756
1757                     ntStatus = GetExceptionCode();
1758                 }
1759
1760                 AFSReleaseResource( &(*ppObjectInfo)->Fcb->NPFcb->Resource);
1761
1762                 //
1763                 // Clear out the extents
1764                 // Get rid of them (note this involves waiting
1765                 // for any writes or reads to the cache to complete)
1766                 //
1767
1768                 (VOID) AFSTearDownFcbExtents( (*ppObjectInfo)->Fcb,
1769                                               NULL);
1770             }
1771
1772             (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1773
1774
1775             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE)
1776             {
1777
1778                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1779                               AFS_TRACE_LEVEL_VERBOSE,
1780                               "AFSInvalidateObject Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
1781                               (*ppObjectInfo)->FileId.Cell,
1782                               (*ppObjectInfo)->FileId.Volume,
1783                               (*ppObjectInfo)->FileId.Vnode,
1784                               (*ppObjectInfo)->FileId.Unique);
1785
1786                 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1787             }
1788
1789             // Fall through to the default processing
1790         }
1791
1792     default:
1793         {
1794
1795             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1796             {
1797                 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1798             }
1799             else
1800             {
1801                 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1802             }
1803
1804             if( Reason == AFS_INVALIDATE_CREDS)
1805             {
1806                 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1807             }
1808
1809             if( Reason == AFS_INVALIDATE_DATA_VERSION)
1810             {
1811                 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1812             }
1813             else
1814             {
1815                 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1816             }
1817
1818             AFSFsRtlNotifyFullReportChange( (*ppObjectInfo)->ParentObjectInformation,
1819                                             NULL,
1820                                             ulFilter,
1821                                             FILE_ACTION_MODIFIED);
1822
1823             //
1824             // Indicate this node requires re-evaluation for the remaining reasons
1825             //
1826
1827             (*ppObjectInfo)->Expiration.QuadPart = 0;
1828
1829             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1830                           AFS_TRACE_LEVEL_VERBOSE,
1831                           "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1832                           (*ppObjectInfo)->FileId.Cell,
1833                           (*ppObjectInfo)->FileId.Volume,
1834                           (*ppObjectInfo)->FileId.Vnode,
1835                           (*ppObjectInfo)->FileId.Unique);
1836
1837             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1838
1839             if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1840                 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1841                 ( Reason == AFS_INVALIDATE_CALLBACK ||
1842                   Reason == AFS_INVALIDATE_EXPIRED))
1843             {
1844                 if ( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1845                                                            AFS_INVALIDATE_DATA_VERSION)))
1846                 {
1847
1848                     (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1849                 }
1850             }
1851
1852             break;
1853         }
1854     }
1855
1856   try_exit:
1857
1858     return ntStatus;
1859 }
1860
1861 NTSTATUS
1862 AFSInvalidateCache( IN AFSInvalidateCacheCB *InvalidateCB)
1863 {
1864
1865     NTSTATUS ntStatus = STATUS_SUCCESS;
1866     AFSFcb      *pDcb = NULL, *pFcb = NULL, *pNextFcb = NULL;
1867     AFSVolumeCB *pVolumeCB = NULL;
1868     AFSFcb      *pTargetDcb = NULL;
1869     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1870     AFSDirectoryCB *pCurrentDirEntry = NULL;
1871     BOOLEAN     bIsChild = FALSE;
1872     ULONGLONG   ullIndex = 0;
1873     AFSObjectInfoCB *pObjectInfo = NULL;
1874     LONG lCount;
1875
1876     __Enter
1877     {
1878
1879         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1880                       AFS_TRACE_LEVEL_VERBOSE,
1881                       "AFSInvalidateCache Invalidation FID %08lX-%08lX-%08lX-%08lX Type %d WholeVolume %d Reason %d\n",
1882                       InvalidateCB->FileID.Cell,
1883                       InvalidateCB->FileID.Volume,
1884                       InvalidateCB->FileID.Vnode,
1885                       InvalidateCB->FileID.Unique,
1886                       InvalidateCB->FileType,
1887                       InvalidateCB->WholeVolume,
1888                       InvalidateCB->Reason);
1889
1890         //
1891         // Need to locate the Fcb for the directory to purge
1892         //
1893
1894         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1895                       AFS_TRACE_LEVEL_VERBOSE,
1896                       "AFSInvalidateCache Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
1897                       &pDevExt->Specific.RDR.VolumeTreeLock,
1898                       PsGetCurrentThread());
1899
1900         //
1901         // Starve any exclusive waiters on this paticular call
1902         //
1903
1904         AFSAcquireSharedStarveExclusive( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
1905
1906         //
1907         // Locate the volume node
1908         //
1909
1910         ullIndex = AFSCreateHighIndex( &InvalidateCB->FileID);
1911
1912         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
1913                                        ullIndex,
1914                                        (AFSBTreeEntry **)&pVolumeCB);
1915
1916         if( pVolumeCB != NULL)
1917         {
1918
1919             lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
1920
1921             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1922                           AFS_TRACE_LEVEL_VERBOSE,
1923                           "AFSInvalidateCache Increment count on volume %08lX Cnt %d\n",
1924                           pVolumeCB,
1925                           lCount);
1926         }
1927
1928         AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
1929
1930         if( !NT_SUCCESS( ntStatus) ||
1931             pVolumeCB == NULL)
1932         {
1933
1934             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1935                           AFS_TRACE_LEVEL_WARNING,
1936                           "AFSInvalidateCache Invalidation FAILURE Unable to locate volume node FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
1937                           InvalidateCB->FileID.Cell,
1938                           InvalidateCB->FileID.Volume,
1939                           InvalidateCB->FileID.Vnode,
1940                           InvalidateCB->FileID.Unique,
1941                           ntStatus);
1942
1943             try_return( ntStatus = STATUS_SUCCESS);
1944         }
1945
1946         //
1947         // If this is a whole volume invalidation then go do it now
1948         //
1949
1950         if( InvalidateCB->WholeVolume)
1951         {
1952
1953             ntStatus = AFSInvalidateVolume( pVolumeCB,
1954                                             InvalidateCB->Reason);
1955
1956             lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1957
1958             try_return( ntStatus);
1959         }
1960
1961         AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1962                           TRUE);
1963
1964         if ( AFSIsVolumeFID( &InvalidateCB->FileID))
1965         {
1966
1967             pObjectInfo = &pVolumeCB->ObjectInformation;
1968         }
1969         else
1970         {
1971
1972             lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
1973
1974             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1975                           AFS_TRACE_LEVEL_VERBOSE,
1976                           "AFSInvalidateCache Decrement count on volume %08lX Cnt %d\n",
1977                           pVolumeCB,
1978                           pVolumeCB->VolumeReferenceCount);
1979
1980             ullIndex = AFSCreateLowIndex( &InvalidateCB->FileID);
1981
1982             ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
1983                                            ullIndex,
1984                                            (AFSBTreeEntry **)&pObjectInfo);
1985         }
1986
1987         if( pObjectInfo != NULL)
1988         {
1989
1990             //
1991             // Reference the node so it won't be torn down
1992             //
1993
1994             lCount = InterlockedIncrement( &pObjectInfo->ObjectReferenceCount);
1995
1996             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1997                           AFS_TRACE_LEVEL_VERBOSE,
1998                           "AFSInvalidateCache Increment count on object %08lX Cnt %d\n",
1999                           pObjectInfo,
2000                           lCount);
2001         }
2002
2003         AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2004
2005         if( !NT_SUCCESS( ntStatus) ||
2006             pObjectInfo == NULL)
2007         {
2008
2009             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2010                           AFS_TRACE_LEVEL_WARNING,
2011                           "AFSInvalidateCache Invalidation FAILURE Unable to locate object FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2012                           InvalidateCB->FileID.Cell,
2013                           InvalidateCB->FileID.Volume,
2014                           InvalidateCB->FileID.Vnode,
2015                           InvalidateCB->FileID.Unique,
2016                           ntStatus);
2017
2018             try_return( ntStatus = STATUS_SUCCESS);
2019         }
2020
2021         AFSInvalidateObject( &pObjectInfo,
2022                              InvalidateCB->Reason);
2023
2024 try_exit:
2025
2026         if( pObjectInfo != NULL)
2027         {
2028
2029             lCount = InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
2030
2031             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2032                           AFS_TRACE_LEVEL_VERBOSE,
2033                           "AFSInvalidateCache Decrement count on object %08lX Cnt %d\n",
2034                           pObjectInfo,
2035                           lCount);
2036         }
2037     }
2038
2039     return ntStatus;
2040 }
2041
2042 BOOLEAN
2043 AFSIsChildOfParent( IN AFSFcb *Dcb,
2044                     IN AFSFcb *Fcb)
2045 {
2046
2047     BOOLEAN bIsChild = FALSE;
2048     AFSFcb *pCurrentFcb = Fcb;
2049
2050     while( pCurrentFcb != NULL)
2051     {
2052
2053         if( pCurrentFcb->ObjectInformation->ParentObjectInformation == Dcb->ObjectInformation)
2054         {
2055
2056             bIsChild = TRUE;
2057
2058             break;
2059         }
2060
2061         pCurrentFcb = pCurrentFcb->ObjectInformation->ParentObjectInformation->Fcb;
2062     }
2063
2064     return bIsChild;
2065 }
2066
2067 inline
2068 ULONGLONG
2069 AFSCreateHighIndex( IN AFSFileID *FileID)
2070 {
2071
2072     ULONGLONG ullIndex = 0;
2073
2074     ullIndex = (((ULONGLONG)FileID->Cell << 32) | FileID->Volume);
2075
2076     return ullIndex;
2077 }
2078
2079 inline
2080 ULONGLONG
2081 AFSCreateLowIndex( IN AFSFileID *FileID)
2082 {
2083
2084     ULONGLONG ullIndex = 0;
2085
2086     ullIndex = (((ULONGLONG)FileID->Vnode << 32) | FileID->Unique);
2087
2088     return ullIndex;
2089 }
2090
2091 BOOLEAN
2092 AFSCheckAccess( IN ACCESS_MASK DesiredAccess,
2093                 IN ACCESS_MASK GrantedAccess,
2094                 IN BOOLEAN DirectoryEntry)
2095 {
2096
2097     BOOLEAN bAccessGranted = TRUE;
2098
2099     //
2100     // Check if we are asking for read/write and granted only read only
2101     // NOTE: There will be more checks here
2102     //
2103
2104     if( !AFSCheckForReadOnlyAccess( DesiredAccess,
2105                                     DirectoryEntry) &&
2106         AFSCheckForReadOnlyAccess( GrantedAccess,
2107                                    DirectoryEntry))
2108     {
2109
2110         bAccessGranted = FALSE;
2111     }
2112
2113     return bAccessGranted;
2114 }
2115
2116 NTSTATUS
2117 AFSGetDriverStatus( IN AFSDriverStatusRespCB *DriverStatus)
2118 {
2119
2120     NTSTATUS         ntStatus = STATUS_SUCCESS;
2121     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2122
2123     //
2124     // Start with read
2125     //
2126
2127     DriverStatus->Status = AFS_DRIVER_STATUS_READY;
2128
2129     if( AFSGlobalRoot == NULL)
2130     {
2131
2132         //
2133         // We are not ready
2134         //
2135
2136         DriverStatus->Status = AFS_DRIVER_STATUS_NOT_READY;
2137     }
2138
2139     if( pControlDevExt->Specific.Control.CommServiceCB.IrpPoolControlFlag != POOL_ACTIVE)
2140     {
2141
2142         //
2143         // No service yet
2144         //
2145
2146         DriverStatus->Status = AFS_DRIVER_STATUS_NO_SERVICE;
2147     }
2148
2149     return ntStatus;
2150 }
2151
2152 NTSTATUS
2153 AFSSubstituteSysName( IN UNICODE_STRING *ComponentName,
2154                       IN UNICODE_STRING *SubstituteName,
2155                       IN ULONG StringIndex)
2156 {
2157
2158     NTSTATUS ntStatus = STATUS_SUCCESS;
2159     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2160     AFSSysNameCB    *pSysName = NULL;
2161     ERESOURCE       *pSysNameLock = NULL;
2162     ULONG            ulIndex = 1;
2163     USHORT           usIndex = 0;
2164     UNICODE_STRING   uniSysName;
2165
2166     __Enter
2167     {
2168
2169 #if defined(_WIN64)
2170
2171         if( IoIs32bitProcess( NULL))
2172         {
2173
2174             pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2175
2176             pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2177         }
2178         else
2179         {
2180
2181             pSysNameLock = &pControlDevExt->Specific.Control.SysName64ListLock;
2182
2183             pSysName = pControlDevExt->Specific.Control.SysName64ListHead;
2184         }
2185 #else
2186
2187         pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2188
2189         pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2190
2191 #endif
2192
2193         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2194                       AFS_TRACE_LEVEL_VERBOSE,
2195                       "AFSSubstituteSysName Acquiring SysName lock %08lX SHARED %08lX\n",
2196                       pSysNameLock,
2197                       PsGetCurrentThread());
2198
2199         AFSAcquireShared( pSysNameLock,
2200                           TRUE);
2201
2202         //
2203         // Find where we are in the list
2204         //
2205
2206         while( pSysName != NULL &&
2207             ulIndex < StringIndex)
2208         {
2209
2210             pSysName = pSysName->fLink;
2211
2212             ulIndex++;
2213         }
2214
2215         if( pSysName == NULL)
2216         {
2217
2218             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
2219         }
2220
2221         RtlInitUnicodeString( &uniSysName,
2222                               L"@SYS");
2223         //
2224         // If it is a full component of @SYS then just substitue the
2225         // name in
2226         //
2227
2228         if( RtlCompareUnicodeString( &uniSysName,
2229                                      ComponentName,
2230                                      TRUE) == 0)
2231         {
2232
2233             SubstituteName->Length = pSysName->SysName.Length;
2234             SubstituteName->MaximumLength = SubstituteName->Length;
2235
2236             SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2237                                                                         SubstituteName->Length,
2238                                                                         AFS_SUBST_BUFFER_TAG);
2239
2240             if( SubstituteName->Buffer == NULL)
2241             {
2242
2243                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2244             }
2245
2246             RtlCopyMemory( SubstituteName->Buffer,
2247                            pSysName->SysName.Buffer,
2248                            pSysName->SysName.Length);
2249         }
2250         else
2251         {
2252
2253             usIndex = 0;
2254
2255             while( ComponentName->Buffer[ usIndex] != L'@')
2256             {
2257
2258                 usIndex++;
2259             }
2260
2261             SubstituteName->Length = (usIndex * sizeof( WCHAR)) + pSysName->SysName.Length;
2262             SubstituteName->MaximumLength = SubstituteName->Length;
2263
2264             SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2265                                                                         SubstituteName->Length,
2266                                                                         AFS_SUBST_BUFFER_TAG);
2267
2268             if( SubstituteName->Buffer == NULL)
2269             {
2270
2271                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2272             }
2273
2274             RtlCopyMemory( SubstituteName->Buffer,
2275                            ComponentName->Buffer,
2276                            usIndex * sizeof( WCHAR));
2277
2278             RtlCopyMemory( &SubstituteName->Buffer[ usIndex],
2279                            pSysName->SysName.Buffer,
2280                            pSysName->SysName.Length);
2281         }
2282
2283 try_exit:
2284
2285         AFSReleaseResource( pSysNameLock);
2286     }
2287
2288     return ntStatus;
2289 }
2290
2291 NTSTATUS
2292 AFSSubstituteNameInPath( IN OUT UNICODE_STRING *FullPathName,
2293                          IN OUT UNICODE_STRING *ComponentName,
2294                          IN UNICODE_STRING *SubstituteName,
2295                          IN OUT UNICODE_STRING *RemainingPath,
2296                          IN BOOLEAN FreePathName)
2297 {
2298
2299     NTSTATUS ntStatus = STATUS_SUCCESS;
2300     UNICODE_STRING uniPathName;
2301     USHORT usPrefixNameLen = 0;
2302     SHORT  sNameLenDelta = 0;
2303
2304     __Enter
2305     {
2306
2307         //
2308         // If the passed in name can handle the additional length
2309         // then just moves things around
2310         //
2311
2312         sNameLenDelta = SubstituteName->Length - ComponentName->Length;
2313
2314         usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2315
2316         if( FullPathName->MaximumLength > FullPathName->Length + sNameLenDelta)
2317         {
2318
2319             if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2320             {
2321
2322                 RtlMoveMemory( &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + SubstituteName->Length)/sizeof( WCHAR))],
2323                                &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + ComponentName->Length)/sizeof( WCHAR))],
2324                                FullPathName->Length - usPrefixNameLen*sizeof( WCHAR) - ComponentName->Length);
2325             }
2326
2327             RtlCopyMemory( &FullPathName->Buffer[ usPrefixNameLen],
2328                            SubstituteName->Buffer,
2329                            SubstituteName->Length);
2330
2331             FullPathName->Length += sNameLenDelta;
2332
2333             ComponentName->Length += sNameLenDelta;
2334
2335             ComponentName->MaximumLength = ComponentName->Length;
2336
2337             if ( RemainingPath->Buffer)
2338             {
2339
2340                 RemainingPath->Buffer += sNameLenDelta/sizeof( WCHAR);
2341             }
2342
2343             try_return( ntStatus);
2344         }
2345
2346         //
2347         // Need to re-allocate the buffer
2348         //
2349
2350         uniPathName.Length = FullPathName->Length -
2351                                          ComponentName->Length +
2352                                          SubstituteName->Length;
2353
2354         uniPathName.MaximumLength = FullPathName->MaximumLength + PAGE_SIZE;
2355
2356         uniPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2357                                                                 uniPathName.MaximumLength,
2358                                                                 AFS_NAME_BUFFER_FOUR_TAG);
2359
2360         if( uniPathName.Buffer == NULL)
2361         {
2362
2363             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2364         }
2365
2366         usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2367
2368         usPrefixNameLen *= sizeof( WCHAR);
2369
2370         RtlZeroMemory( uniPathName.Buffer,
2371                        uniPathName.MaximumLength);
2372
2373         RtlCopyMemory( uniPathName.Buffer,
2374                        FullPathName->Buffer,
2375                        usPrefixNameLen);
2376
2377         RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen/sizeof( WCHAR))],
2378                        SubstituteName->Buffer,
2379                        SubstituteName->Length);
2380
2381         if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2382         {
2383
2384             RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen + SubstituteName->Length)/sizeof( WCHAR)],
2385                            &FullPathName->Buffer[ (usPrefixNameLen + ComponentName->Length)/sizeof( WCHAR)],
2386                            FullPathName->Length - usPrefixNameLen - ComponentName->Length);
2387         }
2388
2389         ComponentName->Buffer = uniPathName.Buffer + (ComponentName->Buffer - FullPathName->Buffer);
2390
2391         ComponentName->Length += sNameLenDelta;
2392
2393         ComponentName->MaximumLength = ComponentName->Length;
2394
2395         if ( RemainingPath->Buffer)
2396         {
2397
2398             RemainingPath->Buffer = uniPathName.Buffer
2399                 + (RemainingPath->Buffer - FullPathName->Buffer)
2400                 + sNameLenDelta/sizeof( WCHAR);
2401         }
2402
2403         if( FreePathName)
2404         {
2405             AFSExFreePool( FullPathName->Buffer);
2406         }
2407
2408         *FullPathName = uniPathName;
2409
2410 try_exit:
2411
2412         NOTHING;
2413     }
2414
2415     return ntStatus;
2416 }
2417
2418 NTSTATUS
2419 AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
2420                      IN ULONG Reason)
2421 {
2422
2423     NTSTATUS ntStatus = STATUS_SUCCESS;
2424     AFSObjectInfoCB *pCurrentObject = NULL;
2425     AFSObjectInfoCB *pNextObject = NULL;
2426     LONG lCount;
2427     AFSFcb *pFcb = NULL;
2428     ULONG ulFilter = 0;
2429
2430     __Enter
2431     {
2432
2433         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2434                       AFS_TRACE_LEVEL_VERBOSE,
2435                       "AFSInvalidateVolume Invalidate volume fid %08lX-%08lX-%08lX-%08lX Reason %08lX\n",
2436                       VolumeCB->ObjectInformation.FileId.Cell,
2437                       VolumeCB->ObjectInformation.FileId.Volume,
2438                       VolumeCB->ObjectInformation.FileId.Vnode,
2439                       VolumeCB->ObjectInformation.FileId.Unique,
2440                       Reason);
2441
2442         //
2443         // Depending on the reason for invalidation then perform work on the node
2444         //
2445
2446         switch( Reason)
2447         {
2448
2449             case AFS_INVALIDATE_DELETED:
2450             {
2451
2452                 //
2453                 // Mark this volume as invalid
2454                 //
2455
2456                 SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
2457
2458                 SetFlag( VolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE);
2459
2460                 break;
2461             }
2462         }
2463
2464         //
2465         // Invalidate the volume root directory
2466         //
2467
2468         pCurrentObject = &VolumeCB->ObjectInformation;
2469
2470         if ( pCurrentObject )
2471         {
2472
2473             lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
2474
2475             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2476                           AFS_TRACE_LEVEL_VERBOSE,
2477                           "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2478                           pCurrentObject,
2479                           lCount);
2480
2481             AFSInvalidateObject( &pCurrentObject,
2482                                  Reason);
2483
2484             lCount = InterlockedDecrement( &pCurrentObject->ObjectReferenceCount);
2485
2486             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2487                           AFS_TRACE_LEVEL_VERBOSE,
2488                           "AFSInvalidateVolumeObjects Decrement count on object %08lX Cnt %d\n",
2489                           pCurrentObject,
2490                           lCount);
2491         }
2492
2493         //
2494         // Apply invalidation to all other volume objects
2495         //
2496
2497         AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2498                           TRUE);
2499
2500         pCurrentObject = VolumeCB->ObjectInfoListHead;
2501
2502         if ( pCurrentObject)
2503         {
2504
2505             //
2506             // Reference the node so it won't be torn down
2507             //
2508
2509             lCount = InterlockedIncrement( &pCurrentObject->ObjectReferenceCount);
2510
2511             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2512                           AFS_TRACE_LEVEL_VERBOSE,
2513                           "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2514                           pCurrentObject,
2515                           lCount);
2516         }
2517
2518         while( pCurrentObject != NULL)
2519         {
2520
2521             pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2522
2523             if ( pNextObject)
2524             {
2525
2526                 //
2527                 // Reference the node so it won't be torn down
2528                 //
2529
2530                 lCount = InterlockedIncrement( &pNextObject->ObjectReferenceCount);
2531
2532                 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2533                               AFS_TRACE_LEVEL_VERBOSE,
2534                               "AFSInvalidateVolumeObjects Increment count on object %08lX Cnt %d\n",
2535                               pNextObject,
2536                               lCount);
2537             }
2538
2539             AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2540
2541             AFSInvalidateObject( &pCurrentObject,
2542                                  Reason);
2543
2544             if ( pCurrentObject )
2545             {
2546
2547                 lCount = InterlockedDecrement( &pCurrentObject->ObjectReferenceCount);
2548
2549                 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2550                               AFS_TRACE_LEVEL_VERBOSE,
2551                               "AFSInvalidateVolumeObjects Decrement count on object %08lX Cnt %d\n",
2552                               pCurrentObject,
2553                               lCount);
2554             }
2555
2556             AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2557                               TRUE);
2558
2559             pCurrentObject = pNextObject;
2560         }
2561
2562         AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2563     }
2564
2565     return ntStatus;
2566 }
2567
2568 VOID
2569 AFSInvalidateAllVolumes( VOID)
2570 {
2571     AFSVolumeCB *pVolumeCB = NULL;
2572     AFSVolumeCB *pNextVolumeCB = NULL;
2573     AFSDeviceExt *pRDRDeviceExt = NULL;
2574     LONG lCount;
2575
2576     pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2577
2578     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2579                   AFS_TRACE_LEVEL_VERBOSE,
2580                   "AFSInvalidateAllVolumes Acquiring RDR VolumeListLock lock %08lX SHARED %08lX\n",
2581                   &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2582                   PsGetCurrentThread());
2583
2584     AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2585                       TRUE);
2586
2587     pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
2588
2589     if ( pVolumeCB)
2590     {
2591
2592         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2593                       AFS_TRACE_LEVEL_VERBOSE,
2594                       "AFSInvalidateAllVolumes Acquiring VolumeRoot ObjectInfoTree lock %08lX SHARED %08lX\n",
2595                       pVolumeCB->ObjectInfoTree.TreeLock,
2596                       PsGetCurrentThread());
2597
2598         lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
2599     }
2600
2601     while( pVolumeCB != NULL)
2602     {
2603
2604         pNextVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2605
2606         if ( pNextVolumeCB)
2607         {
2608
2609             lCount = InterlockedIncrement( &pNextVolumeCB->VolumeReferenceCount);
2610         }
2611
2612         AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2613
2614         // do I need to hold the volume lock here?
2615
2616         AFSInvalidateVolume( pVolumeCB, AFS_INVALIDATE_EXPIRED);
2617
2618         AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2619                           TRUE);
2620
2621         lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
2622
2623         pVolumeCB = pNextVolumeCB;
2624     }
2625
2626     AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2627 }
2628
2629 NTSTATUS
2630 AFSVerifyEntry( IN GUID *AuthGroup,
2631                 IN AFSDirectoryCB *DirEntry)
2632 {
2633
2634     NTSTATUS ntStatus = STATUS_SUCCESS;
2635     AFSDirEnumEntry *pDirEnumEntry = NULL;
2636     AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
2637     IO_STATUS_BLOCK stIoStatus;
2638
2639     __Enter
2640     {
2641
2642         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2643                       AFS_TRACE_LEVEL_VERBOSE_2,
2644                       "AFSVerifyEntry Verifying entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2645                       &DirEntry->NameInformation.FileName,
2646                       pObjectInfo->FileId.Cell,
2647                       pObjectInfo->FileId.Volume,
2648                       pObjectInfo->FileId.Vnode,
2649                       pObjectInfo->FileId.Unique);
2650
2651         ntStatus = AFSEvaluateTargetByID( pObjectInfo,
2652                                           AuthGroup,
2653                                           FALSE,
2654                                           &pDirEnumEntry);
2655
2656         if( !NT_SUCCESS( ntStatus))
2657         {
2658
2659             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2660                           AFS_TRACE_LEVEL_ERROR,
2661                           "AFSValidateEntry Evaluate Target failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2662                           &DirEntry->NameInformation.FileName,
2663                           pObjectInfo->FileId.Cell,
2664                           pObjectInfo->FileId.Volume,
2665                           pObjectInfo->FileId.Vnode,
2666                           pObjectInfo->FileId.Unique,
2667                           ntStatus);
2668
2669             try_return( ntStatus);
2670         }
2671
2672         //
2673         // Check the data version of the file
2674         //
2675
2676         if( pObjectInfo->DataVersion.QuadPart == pDirEnumEntry->DataVersion.QuadPart &&
2677             !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2678         {
2679
2680             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2681                           AFS_TRACE_LEVEL_VERBOSE,
2682                           "AFSVerifyEntry No DV change %I64X for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2683                           pObjectInfo->DataVersion.QuadPart,
2684                           &DirEntry->NameInformation.FileName,
2685                           pObjectInfo->FileId.Cell,
2686                           pObjectInfo->FileId.Volume,
2687                           pObjectInfo->FileId.Vnode,
2688                           pObjectInfo->FileId.Unique);
2689
2690             //
2691             // We are ok, just get out
2692             //
2693
2694             ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2695
2696             try_return( ntStatus = STATUS_SUCCESS);
2697         }
2698
2699         //
2700         // New data version so we will need to process the node based on the type
2701         //
2702
2703         switch( pDirEnumEntry->FileType)
2704         {
2705
2706             case AFS_FILE_TYPE_MOUNTPOINT:
2707             {
2708
2709                 //
2710                 // For a mount point we need to ensure the target is the same
2711                 //
2712
2713                 if( !AFSIsEqualFID( &pObjectInfo->TargetFileId,
2714                                     &pDirEnumEntry->TargetFileId))
2715                 {
2716
2717                 }
2718
2719                 //
2720                 // Update the metadata for the entry
2721                 //
2722
2723                 ntStatus = AFSUpdateMetaData( DirEntry,
2724                                               pDirEnumEntry);
2725
2726                 if( NT_SUCCESS( ntStatus))
2727                 {
2728
2729                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2730                 }
2731
2732                 break;
2733             }
2734
2735             case AFS_FILE_TYPE_SYMLINK:
2736             {
2737
2738                 ASSERT( pDirEnumEntry->TargetNameLength > 0);
2739
2740                 //
2741                 // Update the metadata for the entry
2742                 //
2743
2744                 ntStatus = AFSUpdateMetaData( DirEntry,
2745                                               pDirEnumEntry);
2746
2747                 if( NT_SUCCESS( ntStatus))
2748                 {
2749
2750                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2751                 }
2752
2753                 break;
2754             }
2755
2756             case AFS_FILE_TYPE_FILE:
2757             {
2758                 FILE_OBJECT * pCCFileObject = NULL;
2759                 BOOLEAN bPurgeExtents = FALSE;
2760
2761                 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2762                 {
2763                     bPurgeExtents = TRUE;
2764
2765                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2766                                   AFS_TRACE_LEVEL_VERBOSE,
2767                                   "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2768                                   &DirEntry->NameInformation.FileName,
2769                                   pObjectInfo->FileId.Cell,
2770                                   pObjectInfo->FileId.Volume,
2771                                   pObjectInfo->FileId.Vnode,
2772                                   pObjectInfo->FileId.Unique);
2773
2774                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
2775                 }
2776
2777                 //
2778                 // Update the metadata for the entry
2779                 //
2780
2781                 ntStatus = AFSUpdateMetaData( DirEntry,
2782                                               pDirEnumEntry);
2783
2784                 if( !NT_SUCCESS( ntStatus))
2785                 {
2786
2787                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2788                                   AFS_TRACE_LEVEL_ERROR,
2789                                   "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
2790                                   &DirEntry->NameInformation.FileName,
2791                                   pObjectInfo->FileId.Cell,
2792                                   pObjectInfo->FileId.Volume,
2793                                   pObjectInfo->FileId.Vnode,
2794                                   pObjectInfo->FileId.Unique,
2795                                   ntStatus);
2796
2797                     break;
2798                 }
2799
2800                 if( pObjectInfo->Fcb != NULL)
2801                 {
2802
2803                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2804                                   AFS_TRACE_LEVEL_VERBOSE,
2805                                   "AFSVerifyEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2806                                   &DirEntry->NameInformation.FileName,
2807                                   pObjectInfo->FileId.Cell,
2808                                   pObjectInfo->FileId.Volume,
2809                                   pObjectInfo->FileId.Vnode,
2810                                   pObjectInfo->FileId.Unique);
2811
2812                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
2813                                     TRUE);
2814
2815                     __try
2816                     {
2817
2818                         CcFlushCache( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2819                                       NULL,
2820                                       0,
2821                                       &stIoStatus);
2822
2823                         if( !NT_SUCCESS( stIoStatus.Status))
2824                         {
2825
2826                             AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2827                                           AFS_TRACE_LEVEL_ERROR,
2828                                           "AFSVerifyEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
2829                                           &DirEntry->NameInformation.FileName,
2830                                           pObjectInfo->FileId.Cell,
2831                                           pObjectInfo->FileId.Volume,
2832                                           pObjectInfo->FileId.Vnode,
2833                                           pObjectInfo->FileId.Unique,
2834                                           stIoStatus.Status,
2835                                           stIoStatus.Information);
2836
2837                             ntStatus = stIoStatus.Status;
2838                         }
2839
2840                         if ( bPurgeExtents)
2841                         {
2842
2843                             CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2844                                                  NULL,
2845                                                  0,
2846                                                  FALSE);
2847                         }
2848                     }
2849                     __except( EXCEPTION_EXECUTE_HANDLER)
2850                     {
2851                         ntStatus = GetExceptionCode();
2852
2853                         AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2854                                       AFS_TRACE_LEVEL_ERROR,
2855                                       "AFSVerifyEntry CcFlushCache or CcPurgeCacheSection Exception %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2856                                       &DirEntry->NameInformation.FileName,
2857                                       pObjectInfo->FileId.Cell,
2858                                       pObjectInfo->FileId.Volume,
2859                                       pObjectInfo->FileId.Vnode,
2860                                       pObjectInfo->FileId.Unique,
2861                                       ntStatus);
2862                     }
2863
2864                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
2865
2866                     if ( bPurgeExtents)
2867                     {
2868                         AFSFlushExtents( pObjectInfo->Fcb,
2869                                          AuthGroup);
2870                     }
2871
2872                     //
2873                     // Reacquire the Fcb to purge the cache
2874                     //
2875
2876                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2877                                   AFS_TRACE_LEVEL_VERBOSE,
2878                                   "AFSVerifyEntry Acquiring Fcb lock %08lX EXCL %08lX\n",
2879                                   &pObjectInfo->Fcb->NPFcb->Resource,
2880                                   PsGetCurrentThread());
2881
2882                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
2883                                     TRUE);
2884
2885                     //
2886                     // Update file sizes
2887                     //
2888
2889                     pObjectInfo->Fcb->Header.AllocationSize.QuadPart  = pObjectInfo->AllocationSize.QuadPart;
2890                     pObjectInfo->Fcb->Header.FileSize.QuadPart        = pObjectInfo->EndOfFile.QuadPart;
2891                     pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
2892
2893                     pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
2894
2895                     if ( pCCFileObject != NULL)
2896                     {
2897                         CcSetFileSizes( pCCFileObject,
2898                                         (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
2899                     }
2900
2901                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
2902                 }
2903                 else
2904                 {
2905                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2906                                   AFS_TRACE_LEVEL_WARNING,
2907                                   "AFSValidateEntry Fcb NULL %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2908                                   &DirEntry->NameInformation.FileName,
2909                                   pObjectInfo->FileId.Cell,
2910                                   pObjectInfo->FileId.Volume,
2911                                   pObjectInfo->FileId.Vnode,
2912                                   pObjectInfo->FileId.Unique);
2913                 }
2914
2915                 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2916
2917                 break;
2918             }
2919
2920             case AFS_FILE_TYPE_DIRECTORY:
2921             {
2922
2923                 AFSFcb *pCurrentFcb = NULL;
2924                 AFSDirectoryCB *pCurrentDirEntry = NULL;
2925
2926                 //
2927                 // For a directory or root entry flush the content of
2928                 // the directory enumeration.
2929                 //
2930
2931                 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
2932                 {
2933
2934                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2935                                   AFS_TRACE_LEVEL_VERBOSE_2,
2936                                   "AFSVerifyEntry Validating directory content for entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2937                                   &DirEntry->NameInformation.FileName,
2938                                   pObjectInfo->FileId.Cell,
2939                                   pObjectInfo->FileId.Volume,
2940                                   pObjectInfo->FileId.Vnode,
2941                                   pObjectInfo->FileId.Unique);
2942
2943                     AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2944                                     TRUE);
2945
2946                     ntStatus = AFSValidateDirectoryCache( pObjectInfo,
2947                                                           AuthGroup);
2948
2949                     AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2950
2951                     if ( !NT_SUCCESS( ntStatus))
2952                     {
2953
2954                         try_return( ntStatus);
2955                     }
2956                 }
2957
2958                 //
2959                 // Update the metadata for the entry
2960                 //
2961
2962                 ntStatus = AFSUpdateMetaData( DirEntry,
2963                                               pDirEnumEntry);
2964
2965                 if( NT_SUCCESS( ntStatus))
2966                 {
2967
2968                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2969                 }
2970
2971                 break;
2972             }
2973
2974             case AFS_FILE_TYPE_DFSLINK:
2975             {
2976
2977                 UNICODE_STRING uniTargetName;
2978
2979                 //
2980                 // For a DFS link need to check the target name has not changed
2981                 //
2982
2983                 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
2984
2985                 uniTargetName.MaximumLength = uniTargetName.Length;
2986
2987                 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
2988
2989                 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
2990                                 TRUE);
2991
2992                 if( DirEntry->NameInformation.TargetName.Length == 0 ||
2993                     RtlCompareUnicodeString( &uniTargetName,
2994                                              &DirEntry->NameInformation.TargetName,
2995                                              TRUE) != 0)
2996                 {
2997
2998                     //
2999                     // Update the target name
3000                     //
3001
3002                     ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3003                                                     &DirEntry->Flags,
3004                                                     uniTargetName.Buffer,
3005                                                     uniTargetName.Length);
3006
3007                     if( !NT_SUCCESS( ntStatus))
3008                     {
3009
3010                         AFSReleaseResource( &DirEntry->NonPaged->Lock);
3011
3012                         break;
3013                     }
3014                 }
3015
3016                 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3017
3018                 //
3019                 // Update the metadata for the entry
3020                 //
3021
3022                 ntStatus = AFSUpdateMetaData( DirEntry,
3023                                               pDirEnumEntry);
3024
3025                 if( NT_SUCCESS( ntStatus))
3026                 {
3027
3028                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3029                 }
3030
3031                 break;
3032             }
3033
3034             default:
3035
3036                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3037                               AFS_TRACE_LEVEL_WARNING,
3038                               "AFSVerifyEntry Attempt to verify node of type %d %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3039                               pObjectInfo->FileType,
3040                               &DirEntry->NameInformation.FileName,
3041                               pObjectInfo->FileId.Cell,
3042                               pObjectInfo->FileId.Volume,
3043                               pObjectInfo->FileId.Vnode,
3044                               pObjectInfo->FileId.Unique);
3045
3046                 break;
3047         }
3048
3049  try_exit:
3050
3051         if( pDirEnumEntry != NULL)
3052         {
3053
3054             AFSExFreePool( pDirEnumEntry);
3055         }
3056     }
3057
3058     return ntStatus;
3059 }
3060
3061 NTSTATUS
3062 AFSSetVolumeState( IN AFSVolumeStatusCB *VolumeStatus)
3063 {
3064
3065     NTSTATUS ntStatus = STATUS_SUCCESS;
3066     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
3067     ULONGLONG   ullIndex = 0;
3068     AFSVolumeCB *pVolumeCB = NULL;
3069     AFSFcb *pFcb = NULL;
3070     AFSObjectInfoCB *pCurrentObject = NULL;
3071     LONG lCount;
3072
3073     __Enter
3074     {
3075
3076         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3077                       AFS_TRACE_LEVEL_VERBOSE,
3078                       "AFSSetVolumeState Marking volume state %d Volume Cell %08lX Volume %08lX\n",
3079                       VolumeStatus->Online,
3080                       VolumeStatus->FileID.Cell,
3081                       VolumeStatus->FileID.Volume);
3082
3083         //
3084         // Need to locate the Fcb for the directory to purge
3085         //
3086
3087         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3088                       AFS_TRACE_LEVEL_VERBOSE,
3089                       "AFSSetVolumeState Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
3090                       &pDevExt->Specific.RDR.VolumeTreeLock,
3091                       PsGetCurrentThread());
3092
3093         AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
3094
3095         //
3096         // Locate the volume node
3097         //
3098
3099         ullIndex = AFSCreateHighIndex( &VolumeStatus->FileID);
3100
3101         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
3102                                        ullIndex,
3103                                        (AFSBTreeEntry **)&pVolumeCB);
3104
3105         if( pVolumeCB != NULL)
3106         {
3107
3108             lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
3109
3110             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3111
3112             //
3113             // Set the volume state accordingly
3114             //
3115
3116             if( VolumeStatus->Online)
3117             {
3118
3119                 InterlockedAnd( (LONG *)&(pVolumeCB->Flags), ~AFS_VOLUME_FLAGS_OFFLINE);
3120             }
3121             else
3122             {
3123
3124                 InterlockedOr( (LONG *)&(pVolumeCB->Flags), AFS_VOLUME_FLAGS_OFFLINE);
3125             }
3126
3127             AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
3128                               TRUE);
3129
3130             pCurrentObject = pVolumeCB->ObjectInfoListHead;;
3131
3132             while( pCurrentObject != NULL)
3133             {
3134
3135                 if( VolumeStatus->Online)
3136                 {
3137
3138                     ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
3139
3140                     SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
3141
3142                     pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
3143                 }
3144                 else
3145                 {
3146
3147                     SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
3148                 }
3149
3150                 pFcb = pCurrentObject->Fcb;
3151
3152                 if( pFcb != NULL &&
3153                     !(VolumeStatus->Online) &&
3154                     pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
3155                 {
3156
3157                     AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3158                                   AFS_TRACE_LEVEL_ERROR,
3159                                   "AFSSetVolumeState Marking volume offline and canceling extents Volume Cell %08lX Volume %08lX\n",
3160                                   VolumeStatus->FileID.Cell,
3161                                   VolumeStatus->FileID.Volume);
3162
3163                     //
3164                     // Clear out the extents
3165                     //
3166
3167                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3168                                   AFS_TRACE_LEVEL_VERBOSE,
3169                                   "AFSSetVolumeState Acquiring Fcb extents lock %08lX EXCL %08lX\n",
3170                                   &pFcb->NPFcb->Specific.File.ExtentsResource,
3171                                   PsGetCurrentThread());
3172
3173                     AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
3174                                     TRUE);
3175
3176                     pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
3177
3178                     KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
3179                                 0,
3180                                 FALSE);
3181
3182                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3183                                   AFS_TRACE_LEVEL_VERBOSE,
3184                                   "AFSSetVolumeState Releasing Fcb extents lock %08lX EXCL %08lX\n",
3185                                   &pFcb->NPFcb->Specific.File.ExtentsResource,
3186                                   PsGetCurrentThread());
3187
3188                     AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
3189
3190                     //
3191                     // And get rid of them (note this involves waiting
3192                     // for any writes or reads to the cache to complete)
3193                     //
3194
3195                     (VOID) AFSTearDownFcbExtents( pFcb,
3196                                                   NULL);
3197                 }
3198
3199                 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
3200             }
3201
3202             AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
3203
3204             lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
3205         }
3206         else
3207         {
3208
3209             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3210         }
3211     }
3212
3213     return ntStatus;
3214 }
3215
3216 NTSTATUS
3217 AFSSetNetworkState( IN AFSNetworkStatusCB *NetworkStatus)
3218 {
3219
3220     NTSTATUS ntStatus = STATUS_SUCCESS;
3221
3222     __Enter
3223     {
3224
3225         if( AFSGlobalRoot == NULL)
3226         {
3227
3228             try_return( ntStatus);
3229         }
3230
3231         AFSAcquireExcl( AFSGlobalRoot->VolumeLock,
3232                         TRUE);
3233
3234         //
3235         // Set the network state according to the information
3236         //
3237
3238         if( NetworkStatus->Online)
3239         {
3240
3241             ClearFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3242         }
3243         else
3244         {
3245
3246             SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3247         }
3248
3249         AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3250
3251 try_exit:
3252
3253         NOTHING;
3254     }
3255
3256     return ntStatus;
3257 }
3258
3259 NTSTATUS
3260 AFSValidateDirectoryCache( IN AFSObjectInfoCB *ObjectInfo,
3261                            IN GUID *AuthGroup)
3262 {
3263
3264     NTSTATUS ntStatus = STATUS_SUCCESS;
3265     BOOLEAN  bAcquiredLock = FALSE;
3266     AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
3267     AFSFcb *pFcb = NULL;
3268
3269     __Enter
3270     {
3271
3272         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3273                       AFS_TRACE_LEVEL_VERBOSE,
3274                       "AFSValidateDirectoryCache Validating content for FID %08lX-%08lX-%08lX-%08lX\n",
3275                       ObjectInfo->FileId.Cell,
3276                       ObjectInfo->FileId.Volume,
3277                       ObjectInfo->FileId.Vnode,
3278                       ObjectInfo->FileId.Unique);
3279
3280         if( !ExIsResourceAcquiredLite( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock))
3281         {
3282
3283             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3284                           AFS_TRACE_LEVEL_VERBOSE,
3285                           "AFSValidateDirectoryCache Acquiring DirectoryNodeHdr.TreeLock lock %08lX EXCL %08lX\n",
3286                           ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3287                           PsGetCurrentThread());
3288
3289             AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3290                             TRUE);
3291
3292             bAcquiredLock = TRUE;
3293         }
3294
3295         //
3296         // Check for inconsistency between DirectoryNodeList and DirectoryNodeCount
3297         //
3298
3299         if ( ObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL &&
3300              ObjectInfo->Specific.Directory.DirectoryNodeCount > 0)
3301         {
3302
3303             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3304                           AFS_TRACE_LEVEL_ERROR,
3305                           "AFSValidateDirectoryCache Empty Node List but Non-Zero Node Count %08lX for dir FID %08lX-%08lX-%08lX-%08lX\n",
3306                           ObjectInfo->Specific.Directory.DirectoryNodeCount,
3307                           ObjectInfo->FileId.Cell,
3308                           ObjectInfo->FileId.Volume,
3309                           ObjectInfo->FileId.Vnode,
3310                           ObjectInfo->FileId.Unique);
3311         }
3312
3313         //
3314         // Reset the directory list information by clearing all valid entries
3315         //
3316
3317         pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3318
3319         while( pCurrentDirEntry != NULL)
3320         {
3321
3322             pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3323
3324             if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
3325             {
3326
3327                 //
3328                 // If this entry has been deleted then process it here
3329                 //
3330
3331                 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
3332                     pCurrentDirEntry->OpenReferenceCount == 0)
3333                 {
3334
3335                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3336                                   AFS_TRACE_LEVEL_VERBOSE,
3337                                   "AFSValidateDirectoryCache Deleting dir entry %p name %wZ\n",
3338                                   pCurrentDirEntry,
3339                                   &pCurrentDirEntry->NameInformation.FileName);
3340
3341                     AFSDeleteDirEntry( ObjectInfo,
3342                                        pCurrentDirEntry);
3343                 }
3344                 else
3345                 {
3346
3347                     ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID);
3348
3349                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3350                                   AFS_TRACE_LEVEL_VERBOSE,
3351                                   "AFSValidateDirectoryCache Clear VALID flag on DE %p Reference count %08lX\n",
3352                                   pCurrentDirEntry,
3353                                   pCurrentDirEntry->OpenReferenceCount);
3354
3355                     //
3356                     // We pull the short name from the parent tree since it could change below
3357                     //
3358
3359                     if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
3360                     {
3361
3362                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3363                                       AFS_TRACE_LEVEL_VERBOSE,
3364                                       "AFSValidateDirectoryCache Removing DE %p (%08lX) from shortname tree for %wZ\n",
3365                                       pCurrentDirEntry,
3366                                       pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3367                                       &pCurrentDirEntry->NameInformation.FileName);
3368
3369                         AFSRemoveShortNameDirEntry( &ObjectInfo->Specific.Directory.ShortNameTree,
3370                                                     pCurrentDirEntry);
3371
3372                         ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3373                     }
3374                 }
3375             }
3376
3377             pCurrentDirEntry = pNextDirEntry;
3378         }
3379
3380         //
3381         // Reget the directory contents
3382         //
3383
3384         ntStatus = AFSVerifyDirectoryContent( ObjectInfo,
3385                                               AuthGroup);
3386
3387         if ( !NT_SUCCESS( ntStatus))
3388         {
3389             try_return( ntStatus);
3390         }
3391
3392         //
3393         // Now start again and tear down any entries not valid
3394         //
3395
3396         pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3397
3398         while( pCurrentDirEntry != NULL)
3399         {
3400
3401             pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3402
3403             if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID))
3404             {
3405
3406                 if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME) &&
3407                     pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex > 0)
3408                 {
3409
3410                     if( ObjectInfo->Specific.Directory.ShortNameTree == NULL)
3411                     {
3412
3413                         ObjectInfo->Specific.Directory.ShortNameTree = pCurrentDirEntry;
3414
3415                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3416                                       AFS_TRACE_LEVEL_VERBOSE,
3417                                       "AFSValidateDirectoryCache Insert DE %p to head of shortname tree for %wZ\n",
3418                                       pCurrentDirEntry,
3419                                       &pCurrentDirEntry->NameInformation.FileName);
3420
3421                         SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3422                     }
3423                     else
3424                     {
3425
3426                         if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfo->Specific.Directory.ShortNameTree,
3427                                                                      pCurrentDirEntry)))
3428                         {
3429                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3430                                           AFS_TRACE_LEVEL_VERBOSE,
3431                                           "AFSValidateDirectoryCache Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
3432                                           pCurrentDirEntry,
3433                                           pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3434                                           &pCurrentDirEntry->NameInformation.FileName);
3435                         }
3436                         else
3437                         {
3438                             SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3439
3440                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3441                                           AFS_TRACE_LEVEL_VERBOSE,
3442                                           "AFSValidateDirectoryCache Insert DE %p to shortname tree for %wZ\n",
3443                                           pCurrentDirEntry,
3444                                           &pCurrentDirEntry->NameInformation.FileName);
3445                         }
3446                     }
3447                 }
3448
3449                 pCurrentDirEntry = pNextDirEntry;
3450
3451                 continue;
3452             }
3453
3454             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3455                           AFS_TRACE_LEVEL_VERBOSE,
3456                           "AFSValidateDirectoryCache Processing INVALID DE %p Reference count %08lX\n",
3457                           pCurrentDirEntry,
3458                           pCurrentDirEntry->OpenReferenceCount);
3459
3460             if( pCurrentDirEntry->OpenReferenceCount == 0)
3461             {
3462
3463                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3464                               AFS_TRACE_LEVEL_VERBOSE,
3465                               "AFSValidateDirectoryCache Deleting dir entry %wZ from parent FID %08lX-%08lX-%08lX-%08lX\n",
3466                               &pCurrentDirEntry->NameInformation.FileName,
3467                               ObjectInfo->FileId.Cell,
3468                               ObjectInfo->FileId.Volume,
3469                               ObjectInfo->FileId.Vnode,
3470                               ObjectInfo->FileId.Unique);
3471
3472                 AFSDeleteDirEntry( ObjectInfo,
3473                                    pCurrentDirEntry);
3474             }
3475             else
3476             {
3477
3478                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3479                               AFS_TRACE_LEVEL_VERBOSE,
3480                               "AFSValidateDirectoryCache Setting dir entry %p Name %wZ DELETED in parent FID %08lX-%08lX-%08lX-%08lX\n",
3481                               pCurrentDirEntry,
3482                               &pCurrentDirEntry->NameInformation.FileName,
3483                               ObjectInfo->FileId.Cell,
3484                               ObjectInfo->FileId.Volume,
3485                               ObjectInfo->FileId.Vnode,
3486                               ObjectInfo->FileId.Unique);
3487
3488                 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
3489
3490                 AFSRemoveNameEntry( ObjectInfo,
3491                                     pCurrentDirEntry);
3492             }
3493
3494             pCurrentDirEntry = pNextDirEntry;
3495         }
3496
3497 #if DBG
3498         if( !AFSValidateDirList( ObjectInfo))
3499         {
3500
3501             AFSPrint("AFSValidateDirectoryCache Invalid count ...\n");
3502         }
3503 #endif
3504
3505 try_exit:
3506
3507         if( bAcquiredLock)
3508         {
3509
3510             AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3511         }
3512     }
3513
3514     return ntStatus;
3515 }
3516
3517 BOOLEAN
3518 AFSIsVolumeFID( IN AFSFileID *FileID)
3519 {
3520
3521     BOOLEAN bIsVolume = FALSE;
3522
3523     if( FileID->Vnode == 1 &&
3524         FileID->Unique == 1)
3525     {
3526
3527         bIsVolume = TRUE;
3528     }
3529
3530     return bIsVolume;
3531 }
3532
3533 BOOLEAN
3534 AFSIsFinalNode( IN AFSFcb *Fcb)
3535 {
3536
3537     BOOLEAN bIsFinalNode = FALSE;
3538
3539     if( Fcb->Header.NodeTypeCode == AFS_ROOT_FCB ||
3540         Fcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB ||
3541         Fcb->Header.NodeTypeCode == AFS_FILE_FCB ||
3542         Fcb->Header.NodeTypeCode == AFS_DFS_LINK_FCB ||
3543         Fcb->Header.NodeTypeCode == AFS_INVALID_FCB )
3544     {
3545
3546         bIsFinalNode = TRUE;
3547     }
3548     else
3549     {
3550
3551         ASSERT( Fcb->Header.NodeTypeCode == AFS_MOUNT_POINT_FCB ||
3552                 Fcb->Header.NodeTypeCode == AFS_SYMBOLIC_LINK_FCB);
3553     }
3554
3555     return bIsFinalNode;
3556 }
3557
3558 NTSTATUS
3559 AFSUpdateMetaData( IN AFSDirectoryCB *DirEntry,
3560                    IN AFSDirEnumEntry *DirEnumEntry)
3561 {
3562
3563     NTSTATUS ntStatus = STATUS_SUCCESS;
3564     UNICODE_STRING uniTargetName;
3565     AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
3566
3567     __Enter
3568     {
3569
3570         pObjectInfo->TargetFileId = DirEnumEntry->TargetFileId;
3571
3572         pObjectInfo->Expiration = DirEnumEntry->Expiration;
3573
3574         pObjectInfo->DataVersion = DirEnumEntry->DataVersion;
3575
3576         pObjectInfo->FileType = DirEnumEntry->FileType;
3577
3578         pObjectInfo->CreationTime = DirEnumEntry->CreationTime;
3579
3580         pObjectInfo->LastAccessTime = DirEnumEntry->LastAccessTime;
3581
3582         pObjectInfo->LastWriteTime = DirEnumEntry->LastWriteTime;
3583
3584         pObjectInfo->ChangeTime = DirEnumEntry->ChangeTime;
3585
3586         pObjectInfo->EndOfFile = DirEnumEntry->EndOfFile;
3587
3588         pObjectInfo->AllocationSize = DirEnumEntry->AllocationSize;
3589
3590         pObjectInfo->FileAttributes = DirEnumEntry->FileAttributes;
3591
3592         if( pObjectInfo->FileType == AFS_FILE_TYPE_MOUNTPOINT)
3593         {
3594
3595             pObjectInfo->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
3596         }
3597
3598         if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK ||
3599             pObjectInfo->FileType == AFS_FILE_TYPE_DFSLINK)
3600         {
3601
3602             pObjectInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
3603         }
3604
3605         pObjectInfo->EaSize = DirEnumEntry->EaSize;
3606
3607         pObjectInfo->Links = DirEnumEntry->Links;
3608
3609         if( DirEnumEntry->TargetNameLength > 0)
3610         {
3611
3612             //
3613             // Update the target name information if needed
3614             //
3615
3616             uniTargetName.Length = (USHORT)DirEnumEntry->TargetNameLength;
3617
3618             uniTargetName.MaximumLength = uniTargetName.Length;
3619
3620             uniTargetName.Buffer = (WCHAR *)((char *)DirEnumEntry + DirEnumEntry->TargetNameOffset);
3621
3622             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3623                             TRUE);
3624
3625             if( DirEntry->NameInformation.TargetName.Length == 0 ||
3626                 RtlCompareUnicodeString( &uniTargetName,
3627                                          &DirEntry->NameInformation.TargetName,
3628                                          TRUE) != 0)
3629             {
3630
3631                 //
3632                 // Update the target name
3633                 //
3634
3635                 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3636                                                 &DirEntry->Flags,
3637                                                 uniTargetName.Buffer,
3638                                                 uniTargetName.Length);
3639
3640                 if( !NT_SUCCESS( ntStatus))
3641                 {
3642
3643                     AFSReleaseResource( &DirEntry->NonPaged->Lock);
3644
3645                     try_return( ntStatus);
3646                 }
3647             }
3648
3649             AFSReleaseResource( &DirEntry->NonPaged->Lock);
3650         }
3651         else if( DirEntry->NameInformation.TargetName.Length > 0)
3652         {
3653
3654             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3655                             TRUE);
3656
3657             if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER) &&
3658                 DirEntry->NameInformation.TargetName.Buffer != NULL)
3659             {
3660                 AFSExFreePool( DirEntry->NameInformation.TargetName.Buffer);
3661             }
3662
3663             ClearFlag( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER);
3664
3665             DirEntry->NameInformation.TargetName.Length = 0;
3666             DirEntry->NameInformation.TargetName.MaximumLength = 0;
3667             DirEntry->NameInformation.TargetName.Buffer = NULL;
3668
3669             AFSReleaseResource( &DirEntry->NonPaged->Lock);
3670         }
3671
3672 try_exit:
3673
3674         NOTHING;
3675     }
3676
3677     return ntStatus;
3678 }
3679
3680 NTSTATUS
3681 AFSValidateEntry( IN AFSDirectoryCB *DirEntry,
3682                   IN GUID *AuthGroup,
3683                   IN BOOLEAN PurgeContent,
3684                   IN BOOLEAN FastCall)
3685 {
3686
3687     NTSTATUS ntStatus = STATUS_SUCCESS;
3688     LARGE_INTEGER liSystemTime;
3689     AFSDirEnumEntry *pDirEnumEntry = NULL;
3690     AFSFcb *pCurrentFcb = NULL;
3691     BOOLEAN bReleaseFcb = FALSE;
3692     AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
3693
3694     __Enter
3695     {
3696
3697         //
3698         // If we have an Fcb hanging off the directory entry then be sure to acquire the locks in the
3699         // correct order
3700         //
3701
3702         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3703                       AFS_TRACE_LEVEL_VERBOSE_2,
3704                       "AFSValidateEntry Validating entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3705                       &DirEntry->NameInformation.FileName,
3706                       pObjectInfo->FileId.Cell,
3707                       pObjectInfo->FileId.Volume,
3708                       pObjectInfo->FileId.Vnode,
3709                       pObjectInfo->FileId.Unique);
3710
3711         //
3712         // If this is a fake node then bail since the service knows nothing about it
3713         //
3714
3715         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_FAKE))
3716         {
3717
3718             try_return( ntStatus);
3719         }
3720
3721         if( PurgeContent &&
3722             pObjectInfo->Fcb != NULL)
3723         {
3724
3725             pCurrentFcb = pObjectInfo->Fcb;
3726
3727             if( !ExIsResourceAcquiredLite( &pCurrentFcb->NPFcb->Resource))
3728             {
3729
3730                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3731                               AFS_TRACE_LEVEL_VERBOSE,
3732                               "AFSValidateEntry Acquiring Fcb lock %08lX EXCL %08lX\n",
3733                               &pCurrentFcb->NPFcb->Resource,
3734                               PsGetCurrentThread());
3735
3736                 AFSAcquireExcl( &pCurrentFcb->NPFcb->Resource,
3737                                 TRUE);
3738
3739                 bReleaseFcb = TRUE;
3740             }
3741         }
3742
3743         //
3744         // This routine ensures that the current entry is valid by:
3745         //
3746         //      1) Checking that the expiration time is non-zero and after where we
3747         //         currently are
3748         //
3749
3750         KeQuerySystemTime( &liSystemTime);
3751
3752         if( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) &&
3753             !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
3754             !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA) &&
3755             pObjectInfo->Expiration.QuadPart >= liSystemTime.QuadPart)
3756         {
3757
3758             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3759                           AFS_TRACE_LEVEL_VERBOSE_2,
3760                           "AFSValidateEntry Directory entry %wZ FID %08lX-%08lX-%08lX-%08lX VALID\n",
3761                           &DirEntry->NameInformation.FileName,
3762                           pObjectInfo->FileId.Cell,
3763                           pObjectInfo->FileId.Volume,
3764                           pObjectInfo->FileId.Vnode,
3765                           pObjectInfo->FileId.Unique);
3766
3767             try_return( ntStatus);
3768         }
3769
3770         //
3771         // This node requires updating
3772         //
3773
3774         ntStatus = AFSEvaluateTargetByID( pObjectInfo,
3775                                           AuthGroup,
3776                                           FastCall,
3777                                           &pDirEnumEntry);
3778
3779         if( !NT_SUCCESS( ntStatus))
3780         {
3781
3782             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3783                           AFS_TRACE_LEVEL_ERROR,
3784                           "AFSValidateEntry Failed to evaluate entry FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
3785                           FastCall,
3786                           &DirEntry->NameInformation.FileName,
3787                           pObjectInfo->FileId.Cell,
3788                           pObjectInfo->FileId.Volume,
3789                           pObjectInfo->FileId.Vnode,
3790                           pObjectInfo->FileId.Unique,
3791                       &nbs