Windows: include owner/group in Security DACL
[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                     InvalidateCB->Reason == AFS_INVALIDATE_DATA_VERSION)
1714                 {
1715                     pObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1716                 }
1717
1718                 pObjectInfo->Expiration.QuadPart = 0;
1719
1720                 pObjectInfo->TargetFileId.Vnode = 0;
1721
1722                 pObjectInfo->TargetFileId.Unique = 0;
1723
1724                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1725                               AFS_TRACE_LEVEL_VERBOSE,
1726                               "AFSInvalidateCache Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1727                               pObjectInfo->FileId.Cell,
1728                               pObjectInfo->FileId.Volume,
1729                               pObjectInfo->FileId.Vnode,
1730                               pObjectInfo->FileId.Unique);
1731
1732                 SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1733             }
1734
1735             ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1736
1737             if( InvalidateCB->Reason == AFS_INVALIDATE_CREDS)
1738             {
1739                 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1740             }
1741
1742             if( InvalidateCB->Reason == AFS_INVALIDATE_DATA_VERSION)
1743             {
1744                 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1745             }
1746             else
1747             {
1748                 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1749             }
1750
1751             AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
1752                                             NULL,
1753                                             FILE_NOTIFY_CHANGE_FILE_NAME |
1754                                             FILE_NOTIFY_CHANGE_ATTRIBUTES,
1755                                             FILE_ACTION_MODIFIED);
1756
1757             try_return( ntStatus);
1758         }
1759
1760         //
1761         // Depending on the reason for invalidation then perform work on the node
1762         //
1763
1764         switch( InvalidateCB->Reason)
1765         {
1766
1767             case AFS_INVALIDATE_DELETED:
1768             {
1769
1770                 //
1771                 // Mark this node as invalid
1772                 //
1773
1774                 SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DELETED);
1775
1776                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1777                               AFS_TRACE_LEVEL_VERBOSE,
1778                               "AFSInvalidateCache Set DELETE flag on fid %08lX-%08lX-%08lX-%08lX\n",
1779                               pObjectInfo->FileId.Cell,
1780                               pObjectInfo->FileId.Volume,
1781                               pObjectInfo->FileId.Vnode,
1782                               pObjectInfo->FileId.Unique);
1783
1784                 if( pObjectInfo->ParentObjectInformation != NULL)
1785                 {
1786
1787                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1788                                   AFS_TRACE_LEVEL_VERBOSE,
1789                                   "AFSInvalidateCache Set VERIFY flag on parent fid %08lX-%08lX-%08lX-%08lX\n",
1790                                   pObjectInfo->ParentObjectInformation->FileId.Cell,
1791                                   pObjectInfo->ParentObjectInformation->FileId.Volume,
1792                                   pObjectInfo->ParentObjectInformation->FileId.Vnode,
1793                                   pObjectInfo->ParentObjectInformation->FileId.Unique);
1794
1795                     SetFlag( pObjectInfo->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
1796                     pObjectInfo->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
1797                     pObjectInfo->ParentObjectInformation->Expiration.QuadPart = 0;
1798                 }
1799
1800                 if( pObjectInfo->FileType == AFS_FILE_TYPE_DIRECTORY)
1801                 {
1802                     ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1803                 }
1804                 else
1805                 {
1806                     ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1807                 }
1808
1809                 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
1810                                                 NULL,
1811                                                 ulFilter,
1812                                                 FILE_ACTION_REMOVED);
1813
1814                 break;
1815             }
1816
1817             case AFS_INVALIDATE_FLUSHED:
1818             {
1819
1820                 if( pObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
1821                     pObjectInfo->Fcb != NULL)
1822                 {
1823
1824                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1825                                   AFS_TRACE_LEVEL_VERBOSE,
1826                                   "AFSInvalidateCache Flush/purge file fid %08lX-%08lX-%08lX-%08lX\n",
1827                                   pObjectInfo->FileId.Cell,
1828                                   pObjectInfo->FileId.Volume,
1829                                   pObjectInfo->FileId.Vnode,
1830                                   pObjectInfo->FileId.Unique);
1831
1832                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
1833                                     TRUE);
1834
1835                     __try
1836                     {
1837
1838                         CcFlushCache( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
1839                                       NULL,
1840                                       0,
1841                                       &stIoStatus);
1842
1843                         if( !NT_SUCCESS( stIoStatus.Status))
1844                         {
1845
1846                             AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
1847                                           AFS_TRACE_LEVEL_ERROR,
1848                                           "AFSInvalidateCache CcFlushCache failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1849                                           pObjectInfo->FileId.Cell,
1850                                           pObjectInfo->FileId.Volume,
1851                                           pObjectInfo->FileId.Vnode,
1852                                           pObjectInfo->FileId.Unique,
1853                                           stIoStatus.Status,
1854                                           stIoStatus.Information);
1855
1856                             ntStatus = stIoStatus.Status;
1857                         }
1858
1859                         CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
1860                                              NULL,
1861                                              0,
1862                                              FALSE);
1863                     }
1864                     __except( EXCEPTION_EXECUTE_HANDLER)
1865                     {
1866
1867                         ntStatus = GetExceptionCode();
1868                     }
1869
1870                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
1871
1872                     //
1873                     // Clear out the extents
1874                     // Get rid of them (note this involves waiting
1875                     // for any writes or reads to the cache to complete)
1876                     //
1877
1878                     (VOID) AFSTearDownFcbExtents( pObjectInfo->Fcb);
1879                 }
1880
1881                 // Fall through to the default processing
1882             }
1883
1884             default:
1885             {
1886
1887                 if( pObjectInfo->FileType == AFS_FILE_TYPE_DIRECTORY)
1888                 {
1889                     ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1890                 }
1891                 else
1892                 {
1893                     ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1894                 }
1895
1896                 if( InvalidateCB->Reason == AFS_INVALIDATE_CREDS)
1897                 {
1898                     ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1899                 }
1900
1901                 if( InvalidateCB->Reason == AFS_INVALIDATE_DATA_VERSION)
1902                 {
1903                     ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1904                 }
1905                 else
1906                 {
1907                     ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1908                 }
1909
1910                 AFSFsRtlNotifyFullReportChange( pObjectInfo->ParentObjectInformation,
1911                                                 NULL,
1912                                                 ulFilter,
1913                                                 FILE_ACTION_MODIFIED);
1914
1915                 //
1916                 // Indicate this node requires re-evaluation for the remaining reasons
1917                 //
1918
1919                 pObjectInfo->Expiration.QuadPart = 0;
1920
1921                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1922                               AFS_TRACE_LEVEL_VERBOSE,
1923                               "AFSInvalidateCache Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1924                               pObjectInfo->FileId.Cell,
1925                               pObjectInfo->FileId.Volume,
1926                               pObjectInfo->FileId.Vnode,
1927                               pObjectInfo->FileId.Unique);
1928
1929                 SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1930
1931                 if( InvalidateCB->Reason == AFS_INVALIDATE_FLUSHED ||
1932                     InvalidateCB->Reason == AFS_INVALIDATE_DATA_VERSION)
1933                 {
1934                     pObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1935
1936                     if( pObjectInfo->FileType == AFS_FILE_TYPE_FILE)
1937                     {
1938
1939                         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1940                                       AFS_TRACE_LEVEL_VERBOSE,
1941                                       "AFSInvalidateCache Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
1942                                       pObjectInfo->FileId.Cell,
1943                                       pObjectInfo->FileId.Volume,
1944                                       pObjectInfo->FileId.Vnode,
1945                                       pObjectInfo->FileId.Unique);
1946
1947                         SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1948                     }
1949                 }
1950
1951                 break;
1952             }
1953         }
1954
1955 try_exit:
1956
1957         if( pObjectInfo != NULL)
1958         {
1959
1960             InterlockedDecrement( &pObjectInfo->ObjectReferenceCount);
1961
1962             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1963                           AFS_TRACE_LEVEL_VERBOSE,
1964                           "AFSInvalidateCache Decrement count on object %08lX Cnt %d\n",
1965                           pObjectInfo,
1966                           pObjectInfo->ObjectReferenceCount);
1967         }
1968     }
1969
1970     return ntStatus;
1971 }
1972
1973 BOOLEAN
1974 AFSIsChildOfParent( IN AFSFcb *Dcb,
1975                     IN AFSFcb *Fcb)
1976 {
1977
1978     BOOLEAN bIsChild = FALSE;
1979     AFSFcb *pCurrentFcb = Fcb;
1980
1981     while( pCurrentFcb != NULL)
1982     {
1983
1984         if( pCurrentFcb->ObjectInformation->ParentObjectInformation == Dcb->ObjectInformation)
1985         {
1986
1987             bIsChild = TRUE;
1988
1989             break;
1990         }
1991
1992         pCurrentFcb = pCurrentFcb->ObjectInformation->ParentObjectInformation->Fcb;
1993     }
1994
1995     return bIsChild;
1996 }
1997
1998 inline
1999 ULONGLONG
2000 AFSCreateHighIndex( IN AFSFileID *FileID)
2001 {
2002
2003     ULONGLONG ullIndex = 0;
2004
2005     ullIndex = (((ULONGLONG)FileID->Cell << 32) | FileID->Volume);
2006
2007     return ullIndex;
2008 }
2009
2010 inline
2011 ULONGLONG
2012 AFSCreateLowIndex( IN AFSFileID *FileID)
2013 {
2014
2015     ULONGLONG ullIndex = 0;
2016
2017     ullIndex = (((ULONGLONG)FileID->Vnode << 32) | FileID->Unique);
2018
2019     return ullIndex;
2020 }
2021
2022 BOOLEAN
2023 AFSCheckAccess( IN ACCESS_MASK DesiredAccess,
2024                 IN ACCESS_MASK GrantedAccess,
2025                 IN BOOLEAN DirectoryEntry)
2026 {
2027
2028     BOOLEAN bAccessGranted = TRUE;
2029
2030     //
2031     // Check if we are asking for read/write and granted only read only
2032     // NOTE: There will be more checks here
2033     //
2034
2035     if( !AFSCheckForReadOnlyAccess( DesiredAccess,
2036                                     DirectoryEntry) &&
2037         AFSCheckForReadOnlyAccess( GrantedAccess,
2038                                    DirectoryEntry))
2039     {
2040
2041         bAccessGranted = FALSE;
2042     }
2043
2044     return bAccessGranted;
2045 }
2046
2047 NTSTATUS
2048 AFSGetDriverStatus( IN AFSDriverStatusRespCB *DriverStatus)
2049 {
2050
2051     NTSTATUS         ntStatus = STATUS_SUCCESS;
2052     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2053
2054     //
2055     // Start with read
2056     //
2057
2058     DriverStatus->Status = AFS_DRIVER_STATUS_READY;
2059
2060     if( AFSGlobalRoot == NULL)
2061     {
2062
2063         //
2064         // We are not ready
2065         //
2066
2067         DriverStatus->Status = AFS_DRIVER_STATUS_NOT_READY;
2068     }
2069
2070     if( pControlDevExt->Specific.Control.CommServiceCB.IrpPoolControlFlag != POOL_ACTIVE)
2071     {
2072
2073         //
2074         // No service yet
2075         //
2076
2077         DriverStatus->Status = AFS_DRIVER_STATUS_NO_SERVICE;
2078     }
2079
2080     return ntStatus;
2081 }
2082
2083 NTSTATUS
2084 AFSSubstituteSysName( IN UNICODE_STRING *ComponentName,
2085                       IN UNICODE_STRING *SubstituteName,
2086                       IN ULONG StringIndex)
2087 {
2088
2089     NTSTATUS ntStatus = STATUS_SUCCESS;
2090     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2091     AFSSysNameCB    *pSysName = NULL;
2092     ERESOURCE       *pSysNameLock = NULL;
2093     ULONG            ulIndex = 1;
2094     USHORT           usIndex = 0;
2095     UNICODE_STRING   uniSysName;
2096
2097     __Enter
2098     {
2099
2100 #if defined(_WIN64)
2101
2102         if( IoIs32bitProcess( NULL))
2103         {
2104
2105             pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2106
2107             pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2108         }
2109         else
2110         {
2111
2112             pSysNameLock = &pControlDevExt->Specific.Control.SysName64ListLock;
2113
2114             pSysName = pControlDevExt->Specific.Control.SysName64ListHead;
2115         }
2116 #else
2117
2118         pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2119
2120         pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2121
2122 #endif
2123
2124         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2125                       AFS_TRACE_LEVEL_VERBOSE,
2126                       "AFSSubstituteSysName Acquiring SysName lock %08lX SHARED %08lX\n",
2127                       pSysNameLock,
2128                       PsGetCurrentThread());
2129
2130         AFSAcquireShared( pSysNameLock,
2131                           TRUE);
2132
2133         //
2134         // Find where we are in the list
2135         //
2136
2137         while( pSysName != NULL &&
2138             ulIndex < StringIndex)
2139         {
2140
2141             pSysName = pSysName->fLink;
2142
2143             ulIndex++;
2144         }
2145
2146         if( pSysName == NULL)
2147         {
2148
2149             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
2150         }
2151
2152         RtlInitUnicodeString( &uniSysName,
2153                               L"@SYS");
2154         //
2155         // If it is a full component of @SYS then just substitue the
2156         // name in
2157         //
2158
2159         if( RtlCompareUnicodeString( &uniSysName,
2160                                      ComponentName,
2161                                      TRUE) == 0)
2162         {
2163
2164             SubstituteName->Length = pSysName->SysName.Length;
2165             SubstituteName->MaximumLength = SubstituteName->Length;
2166
2167             SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2168                                                                         SubstituteName->Length,
2169                                                                         AFS_SUBST_BUFFER_TAG);
2170
2171             if( SubstituteName->Buffer == NULL)
2172             {
2173
2174                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2175             }
2176
2177             RtlCopyMemory( SubstituteName->Buffer,
2178                            pSysName->SysName.Buffer,
2179                            pSysName->SysName.Length);
2180         }
2181         else
2182         {
2183
2184             usIndex = 0;
2185
2186             while( ComponentName->Buffer[ usIndex] != L'@')
2187             {
2188
2189                 usIndex++;
2190             }
2191
2192             SubstituteName->Length = (usIndex * sizeof( WCHAR)) + pSysName->SysName.Length;
2193             SubstituteName->MaximumLength = SubstituteName->Length;
2194
2195             SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2196                                                                         SubstituteName->Length,
2197                                                                         AFS_SUBST_BUFFER_TAG);
2198
2199             if( SubstituteName->Buffer == NULL)
2200             {
2201
2202                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2203             }
2204
2205             RtlCopyMemory( SubstituteName->Buffer,
2206                            ComponentName->Buffer,
2207                            usIndex * sizeof( WCHAR));
2208
2209             RtlCopyMemory( &SubstituteName->Buffer[ usIndex],
2210                            pSysName->SysName.Buffer,
2211                            pSysName->SysName.Length);
2212         }
2213
2214 try_exit:
2215
2216         AFSReleaseResource( pSysNameLock);
2217     }
2218
2219     return ntStatus;
2220 }
2221
2222 NTSTATUS
2223 AFSSubstituteNameInPath( IN OUT UNICODE_STRING *FullPathName,
2224                          IN OUT UNICODE_STRING *ComponentName,
2225                          IN UNICODE_STRING *SubstituteName,
2226                          IN OUT UNICODE_STRING *RemainingPath,
2227                          IN BOOLEAN FreePathName)
2228 {
2229
2230     NTSTATUS ntStatus = STATUS_SUCCESS;
2231     UNICODE_STRING uniPathName;
2232     USHORT usPrefixNameLen = 0;
2233     SHORT  sNameLenDelta = 0;
2234
2235     __Enter
2236     {
2237
2238         //
2239         // If the passed in name can handle the additional length
2240         // then just moves things around
2241         //
2242
2243         sNameLenDelta = SubstituteName->Length - ComponentName->Length;
2244
2245         usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2246
2247         if( FullPathName->MaximumLength > FullPathName->Length + sNameLenDelta)
2248         {
2249
2250             if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2251             {
2252
2253                 RtlMoveMemory( &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + SubstituteName->Length)/sizeof( WCHAR))],
2254                                &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + ComponentName->Length)/sizeof( WCHAR))],
2255                                FullPathName->Length - usPrefixNameLen*sizeof( WCHAR) - ComponentName->Length);
2256             }
2257
2258             RtlCopyMemory( &FullPathName->Buffer[ usPrefixNameLen],
2259                            SubstituteName->Buffer,
2260                            SubstituteName->Length);
2261
2262             FullPathName->Length += sNameLenDelta;
2263
2264             ComponentName->Length += sNameLenDelta;
2265
2266             ComponentName->MaximumLength = ComponentName->Length;
2267
2268             if ( RemainingPath->Buffer)
2269             {
2270
2271                 RemainingPath->Buffer += sNameLenDelta/sizeof( WCHAR);
2272             }
2273
2274             try_return( ntStatus);
2275         }
2276
2277         //
2278         // Need to re-allocate the buffer
2279         //
2280
2281         uniPathName.Length = FullPathName->Length -
2282                                          ComponentName->Length +
2283                                          SubstituteName->Length;
2284
2285         uniPathName.MaximumLength = FullPathName->MaximumLength + PAGE_SIZE;
2286
2287         uniPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2288                                                                 uniPathName.MaximumLength,
2289                                                                 AFS_NAME_BUFFER_FOUR_TAG);
2290
2291         if( uniPathName.Buffer == NULL)
2292         {
2293
2294             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2295         }
2296
2297         usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2298
2299         usPrefixNameLen *= sizeof( WCHAR);
2300
2301         RtlZeroMemory( uniPathName.Buffer,
2302                        uniPathName.MaximumLength);
2303
2304         RtlCopyMemory( uniPathName.Buffer,
2305                        FullPathName->Buffer,
2306                        usPrefixNameLen);
2307
2308         RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen/sizeof( WCHAR))],
2309                        SubstituteName->Buffer,
2310                        SubstituteName->Length);
2311
2312         if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2313         {
2314
2315             RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen + SubstituteName->Length)/sizeof( WCHAR)],
2316                            &FullPathName->Buffer[ (usPrefixNameLen + ComponentName->Length)/sizeof( WCHAR)],
2317                            FullPathName->Length - usPrefixNameLen - ComponentName->Length);
2318         }
2319
2320         ComponentName->Buffer = uniPathName.Buffer + (ComponentName->Buffer - FullPathName->Buffer);
2321
2322         ComponentName->Length += sNameLenDelta;
2323
2324         ComponentName->MaximumLength = ComponentName->Length;
2325
2326         if ( RemainingPath->Buffer)
2327         {
2328
2329             RemainingPath->Buffer = uniPathName.Buffer
2330                 + (RemainingPath->Buffer - FullPathName->Buffer)
2331                 + sNameLenDelta/sizeof( WCHAR);
2332         }
2333
2334         if( FreePathName)
2335         {
2336             AFSExFreePool( FullPathName->Buffer);
2337         }
2338
2339         *FullPathName = uniPathName;
2340
2341 try_exit:
2342
2343         NOTHING;
2344     }
2345
2346     return ntStatus;
2347 }
2348
2349 NTSTATUS
2350 AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
2351                      IN ULONG Reason)
2352 {
2353
2354     NTSTATUS ntStatus = STATUS_SUCCESS;
2355     AFSFcb *pFcb = NULL;
2356     AFSObjectInfoCB *pCurrentObject = NULL;
2357     ULONG ulFilter = 0;
2358
2359     __Enter
2360     {
2361
2362         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2363                       AFS_TRACE_LEVEL_VERBOSE,
2364                       "AFSInvalidateVolume Invalidate volume fid %08lX-%08lX-%08lX-%08lX Reason %08lX\n",
2365                       VolumeCB->ObjectInformation.FileId.Cell,
2366                       VolumeCB->ObjectInformation.FileId.Volume,
2367                       VolumeCB->ObjectInformation.FileId.Vnode,
2368                       VolumeCB->ObjectInformation.FileId.Unique,
2369                       Reason);
2370
2371         //
2372         // Depending on the reason for invalidation then perform work on the node
2373         //
2374
2375         switch( Reason)
2376         {
2377
2378             case AFS_INVALIDATE_DELETED:
2379             {
2380
2381                 //
2382                 // Mark this volume as invalid
2383                 //
2384
2385                 VolumeCB->ObjectInformation.Expiration.QuadPart = 0;
2386
2387                 SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
2388
2389                 SetFlag( VolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE);
2390
2391                 AFSFsRtlNotifyFullReportChange( &VolumeCB->ObjectInformation,
2392                                                 NULL,
2393                                                 FILE_NOTIFY_CHANGE_DIR_NAME,
2394                                                 FILE_ACTION_REMOVED);
2395
2396                 AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2397                                   TRUE);
2398
2399                 pCurrentObject = VolumeCB->ObjectInfoListHead;
2400
2401                 while( pCurrentObject != NULL)
2402                 {
2403
2404                     if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY)
2405                     {
2406                         ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
2407                     }
2408                     else
2409                     {
2410                         ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
2411                     }
2412
2413                     AFSFsRtlNotifyFullReportChange( pCurrentObject,
2414                                                     NULL,
2415                                                     ulFilter,
2416                                                     FILE_ACTION_REMOVED);
2417
2418                     SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
2419
2420                     pFcb = pCurrentObject->Fcb;
2421
2422                     if( pFcb != NULL &&
2423                         pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
2424                     {
2425
2426
2427                         //
2428                         // Clear out the extents
2429                         // And get rid of them (note this involves waiting
2430                         // for any writes or reads to the cache to complete)
2431                         //
2432
2433                         (VOID) AFSTearDownFcbExtents( pFcb);
2434                     }
2435
2436                     pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2437                 }
2438
2439                 AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2440
2441                 break;
2442             }
2443
2444             default:
2445             {
2446
2447                 //
2448                 // Indicate this node requires re-evaluation for the remaining reasons
2449                 //
2450
2451                 VolumeCB->ObjectInformation.Expiration.QuadPart = 0;
2452
2453                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2454                               AFS_TRACE_LEVEL_VERBOSE,
2455                               "AFSInvalidateVolume Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
2456                               VolumeCB->ObjectInformation.FileId.Cell,
2457                               VolumeCB->ObjectInformation.FileId.Volume,
2458                               VolumeCB->ObjectInformation.FileId.Vnode,
2459                               VolumeCB->ObjectInformation.FileId.Unique);
2460
2461                 SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_VERIFY);
2462
2463                 if( Reason == AFS_INVALIDATE_FLUSHED ||
2464                     Reason == AFS_INVALIDATE_DATA_VERSION)
2465                 {
2466
2467                     VolumeCB->ObjectInformation.DataVersion.QuadPart = (ULONGLONG)-1;
2468                 }
2469
2470                 //
2471                 // Notify anyone that cares
2472                 //
2473
2474                 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
2475
2476                 if( Reason == AFS_INVALIDATE_CREDS)
2477                 {
2478                     ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
2479                 }
2480
2481                 if( Reason == AFS_INVALIDATE_DATA_VERSION)
2482                 {
2483                     ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
2484                 }
2485                 else
2486                 {
2487                     ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
2488                 }
2489
2490                 AFSFsRtlNotifyFullReportChange( &VolumeCB->ObjectInformation,
2491                                                 NULL,
2492                                                 ulFilter,
2493                                                 FILE_ACTION_MODIFIED);
2494
2495                 //
2496                 // Volume invalidations require all objects in the volume be re-verified
2497                 //
2498
2499                 AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2500                                   TRUE);
2501
2502                 pCurrentObject = VolumeCB->ObjectInfoListHead;
2503
2504                 while( pCurrentObject != NULL)
2505                 {
2506
2507                     pCurrentObject->Expiration.QuadPart = 0;
2508
2509                     pCurrentObject->TargetFileId.Vnode = 0;
2510
2511                     pCurrentObject->TargetFileId.Unique = 0;
2512
2513                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2514                                   AFS_TRACE_LEVEL_VERBOSE,
2515                                   "AFSInvalidateVolume Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
2516                                   pCurrentObject->FileId.Cell,
2517                                   pCurrentObject->FileId.Volume,
2518                                   pCurrentObject->FileId.Vnode,
2519                                   pCurrentObject->FileId.Unique);
2520
2521                     SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
2522
2523                     if( Reason == AFS_INVALIDATE_FLUSHED ||
2524                         Reason == AFS_INVALIDATE_DATA_VERSION)
2525                     {
2526
2527                         pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
2528
2529                         if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
2530                         {
2531
2532                             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2533                                           AFS_TRACE_LEVEL_VERBOSE,
2534                                           "AFSInvalidateVolume Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
2535                                           pCurrentObject->FileId.Cell,
2536                                           pCurrentObject->FileId.Volume,
2537                                           pCurrentObject->FileId.Vnode,
2538                                           pCurrentObject->FileId.Unique);
2539
2540                             SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
2541                         }
2542                     }
2543
2544                     if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY)
2545                     {
2546                         ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
2547                     }
2548                     else
2549                     {
2550                         ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
2551                     }
2552
2553                     if( Reason == AFS_INVALIDATE_CREDS)
2554                     {
2555                         ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
2556                     }
2557
2558                     if( Reason == AFS_INVALIDATE_DATA_VERSION)
2559                     {
2560                         ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
2561                     }
2562                     else
2563                     {
2564                         ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
2565                     }
2566
2567                     AFSFsRtlNotifyFullReportChange( pCurrentObject,
2568                                                     NULL,
2569                                                     ulFilter,
2570                                                     FILE_ACTION_MODIFIED);
2571
2572                     pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2573                 }
2574
2575                 AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2576
2577                 break;
2578             }
2579         }
2580     }
2581
2582     return ntStatus;
2583 }
2584
2585 NTSTATUS
2586 AFSVerifyEntry( IN GUID *AuthGroup,
2587                 IN AFSDirectoryCB *DirEntry)
2588 {
2589
2590     NTSTATUS ntStatus = STATUS_SUCCESS;
2591     AFSDirEnumEntry *pDirEnumEntry = NULL;
2592     AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
2593     IO_STATUS_BLOCK stIoStatus;
2594
2595     __Enter
2596     {
2597
2598         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2599                       AFS_TRACE_LEVEL_VERBOSE_2,
2600                       "AFSVerifyEntry Verifying entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2601                       &DirEntry->NameInformation.FileName,
2602                       pObjectInfo->FileId.Cell,
2603                       pObjectInfo->FileId.Volume,
2604                       pObjectInfo->FileId.Vnode,
2605                       pObjectInfo->FileId.Unique);
2606
2607         ntStatus = AFSEvaluateTargetByID( pObjectInfo,
2608                                           AuthGroup,
2609                                           FALSE,
2610                                           &pDirEnumEntry);
2611
2612         if( !NT_SUCCESS( ntStatus))
2613         {
2614
2615             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2616                           AFS_TRACE_LEVEL_ERROR,
2617                           "AFSValidateEntry Evaluate Target failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2618                           &DirEntry->NameInformation.FileName,
2619                           pObjectInfo->FileId.Cell,
2620                           pObjectInfo->FileId.Volume,
2621                           pObjectInfo->FileId.Vnode,
2622                           pObjectInfo->FileId.Unique,
2623                           ntStatus);
2624
2625             try_return( ntStatus);
2626         }
2627
2628         //
2629         // Check the data version of the file
2630         //
2631
2632         if( pObjectInfo->DataVersion.QuadPart == pDirEnumEntry->DataVersion.QuadPart &&
2633             !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2634         {
2635
2636             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2637                           AFS_TRACE_LEVEL_VERBOSE,
2638                           "AFSVerifyEntry No DV change %I64X for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2639                           pObjectInfo->DataVersion.QuadPart,
2640                           &DirEntry->NameInformation.FileName,
2641                           pObjectInfo->FileId.Cell,
2642                           pObjectInfo->FileId.Volume,
2643                           pObjectInfo->FileId.Vnode,
2644                           pObjectInfo->FileId.Unique);
2645
2646             //
2647             // We are ok, just get out
2648             //
2649
2650             ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2651
2652             try_return( ntStatus = STATUS_SUCCESS);
2653         }
2654
2655         //
2656         // New data version so we will need to process the node based on the type
2657         //
2658
2659         switch( pDirEnumEntry->FileType)
2660         {
2661
2662             case AFS_FILE_TYPE_MOUNTPOINT:
2663             {
2664
2665                 //
2666                 // For a mount point we need to ensure the target is the same
2667                 //
2668
2669                 if( !AFSIsEqualFID( &pObjectInfo->TargetFileId,
2670                                     &pDirEnumEntry->TargetFileId))
2671                 {
2672
2673                 }
2674
2675                 //
2676                 // Update the metadata for the entry
2677                 //
2678
2679                 ntStatus = AFSUpdateMetaData( DirEntry,
2680                                               pDirEnumEntry);
2681
2682                 if( NT_SUCCESS( ntStatus))
2683                 {
2684
2685                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2686                 }
2687
2688                 break;
2689             }
2690
2691             case AFS_FILE_TYPE_SYMLINK:
2692             {
2693
2694                 ASSERT( pDirEnumEntry->TargetNameLength > 0);
2695
2696                 //
2697                 // Update the metadata for the entry
2698                 //
2699
2700                 ntStatus = AFSUpdateMetaData( DirEntry,
2701                                               pDirEnumEntry);
2702
2703                 if( NT_SUCCESS( ntStatus))
2704                 {
2705
2706                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2707                 }
2708
2709                 break;
2710             }
2711
2712             case AFS_FILE_TYPE_FILE:
2713             {
2714                 FILE_OBJECT * pCCFileObject = NULL;
2715                 BOOLEAN bPurgeExtents = FALSE;
2716
2717                 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2718                 {
2719                     bPurgeExtents = TRUE;
2720
2721                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2722                                   AFS_TRACE_LEVEL_VERBOSE,
2723                                   "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2724                                   &DirEntry->NameInformation.FileName,
2725                                   pObjectInfo->FileId.Cell,
2726                                   pObjectInfo->FileId.Volume,
2727                                   pObjectInfo->FileId.Vnode,
2728                                   pObjectInfo->FileId.Unique);
2729
2730                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
2731                 }
2732
2733                 //
2734                 // Update the metadata for the entry
2735                 //
2736
2737                 ntStatus = AFSUpdateMetaData( DirEntry,
2738                                               pDirEnumEntry);
2739
2740                 if( !NT_SUCCESS( ntStatus))
2741                 {
2742
2743                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2744                                   AFS_TRACE_LEVEL_ERROR,
2745                                   "AFSInvalidateCache Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
2746                                   &DirEntry->NameInformation.FileName,
2747                                   pObjectInfo->FileId.Cell,
2748                                   pObjectInfo->FileId.Volume,
2749                                   pObjectInfo->FileId.Vnode,
2750                                   pObjectInfo->FileId.Unique,
2751                                   ntStatus);
2752
2753                     break;
2754                 }
2755
2756                 if( pObjectInfo->Fcb != NULL)
2757                 {
2758
2759                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2760                                   AFS_TRACE_LEVEL_VERBOSE,
2761                                   "AFSVerifyEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2762                                   &DirEntry->NameInformation.FileName,
2763                                   pObjectInfo->FileId.Cell,
2764                                   pObjectInfo->FileId.Volume,
2765                                   pObjectInfo->FileId.Vnode,
2766                                   pObjectInfo->FileId.Unique);
2767
2768                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
2769                                     TRUE);
2770
2771                     __try
2772                     {
2773
2774                         CcFlushCache( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2775                                       NULL,
2776                                       0,
2777                                       &stIoStatus);
2778
2779                         if( !NT_SUCCESS( stIoStatus.Status))
2780                         {
2781
2782                             AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2783                                           AFS_TRACE_LEVEL_ERROR,
2784                                           "AFSVerifyEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
2785                                           &DirEntry->NameInformation.FileName,
2786                                           pObjectInfo->FileId.Cell,
2787                                           pObjectInfo->FileId.Volume,
2788                                           pObjectInfo->FileId.Vnode,
2789                                           pObjectInfo->FileId.Unique,
2790                                           stIoStatus.Status,
2791                                           stIoStatus.Information);
2792
2793                             ntStatus = stIoStatus.Status;
2794                         }
2795
2796                         if ( bPurgeExtents)
2797                         {
2798
2799                             CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
2800                                                  NULL,
2801                                                  0,
2802                                                  FALSE);
2803                         }
2804                     }
2805                     __except( EXCEPTION_EXECUTE_HANDLER)
2806                     {
2807                         ntStatus = GetExceptionCode();
2808
2809                         AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2810                                       AFS_TRACE_LEVEL_ERROR,
2811                                       "AFSVerifyEntry CcFlushCache or CcPurgeCacheSection Exception %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2812                                       &DirEntry->NameInformation.FileName,
2813                                       pObjectInfo->FileId.Cell,
2814                                       pObjectInfo->FileId.Volume,
2815                                       pObjectInfo->FileId.Vnode,
2816                                       pObjectInfo->FileId.Unique,
2817                                       ntStatus);
2818                     }
2819
2820                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
2821
2822                     if ( bPurgeExtents)
2823                     {
2824                         AFSFlushExtents( pObjectInfo->Fcb);
2825                     }
2826
2827                     //
2828                     // Reacquire the Fcb to purge the cache
2829                     //
2830
2831                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2832                                   AFS_TRACE_LEVEL_VERBOSE,
2833                                   "AFSVerifyEntry Acquiring Fcb lock %08lX EXCL %08lX\n",
2834                                   &pObjectInfo->Fcb->NPFcb->Resource,
2835                                   PsGetCurrentThread());
2836
2837                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
2838                                     TRUE);
2839
2840                     //
2841                     // Update file sizes
2842                     //
2843
2844                     pObjectInfo->Fcb->Header.AllocationSize.QuadPart  = pObjectInfo->AllocationSize.QuadPart;
2845                     pObjectInfo->Fcb->Header.FileSize.QuadPart        = pObjectInfo->EndOfFile.QuadPart;
2846                     pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
2847
2848                     pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
2849
2850                     if ( pCCFileObject != NULL)
2851                     {
2852                         CcSetFileSizes( pCCFileObject,
2853                                         (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
2854                     }
2855
2856                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
2857                 }
2858                 else
2859                 {
2860                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2861                                   AFS_TRACE_LEVEL_WARNING,
2862                                   "AFSValidateEntry Fcb NULL %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2863                                   &DirEntry->NameInformation.FileName,
2864                                   pObjectInfo->FileId.Cell,
2865                                   pObjectInfo->FileId.Volume,
2866                                   pObjectInfo->FileId.Vnode,
2867                                   pObjectInfo->FileId.Unique);
2868                 }
2869
2870                 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2871
2872                 break;
2873             }
2874
2875             case AFS_FILE_TYPE_DIRECTORY:
2876             {
2877
2878                 AFSFcb *pCurrentFcb = NULL;
2879                 AFSDirectoryCB *pCurrentDirEntry = NULL;
2880
2881                 //
2882                 // For a directory or root entry flush the content of
2883                 // the directory enumeration.
2884                 //
2885
2886                 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
2887                 {
2888
2889                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2890                                   AFS_TRACE_LEVEL_VERBOSE_2,
2891                                   "AFSVerifyEntry Validating directory content for entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2892                                   &DirEntry->NameInformation.FileName,
2893                                   pObjectInfo->FileId.Cell,
2894                                   pObjectInfo->FileId.Volume,
2895                                   pObjectInfo->FileId.Vnode,
2896                                   pObjectInfo->FileId.Unique);
2897
2898                     AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2899                                     TRUE);
2900
2901                     AFSValidateDirectoryCache( pObjectInfo,
2902                                                AuthGroup);
2903
2904                     AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2905                 }
2906
2907                 //
2908                 // Update the metadata for the entry
2909                 //
2910
2911                 ntStatus = AFSUpdateMetaData( DirEntry,
2912                                               pDirEnumEntry);
2913
2914                 if( NT_SUCCESS( ntStatus))
2915                 {
2916
2917                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2918                 }
2919
2920                 break;
2921             }
2922
2923             case AFS_FILE_TYPE_DFSLINK:
2924             {
2925
2926                 UNICODE_STRING uniTargetName;
2927
2928                 //
2929                 // For a DFS link need to check the target name has not changed
2930                 //
2931
2932                 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
2933
2934                 uniTargetName.MaximumLength = uniTargetName.Length;
2935
2936                 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
2937
2938                 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
2939                                 TRUE);
2940
2941                 if( DirEntry->NameInformation.TargetName.Length == 0 ||
2942                     RtlCompareUnicodeString( &uniTargetName,
2943                                              &DirEntry->NameInformation.TargetName,
2944                                              TRUE) != 0)
2945                 {
2946
2947                     //
2948                     // Update the target name
2949                     //
2950
2951                     ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
2952                                                     &DirEntry->Flags,
2953                                                     uniTargetName.Buffer,
2954                                                     uniTargetName.Length);
2955
2956                     if( !NT_SUCCESS( ntStatus))
2957                     {
2958
2959                         AFSReleaseResource( &DirEntry->NonPaged->Lock);
2960
2961                         break;
2962                     }
2963                 }
2964
2965                 AFSReleaseResource( &DirEntry->NonPaged->Lock);
2966
2967                 //
2968                 // Update the metadata for the entry
2969                 //
2970
2971                 ntStatus = AFSUpdateMetaData( DirEntry,
2972                                               pDirEnumEntry);
2973
2974                 if( NT_SUCCESS( ntStatus))
2975                 {
2976
2977                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2978                 }
2979
2980                 break;
2981             }
2982
2983             default:
2984
2985                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2986                               AFS_TRACE_LEVEL_WARNING,
2987                               "AFSVerifyEntry Attempt to verify node of type %d\n",
2988                               pObjectInfo->FileType);
2989
2990                 break;
2991         }
2992
2993  try_exit:
2994
2995         if( pDirEnumEntry != NULL)
2996         {
2997
2998             AFSExFreePool( pDirEnumEntry);
2999         }
3000     }
3001
3002     return ntStatus;
3003 }
3004
3005 NTSTATUS
3006 AFSSetVolumeState( IN AFSVolumeStatusCB *VolumeStatus)
3007 {
3008
3009     NTSTATUS ntStatus = STATUS_SUCCESS;
3010     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
3011     ULONGLONG   ullIndex = 0;
3012     AFSVolumeCB *pVolumeCB = NULL;
3013     AFSFcb *pFcb = NULL;
3014     AFSObjectInfoCB *pCurrentObject = NULL;
3015
3016     __Enter
3017     {
3018
3019         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3020                       AFS_TRACE_LEVEL_VERBOSE,
3021                       "AFSSetVolumeState Marking volume state %d Volume Cell %08lX Volume %08lX\n",
3022                       VolumeStatus->Online,
3023                       VolumeStatus->FileID.Cell,
3024                       VolumeStatus->FileID.Volume);
3025
3026         //
3027         // Need to locate the Fcb for the directory to purge
3028         //
3029
3030         AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3031                       AFS_TRACE_LEVEL_VERBOSE,
3032                       "AFSSetVolumeState Acquiring RDR VolumeTreeLock lock %08lX SHARED %08lX\n",
3033                       &pDevExt->Specific.RDR.VolumeTreeLock,
3034                       PsGetCurrentThread());
3035
3036         AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
3037
3038         //
3039         // Locate the volume node
3040         //
3041
3042         ullIndex = AFSCreateHighIndex( &VolumeStatus->FileID);
3043
3044         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
3045                                        ullIndex,
3046                                        (AFSBTreeEntry **)&pVolumeCB);
3047
3048         if( pVolumeCB != NULL)
3049         {
3050
3051             InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
3052
3053             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3054
3055             //
3056             // Set the volume state accordingly
3057             //
3058
3059             if( VolumeStatus->Online)
3060             {
3061
3062                 InterlockedAnd( (LONG *)&(pVolumeCB->Flags), ~AFS_VOLUME_FLAGS_OFFLINE);
3063             }
3064             else
3065             {
3066
3067                 InterlockedOr( (LONG *)&(pVolumeCB->Flags), AFS_VOLUME_FLAGS_OFFLINE);
3068             }
3069
3070             AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
3071                               TRUE);
3072
3073             pCurrentObject = pVolumeCB->ObjectInfoListHead;;
3074
3075             while( pCurrentObject != NULL)
3076             {
3077
3078                 if( VolumeStatus->Online)
3079                 {
3080
3081                     ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
3082
3083                     SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_VERIFY);
3084
3085                     pCurrentObject->DataVersion.QuadPart = (ULONGLONG)-1;
3086                 }
3087                 else
3088                 {
3089
3090                     SetFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
3091                 }
3092
3093                 pFcb = pCurrentObject->Fcb;
3094
3095                 if( pFcb != NULL &&
3096                     !(VolumeStatus->Online) &&
3097                     pFcb->Header.NodeTypeCode == AFS_FILE_FCB)
3098                 {
3099
3100                     AFSDbgLogMsg( AFS_SUBSYSTEM_EXTENT_PROCESSING,
3101                                   AFS_TRACE_LEVEL_ERROR,
3102                                   "AFSSetVolumeState Marking volume offline and canceling extents Volume Cell %08lX Volume %08lX\n",
3103                                   VolumeStatus->FileID.Cell,
3104                                   VolumeStatus->FileID.Volume);
3105
3106                     //
3107                     // Clear out the extents
3108                     //
3109
3110                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3111                                   AFS_TRACE_LEVEL_VERBOSE,
3112                                   "AFSSetVolumeState Acquiring Fcb extents lock %08lX EXCL %08lX\n",
3113                                   &pFcb->NPFcb->Specific.File.ExtentsResource,
3114                                   PsGetCurrentThread());
3115
3116                     AFSAcquireExcl( &pFcb->NPFcb->Specific.File.ExtentsResource,
3117                                     TRUE);
3118
3119                     pFcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_CANCELLED;
3120
3121                     KeSetEvent( &pFcb->NPFcb->Specific.File.ExtentsRequestComplete,
3122                                 0,
3123                                 FALSE);
3124
3125                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3126                                   AFS_TRACE_LEVEL_VERBOSE,
3127                                   "AFSSetVolumeState Releasing Fcb extents lock %08lX EXCL %08lX\n",
3128                                   &pFcb->NPFcb->Specific.File.ExtentsResource,
3129                                   PsGetCurrentThread());
3130
3131                     AFSReleaseResource( &pFcb->NPFcb->Specific.File.ExtentsResource);
3132
3133                     //
3134                     // And get rid of them (note this involves waiting
3135                     // for any writes or reads to the cache to complete)
3136                     //
3137
3138                     (VOID) AFSTearDownFcbExtents( pFcb);
3139                 }
3140
3141                 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
3142             }
3143
3144             AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
3145
3146             InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
3147         }
3148         else
3149         {
3150
3151             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3152         }
3153     }
3154
3155     return ntStatus;
3156 }
3157
3158 NTSTATUS
3159 AFSSetNetworkState( IN AFSNetworkStatusCB *NetworkStatus)
3160 {
3161
3162     NTSTATUS ntStatus = STATUS_SUCCESS;
3163
3164     __Enter
3165     {
3166
3167         if( AFSGlobalRoot == NULL)
3168         {
3169
3170             try_return( ntStatus);
3171         }
3172
3173         AFSAcquireExcl( AFSGlobalRoot->VolumeLock,
3174                         TRUE);
3175
3176         //
3177         // Set the network state according to the information
3178         //
3179
3180         if( NetworkStatus->Online)
3181         {
3182
3183             ClearFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3184         }
3185         else
3186         {
3187
3188             SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3189         }
3190
3191         AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3192
3193 try_exit:
3194
3195         NOTHING;
3196     }
3197
3198     return ntStatus;
3199 }
3200
3201 NTSTATUS
3202 AFSValidateDirectoryCache( IN AFSObjectInfoCB *ObjectInfo,
3203                            IN GUID *AuthGroup)
3204 {
3205
3206     NTSTATUS ntStatus = STATUS_SUCCESS;
3207     BOOLEAN  bAcquiredLock = FALSE;
3208     AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
3209     AFSFcb *pFcb = NULL;
3210
3211     __Enter
3212     {
3213
3214         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
3215                       AFS_TRACE_LEVEL_VERBOSE,
3216                       "AFSValidateDirectoryCache Validating content for FID %08lX-%08lX-%08lX-%08lX\n",
3217                       ObjectInfo->FileId.Cell,
3218                       ObjectInfo->FileId.Volume,
3219                       ObjectInfo->FileId.Vnode,
3220                       ObjectInfo->FileId.Unique);
3221
3222         if( !ExIsResourceAcquiredLite( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock))
3223         {
3224
3225             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
3226                           AFS_TRACE_LEVEL_VERBOSE,
3227                           "AFSValidateDirectoryCache Acquiring DirectoryNodeHdr.TreeLock lock %08lX EXCL %08lX\n",
3228                           ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3229                           PsGetCurrentThread());
3230
3231             AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3232                             TRUE);
3233
3234             bAcquiredLock = TRUE;
3235         }
3236
3237         //
3238         // Check for inconsistency between DirectoryNodeList and DirectoryNodeCount
3239         //
3240
3241         if ( ObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL &&
32