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