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