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