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