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