Windows: Skip Extent operations if Direct IO
[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     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
1699     IO_STATUS_BLOCK stIoStatus;
1700     ULONG ulFilter = 0;
1701     AFSObjectInfoCB * pParentObjectInfo = NULL;
1702
1703     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1704                   AFS_TRACE_LEVEL_VERBOSE,
1705                   "AFSInvalidateObject Invalidation on node type %d for fid %08lX-%08lX-%08lX-%08lX Reason %d\n",
1706                   (*ppObjectInfo)->FileType,
1707                   (*ppObjectInfo)->FileId.Cell,
1708                   (*ppObjectInfo)->FileId.Volume,
1709                   (*ppObjectInfo)->FileId.Vnode,
1710                   (*ppObjectInfo)->FileId.Unique,
1711                   Reason));
1712
1713     if ( BooleanFlagOn( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1714     {
1715
1716         pParentObjectInfo = AFSFindObjectInfo( (*ppObjectInfo)->VolumeCB,
1717                                                &(*ppObjectInfo)->ParentFileId,
1718                                                FALSE);
1719     }
1720
1721     if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_SYMLINK ||
1722         (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DFSLINK ||
1723         (*ppObjectInfo)->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1724     {
1725         //
1726         // We only act on the mount point itself, not the target. If the
1727         // node has been deleted then mark it as such otherwise indicate
1728         // it requires verification
1729         //
1730
1731         if( Reason == AFS_INVALIDATE_DELETED)
1732         {
1733             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
1734         }
1735         else
1736         {
1737
1738             if( Reason == AFS_INVALIDATE_FLUSHED)
1739             {
1740
1741                 (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1742
1743                 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1744             }
1745
1746             (*ppObjectInfo)->Expiration.QuadPart = 0;
1747
1748             (*ppObjectInfo)->TargetFileId.Vnode = 0;
1749
1750             (*ppObjectInfo)->TargetFileId.Unique = 0;
1751
1752             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1753                           AFS_TRACE_LEVEL_VERBOSE,
1754                           "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1755                           (*ppObjectInfo)->FileId.Cell,
1756                           (*ppObjectInfo)->FileId.Volume,
1757                           (*ppObjectInfo)->FileId.Vnode,
1758                           (*ppObjectInfo)->FileId.Unique));
1759
1760             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1761         }
1762
1763         if ( pParentObjectInfo != NULL)
1764         {
1765
1766             ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1767
1768             if( Reason == AFS_INVALIDATE_CREDS)
1769             {
1770                 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1771             }
1772
1773             if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1774                 Reason == AFS_INVALIDATE_FLUSHED)
1775             {
1776                 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1777             }
1778             else
1779             {
1780                 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1781             }
1782
1783             AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1784                                             NULL,
1785                                             ulFilter,
1786                                             FILE_ACTION_MODIFIED);
1787         }
1788
1789         try_return( ntStatus);
1790     }
1791
1792     //
1793     // Depending on the reason for invalidation then perform work on the node
1794     //
1795
1796     switch( Reason)
1797     {
1798
1799     case AFS_INVALIDATE_DELETED:
1800         {
1801
1802             //
1803             // Mark this node as invalid
1804             //
1805
1806             (*ppObjectInfo)->Links = 0;
1807
1808             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_DELETED);
1809
1810             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1811                           AFS_TRACE_LEVEL_VERBOSE,
1812                           "AFSInvalidateObject Set DELETE flag on fid %08lX-%08lX-%08lX-%08lX\n",
1813                           (*ppObjectInfo)->FileId.Cell,
1814                           (*ppObjectInfo)->FileId.Volume,
1815                           (*ppObjectInfo)->FileId.Vnode,
1816                           (*ppObjectInfo)->FileId.Unique));
1817
1818             if( pParentObjectInfo != NULL)
1819             {
1820
1821                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1822                               AFS_TRACE_LEVEL_VERBOSE,
1823                               "AFSInvalidateObject Set VERIFY flag on parent fid %08lX-%08lX-%08lX-%08lX\n",
1824                               pParentObjectInfo->FileId.Cell,
1825                               pParentObjectInfo->FileId.Volume,
1826                               pParentObjectInfo->FileId.Vnode,
1827                               pParentObjectInfo->FileId.Unique));
1828
1829                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1830
1831                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1832
1833                 pParentObjectInfo->Expiration.QuadPart = 0;
1834
1835                 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1836                 {
1837                     ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1838                 }
1839                 else
1840                 {
1841                     ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1842                 }
1843
1844                 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1845                                                 NULL,
1846                                                 ulFilter,
1847                                                 FILE_ACTION_REMOVED);
1848             }
1849
1850             if( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1851                                                       Reason)))
1852             {
1853                 (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1854             }
1855
1856             break;
1857         }
1858
1859     case AFS_INVALIDATE_FLUSHED:
1860         {
1861
1862             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1863                 (*ppObjectInfo)->Fcb != NULL)
1864             {
1865
1866                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1867                               AFS_TRACE_LEVEL_VERBOSE,
1868                               "AFSInvalidateObject Flush/purge file fid %08lX-%08lX-%08lX-%08lX\n",
1869                               (*ppObjectInfo)->FileId.Cell,
1870                               (*ppObjectInfo)->FileId.Volume,
1871                               (*ppObjectInfo)->FileId.Vnode,
1872                               (*ppObjectInfo)->FileId.Unique));
1873
1874                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1875                               AFS_TRACE_LEVEL_VERBOSE,
1876                               "AFSInvalidateObject Flush/purge Acquiring Fcb lock %p EXCL %08lX\n",
1877                               &(*ppObjectInfo)->Fcb->NPFcb->Resource,
1878                               PsGetCurrentThread()));
1879
1880                 AFSAcquireExcl( &(*ppObjectInfo)->Fcb->NPFcb->Resource,
1881                                 TRUE);
1882
1883                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
1884                               AFS_TRACE_LEVEL_VERBOSE,
1885                               "AFSInvalidateObject Flush/purge Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
1886                               &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectResource,
1887                               PsGetCurrentThread()));
1888
1889                 AFSAcquireExcl( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectResource,
1890                                 TRUE);
1891
1892                 __try
1893                 {
1894
1895                     CcFlushCache( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1896                                   NULL,
1897                                   0,
1898                                   &stIoStatus);
1899
1900                     if( !NT_SUCCESS( stIoStatus.Status))
1901                     {
1902
1903                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1904                                       AFS_TRACE_LEVEL_ERROR,
1905                                       "AFSInvalidateObject CcFlushCache failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1906                                       (*ppObjectInfo)->FileId.Cell,
1907                                       (*ppObjectInfo)->FileId.Volume,
1908                                       (*ppObjectInfo)->FileId.Vnode,
1909                                       (*ppObjectInfo)->FileId.Unique,
1910                                       stIoStatus.Status,
1911                                       stIoStatus.Information));
1912
1913                         ntStatus = stIoStatus.Status;
1914                     }
1915
1916
1917                     if ( (*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
1918                     {
1919
1920                         if ( !CcPurgeCacheSection( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1921                                                    NULL,
1922                                                    0,
1923                                                    FALSE))
1924                         {
1925
1926                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1927                                           AFS_TRACE_LEVEL_WARNING,
1928                                           "AFSInvalidateObject CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
1929                                           (*ppObjectInfo)->FileId.Cell,
1930                                           (*ppObjectInfo)->FileId.Volume,
1931                                           (*ppObjectInfo)->FileId.Vnode,
1932                                           (*ppObjectInfo)->FileId.Unique));
1933
1934                             SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1935                         }
1936                     }
1937                 }
1938                 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
1939                 {
1940
1941                     ntStatus = GetExceptionCode();
1942
1943                     AFSDbgTrace(( 0,
1944                                   0,
1945                                   "EXCEPTION - AFSInvalidateObject Cc FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
1946                                   (*ppObjectInfo)->FileId.Cell,
1947                                   (*ppObjectInfo)->FileId.Volume,
1948                                   (*ppObjectInfo)->FileId.Vnode,
1949                                   (*ppObjectInfo)->FileId.Unique,
1950                                   ntStatus));
1951
1952                     SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1953                 }
1954
1955                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
1956                               AFS_TRACE_LEVEL_VERBOSE,
1957                               "AFSInvalidateObject Flush/purge Releasing Fcb SectionObject lock %p EXCL %08lX\n",
1958                               &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectResource,
1959                               PsGetCurrentThread()));
1960
1961                 AFSReleaseResource( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectResource);
1962
1963                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1964                               AFS_TRACE_LEVEL_VERBOSE,
1965                               "AFSInvalidateObject Flush/purge Releasing Fcb lock %p EXCL %08lX\n",
1966                               &(*ppObjectInfo)->Fcb->NPFcb->Resource,
1967                               PsGetCurrentThread()));
1968
1969                 AFSReleaseResource( &(*ppObjectInfo)->Fcb->NPFcb->Resource);
1970
1971                 if( !BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
1972                 {
1973
1974                     //
1975                     // Clear out the extents
1976                     // Get rid of them (note this involves waiting
1977                     // for any writes or reads to the cache to complete)
1978                     //
1979
1980                     AFSTearDownFcbExtents( (*ppObjectInfo)->Fcb,
1981                                            NULL);
1982                 }
1983             }
1984
1985             (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1986
1987
1988             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE)
1989             {
1990
1991                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1992                               AFS_TRACE_LEVEL_VERBOSE,
1993                               "AFSInvalidateObject Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
1994                               (*ppObjectInfo)->FileId.Cell,
1995                               (*ppObjectInfo)->FileId.Volume,
1996                               (*ppObjectInfo)->FileId.Vnode,
1997                               (*ppObjectInfo)->FileId.Unique));
1998
1999                 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
2000             }
2001
2002             // Fall through to the default processing
2003         }
2004
2005     default:
2006         {
2007
2008             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
2009             {
2010                 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
2011             }
2012             else
2013             {
2014                 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
2015             }
2016
2017             if( Reason == AFS_INVALIDATE_CREDS)
2018             {
2019                 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
2020             }
2021
2022             if( Reason == AFS_INVALIDATE_DATA_VERSION)
2023             {
2024                 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
2025             }
2026             else
2027             {
2028                 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
2029             }
2030
2031             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
2032             {
2033
2034                 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo),
2035                                                 NULL,
2036                                                 ulFilter,
2037                                                 FILE_ACTION_MODIFIED);
2038             }
2039             else if ( pParentObjectInfo != NULL)
2040             {
2041
2042                 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
2043                                                 NULL,
2044                                                 ulFilter,
2045                                                 FILE_ACTION_MODIFIED);
2046             }
2047
2048             //
2049             // Indicate this node requires re-evaluation for the remaining reasons
2050             //
2051
2052             (*ppObjectInfo)->Expiration.QuadPart = 0;
2053
2054             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2055                           AFS_TRACE_LEVEL_VERBOSE,
2056                           "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
2057                           (*ppObjectInfo)->FileId.Cell,
2058                           (*ppObjectInfo)->FileId.Volume,
2059                           (*ppObjectInfo)->FileId.Vnode,
2060                           (*ppObjectInfo)->FileId.Unique));
2061
2062             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
2063
2064             if( Reason == AFS_INVALIDATE_DATA_VERSION ||
2065                 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
2066                 ( Reason == AFS_INVALIDATE_CALLBACK ||
2067                   Reason == AFS_INVALIDATE_EXPIRED))
2068             {
2069                 if ( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
2070                                                            AFS_INVALIDATE_DATA_VERSION)))
2071                 {
2072
2073                     (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
2074                 }
2075             }
2076
2077             break;
2078         }
2079     }
2080
2081   try_exit:
2082
2083     if ( pParentObjectInfo != NULL)
2084     {
2085
2086         AFSReleaseObjectInfo( &pParentObjectInfo);
2087     }
2088
2089     return ntStatus;
2090 }
2091
2092 NTSTATUS
2093 AFSInvalidateCache( IN AFSInvalidateCacheCB *InvalidateCB)
2094 {
2095
2096     NTSTATUS ntStatus = STATUS_SUCCESS;
2097     AFSVolumeCB *pVolumeCB = NULL;
2098     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2099     ULONGLONG   ullIndex = 0;
2100     AFSObjectInfoCB *pObjectInfo = NULL;
2101     LONG lCount;
2102
2103     __Enter
2104     {
2105
2106         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2107                       AFS_TRACE_LEVEL_VERBOSE,
2108                       "AFSInvalidateCache Invalidation FID %08lX-%08lX-%08lX-%08lX Type %d WholeVolume %d Reason %d\n",
2109                       InvalidateCB->FileID.Cell,
2110                       InvalidateCB->FileID.Volume,
2111                       InvalidateCB->FileID.Vnode,
2112                       InvalidateCB->FileID.Unique,
2113                       InvalidateCB->FileType,
2114                       InvalidateCB->WholeVolume,
2115                       InvalidateCB->Reason));
2116
2117         //
2118         // Need to locate the Fcb for the directory to purge
2119         //
2120
2121         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2122                       AFS_TRACE_LEVEL_VERBOSE,
2123                       "AFSInvalidateCache Acquiring RDR VolumeTreeLock lock %p SHARED %08lX\n",
2124                       &pDevExt->Specific.RDR.VolumeTreeLock,
2125                       PsGetCurrentThread()));
2126
2127         //
2128         // Starve any exclusive waiters on this paticular call
2129         //
2130
2131         AFSAcquireSharedStarveExclusive( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2132
2133         //
2134         // Locate the volume node
2135         //
2136
2137         ullIndex = AFSCreateHighIndex( &InvalidateCB->FileID);
2138
2139         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2140                                        ullIndex,
2141                                        (AFSBTreeEntry **)&pVolumeCB);
2142
2143         if( pVolumeCB != NULL)
2144         {
2145
2146             lCount = AFSVolumeIncrement( pVolumeCB,
2147                                          AFS_VOLUME_REFERENCE_INVALIDATE);
2148
2149             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2150                           AFS_TRACE_LEVEL_VERBOSE,
2151                           "AFSInvalidateCache Increment count on volume %p Cnt %d\n",
2152                           pVolumeCB,
2153                           lCount));
2154         }
2155
2156         AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2157
2158         if( !NT_SUCCESS( ntStatus) ||
2159             pVolumeCB == NULL)
2160         {
2161
2162             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2163                           AFS_TRACE_LEVEL_WARNING,
2164                           "AFSInvalidateCache Invalidation FAILURE Unable to locate volume node FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2165                           InvalidateCB->FileID.Cell,
2166                           InvalidateCB->FileID.Volume,
2167                           InvalidateCB->FileID.Vnode,
2168                           InvalidateCB->FileID.Unique,
2169                           ntStatus));
2170
2171             try_return( ntStatus = STATUS_SUCCESS);
2172         }
2173
2174         //
2175         // If this is a whole volume invalidation then go do it now
2176         //
2177
2178         if( InvalidateCB->WholeVolume)
2179         {
2180
2181             ntStatus = AFSInvalidateVolume( pVolumeCB,
2182                                             InvalidateCB->Reason);
2183
2184             try_return( ntStatus);
2185         }
2186
2187         AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
2188                           TRUE);
2189
2190         if ( AFSIsVolumeFID( &InvalidateCB->FileID))
2191         {
2192
2193             pObjectInfo = &pVolumeCB->ObjectInformation;
2194         }
2195         else
2196         {
2197
2198             ullIndex = AFSCreateLowIndex( &InvalidateCB->FileID);
2199
2200             ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2201                                            ullIndex,
2202                                            (AFSBTreeEntry **)&pObjectInfo);
2203         }
2204
2205         if( pObjectInfo != NULL)
2206         {
2207
2208             //
2209             // Reference the node so it won't be torn down
2210             //
2211
2212             lCount = AFSObjectInfoIncrement( pObjectInfo,
2213                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2214
2215             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2216                           AFS_TRACE_LEVEL_VERBOSE,
2217                           "AFSInvalidateCache Increment count on object %p Cnt %d\n",
2218                           pObjectInfo,
2219                           lCount));
2220         }
2221
2222         AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2223
2224         if( !NT_SUCCESS( ntStatus) ||
2225             pObjectInfo == NULL)
2226         {
2227
2228             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2229                           AFS_TRACE_LEVEL_VERBOSE,
2230                           "AFSInvalidateCache Invalidation FAILURE Unable to locate object FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2231                           InvalidateCB->FileID.Cell,
2232                           InvalidateCB->FileID.Volume,
2233                           InvalidateCB->FileID.Vnode,
2234                           InvalidateCB->FileID.Unique,
2235                           ntStatus));
2236
2237             try_return( ntStatus = STATUS_SUCCESS);
2238         }
2239
2240         AFSInvalidateObject( &pObjectInfo,
2241                              InvalidateCB->Reason);
2242
2243 try_exit:
2244
2245         if( pObjectInfo != NULL)
2246         {
2247
2248             lCount = AFSObjectInfoDecrement( pObjectInfo,
2249                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2250
2251             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2252                           AFS_TRACE_LEVEL_VERBOSE,
2253                           "AFSInvalidateCache Decrement count on object %p Cnt %d\n",
2254                           pObjectInfo,
2255                           lCount));
2256         }
2257
2258         if ( pVolumeCB != NULL)
2259         {
2260
2261             lCount = AFSVolumeDecrement( pVolumeCB,
2262                                          AFS_VOLUME_REFERENCE_INVALIDATE);
2263
2264             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2265                           AFS_TRACE_LEVEL_VERBOSE,
2266                           "AFSInvalidateCache Decrement count on volume %p Cnt %d\n",
2267                           pVolumeCB,
2268                           lCount));
2269         }
2270     }
2271
2272     return ntStatus;
2273 }
2274
2275 BOOLEAN
2276 AFSIsChildOfParent( IN AFSFcb *Dcb,
2277                     IN AFSFcb *Fcb)
2278 {
2279
2280     BOOLEAN bIsChild = FALSE;
2281     AFSFcb *pCurrentFcb = Fcb;
2282     AFSObjectInfoCB * pParentObjectInfo = NULL;
2283
2284     while( pCurrentFcb != NULL)
2285     {
2286
2287         if( BooleanFlagOn( pCurrentFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
2288             AFSIsEqualFID( &pCurrentFcb->ObjectInformation->ParentFileId, &Dcb->ObjectInformation->FileId))
2289         {
2290
2291             bIsChild = TRUE;
2292
2293             break;
2294         }
2295
2296         pParentObjectInfo = AFSFindObjectInfo( pCurrentFcb->ObjectInformation->VolumeCB,
2297                                                &pCurrentFcb->ObjectInformation->ParentFileId,
2298                                                FALSE);
2299
2300         if ( pParentObjectInfo != NULL)
2301         {
2302
2303             pCurrentFcb = pParentObjectInfo->Fcb;
2304
2305             AFSReleaseObjectInfo( &pParentObjectInfo);
2306         }
2307         else
2308         {
2309
2310             pCurrentFcb = NULL;
2311         }
2312     }
2313
2314     return bIsChild;
2315 }
2316
2317 inline
2318 ULONGLONG
2319 AFSCreateHighIndex( IN AFSFileID *FileID)
2320 {
2321
2322     ULONGLONG ullIndex = 0;
2323
2324     ullIndex = (((ULONGLONG)FileID->Cell << 32) | FileID->Volume);
2325
2326     return ullIndex;
2327 }
2328
2329 inline
2330 ULONGLONG
2331 AFSCreateLowIndex( IN AFSFileID *FileID)
2332 {
2333
2334     ULONGLONG ullIndex = 0;
2335
2336     ullIndex = (((ULONGLONG)FileID->Vnode << 32) | FileID->Unique);
2337
2338     return ullIndex;
2339 }
2340
2341 BOOLEAN
2342 AFSCheckAccess( IN ACCESS_MASK DesiredAccess,
2343                 IN ACCESS_MASK GrantedAccess,
2344                 IN BOOLEAN DirectoryEntry)
2345 {
2346
2347     BOOLEAN bAccessGranted = TRUE;
2348
2349     //
2350     // Check if we are asking for read/write and granted only read only
2351     // NOTE: There will be more checks here
2352     //
2353
2354     if( !AFSCheckForReadOnlyAccess( DesiredAccess,
2355                                     DirectoryEntry) &&
2356         AFSCheckForReadOnlyAccess( GrantedAccess,
2357                                    DirectoryEntry))
2358     {
2359
2360         bAccessGranted = FALSE;
2361     }
2362
2363     return bAccessGranted;
2364 }
2365
2366 NTSTATUS
2367 AFSGetDriverStatus( IN AFSDriverStatusRespCB *DriverStatus)
2368 {
2369
2370     NTSTATUS         ntStatus = STATUS_SUCCESS;
2371     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2372
2373     //
2374     // Start with read
2375     //
2376
2377     DriverStatus->Status = AFS_DRIVER_STATUS_READY;
2378
2379     if( AFSGlobalRoot == NULL)
2380     {
2381
2382         //
2383         // We are not ready
2384         //
2385
2386         DriverStatus->Status = AFS_DRIVER_STATUS_NOT_READY;
2387     }
2388
2389     if( pControlDevExt->Specific.Control.CommServiceCB.IrpPoolControlFlag != POOL_ACTIVE)
2390     {
2391
2392         //
2393         // No service yet
2394         //
2395
2396         DriverStatus->Status = AFS_DRIVER_STATUS_NO_SERVICE;
2397     }
2398
2399     return ntStatus;
2400 }
2401
2402 NTSTATUS
2403 AFSSubstituteSysName( IN UNICODE_STRING *ComponentName,
2404                       IN UNICODE_STRING *SubstituteName,
2405                       IN ULONG StringIndex)
2406 {
2407
2408     NTSTATUS ntStatus = STATUS_SUCCESS;
2409     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2410     AFSSysNameCB    *pSysName = NULL;
2411     ERESOURCE       *pSysNameLock = NULL;
2412     ULONG            ulIndex = 1;
2413     USHORT           usIndex = 0;
2414     UNICODE_STRING   uniSysName;
2415
2416     __Enter
2417     {
2418
2419 #if defined(_WIN64)
2420
2421         if( IoIs32bitProcess( NULL))
2422         {
2423
2424             pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2425
2426             pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2427         }
2428         else
2429         {
2430
2431             pSysNameLock = &pControlDevExt->Specific.Control.SysName64ListLock;
2432
2433             pSysName = pControlDevExt->Specific.Control.SysName64ListHead;
2434         }
2435 #else
2436
2437         pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2438
2439         pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2440
2441 #endif
2442
2443         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2444                       AFS_TRACE_LEVEL_VERBOSE,
2445                       "AFSSubstituteSysName Acquiring SysName lock %p SHARED %08lX\n",
2446                       pSysNameLock,
2447                       PsGetCurrentThread()));
2448
2449         AFSAcquireShared( pSysNameLock,
2450                           TRUE);
2451
2452         //
2453         // Find where we are in the list
2454         //
2455
2456         while( pSysName != NULL &&
2457             ulIndex < StringIndex)
2458         {
2459
2460             pSysName = pSysName->fLink;
2461
2462             ulIndex++;
2463         }
2464
2465         if( pSysName == NULL)
2466         {
2467
2468             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2469                           AFS_TRACE_LEVEL_VERBOSE_2,
2470                           "AFSSubstituteSysName No sysname %wZ Status %08lX\n",
2471                           &ComponentName,
2472                           STATUS_OBJECT_NAME_NOT_FOUND));
2473
2474             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
2475         }
2476
2477         RtlInitUnicodeString( &uniSysName,
2478                               L"@SYS");
2479         //
2480         // If it is a full component of @SYS then just substitue the
2481         // name in
2482         //
2483
2484         if( RtlCompareUnicodeString( &uniSysName,
2485                                      ComponentName,
2486                                      TRUE) == 0)
2487         {
2488
2489             SubstituteName->Length = pSysName->SysName.Length;
2490             SubstituteName->MaximumLength = SubstituteName->Length;
2491
2492             SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2493                                                                         SubstituteName->Length,
2494                                                                         AFS_SUBST_BUFFER_TAG);
2495
2496             if( SubstituteName->Buffer == NULL)
2497             {
2498
2499                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2500             }
2501
2502             RtlCopyMemory( SubstituteName->Buffer,
2503                            pSysName->SysName.Buffer,
2504                            pSysName->SysName.Length);
2505         }
2506         else
2507         {
2508
2509             usIndex = 0;
2510
2511             while( ComponentName->Buffer[ usIndex] != L'@')
2512             {
2513
2514                 usIndex++;
2515             }
2516
2517             SubstituteName->Length = (usIndex * sizeof( WCHAR)) + pSysName->SysName.Length;
2518             SubstituteName->MaximumLength = SubstituteName->Length;
2519
2520             SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2521                                                                         SubstituteName->Length,
2522                                                                         AFS_SUBST_BUFFER_TAG);
2523
2524             if( SubstituteName->Buffer == NULL)
2525             {
2526
2527                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2528             }
2529
2530             RtlCopyMemory( SubstituteName->Buffer,
2531                            ComponentName->Buffer,
2532                            usIndex * sizeof( WCHAR));
2533
2534             RtlCopyMemory( &SubstituteName->Buffer[ usIndex],
2535                            pSysName->SysName.Buffer,
2536                            pSysName->SysName.Length);
2537         }
2538
2539 try_exit:
2540
2541         AFSReleaseResource( pSysNameLock);
2542     }
2543
2544     return ntStatus;
2545 }
2546
2547 NTSTATUS
2548 AFSSubstituteNameInPath( IN OUT UNICODE_STRING *FullPathName,
2549                          IN OUT UNICODE_STRING *ComponentName,
2550                          IN UNICODE_STRING *SubstituteName,
2551                          IN OUT UNICODE_STRING *RemainingPath,
2552                          IN BOOLEAN FreePathName)
2553 {
2554
2555     NTSTATUS ntStatus = STATUS_SUCCESS;
2556     UNICODE_STRING uniPathName;
2557     USHORT usPrefixNameLen = 0;
2558     SHORT  sNameLenDelta = 0;
2559
2560     __Enter
2561     {
2562
2563         //
2564         // If the passed in name can handle the additional length
2565         // then just moves things around
2566         //
2567
2568         sNameLenDelta = SubstituteName->Length - ComponentName->Length;
2569
2570         usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2571
2572         if( FullPathName->MaximumLength > FullPathName->Length + sNameLenDelta)
2573         {
2574
2575             if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2576             {
2577
2578                 RtlMoveMemory( &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + SubstituteName->Length)/sizeof( WCHAR))],
2579                                &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + ComponentName->Length)/sizeof( WCHAR))],
2580                                FullPathName->Length - usPrefixNameLen*sizeof( WCHAR) - ComponentName->Length);
2581             }
2582
2583             RtlCopyMemory( &FullPathName->Buffer[ usPrefixNameLen],
2584                            SubstituteName->Buffer,
2585                            SubstituteName->Length);
2586
2587             FullPathName->Length += sNameLenDelta;
2588
2589             ComponentName->Length += sNameLenDelta;
2590
2591             ComponentName->MaximumLength = ComponentName->Length;
2592
2593             if ( RemainingPath->Buffer)
2594             {
2595
2596                 RemainingPath->Buffer += sNameLenDelta/sizeof( WCHAR);
2597             }
2598
2599             try_return( ntStatus);
2600         }
2601
2602         //
2603         // Need to re-allocate the buffer
2604         //
2605
2606         uniPathName.Length = FullPathName->Length -
2607                                          ComponentName->Length +
2608                                          SubstituteName->Length;
2609
2610         uniPathName.MaximumLength = FullPathName->MaximumLength + PAGE_SIZE;
2611
2612         uniPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2613                                                                 uniPathName.MaximumLength,
2614                                                                 AFS_NAME_BUFFER_FOUR_TAG);
2615
2616         if( uniPathName.Buffer == NULL)
2617         {
2618
2619             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2620         }
2621
2622         usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2623
2624         usPrefixNameLen *= sizeof( WCHAR);
2625
2626         RtlZeroMemory( uniPathName.Buffer,
2627                        uniPathName.MaximumLength);
2628
2629         RtlCopyMemory( uniPathName.Buffer,
2630                        FullPathName->Buffer,
2631                        usPrefixNameLen);
2632
2633         RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen/sizeof( WCHAR))],
2634                        SubstituteName->Buffer,
2635                        SubstituteName->Length);
2636
2637         if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2638         {
2639
2640             RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen + SubstituteName->Length)/sizeof( WCHAR)],
2641                            &FullPathName->Buffer[ (usPrefixNameLen + ComponentName->Length)/sizeof( WCHAR)],
2642                            FullPathName->Length - usPrefixNameLen - ComponentName->Length);
2643         }
2644
2645         ComponentName->Buffer = uniPathName.Buffer + (ComponentName->Buffer - FullPathName->Buffer);
2646
2647         ComponentName->Length += sNameLenDelta;
2648
2649         ComponentName->MaximumLength = ComponentName->Length;
2650
2651         if ( RemainingPath->Buffer)
2652         {
2653
2654             RemainingPath->Buffer = uniPathName.Buffer
2655                 + (RemainingPath->Buffer - FullPathName->Buffer)
2656                 + sNameLenDelta/sizeof( WCHAR);
2657         }
2658
2659         if( FreePathName)
2660         {
2661             AFSExFreePoolWithTag( FullPathName->Buffer, 0);
2662         }
2663
2664         *FullPathName = uniPathName;
2665
2666 try_exit:
2667
2668         NOTHING;
2669     }
2670
2671     return ntStatus;
2672 }
2673
2674 NTSTATUS
2675 AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
2676                      IN ULONG Reason)
2677 {
2678
2679     NTSTATUS ntStatus = STATUS_SUCCESS;
2680     AFSObjectInfoCB *pCurrentObject = NULL;
2681     AFSObjectInfoCB *pNextObject = NULL;
2682     LONG lCount;
2683
2684     __Enter
2685     {
2686
2687         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2688                       AFS_TRACE_LEVEL_VERBOSE,
2689                       "AFSInvalidateVolume Invalidate volume fid %08lX-%08lX-%08lX-%08lX Reason %08lX\n",
2690                       VolumeCB->ObjectInformation.FileId.Cell,
2691                       VolumeCB->ObjectInformation.FileId.Volume,
2692                       VolumeCB->ObjectInformation.FileId.Vnode,
2693                       VolumeCB->ObjectInformation.FileId.Unique,
2694                       Reason));
2695
2696         //
2697         // Depending on the reason for invalidation then perform work on the node
2698         //
2699
2700         switch( Reason)
2701         {
2702
2703             case AFS_INVALIDATE_DELETED:
2704             {
2705
2706                 //
2707                 // Mark this volume as invalid
2708                 //
2709
2710                 SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
2711
2712                 SetFlag( VolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE);
2713
2714                 break;
2715             }
2716         }
2717
2718         AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2719                           TRUE);
2720
2721         //
2722         // Invalidate the volume root directory
2723         //
2724
2725         pCurrentObject = &VolumeCB->ObjectInformation;
2726
2727         if ( pCurrentObject )
2728         {
2729
2730             lCount = AFSObjectInfoIncrement( pCurrentObject,
2731                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2732
2733             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2734                           AFS_TRACE_LEVEL_VERBOSE,
2735                           "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2736                           pCurrentObject,
2737                           lCount));
2738
2739             AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2740
2741             AFSInvalidateObject( &pCurrentObject,
2742                                  Reason);
2743
2744             AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2745                               TRUE);
2746
2747             if ( pCurrentObject)
2748             {
2749
2750                 lCount = AFSObjectInfoDecrement( pCurrentObject,
2751                                                  AFS_OBJECT_REFERENCE_INVALIDATION);
2752
2753                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2754                               AFS_TRACE_LEVEL_VERBOSE,
2755                               "AFSInvalidateVolumeObjects Decrement count on object %p Cnt %d\n",
2756                               pCurrentObject,
2757                               lCount));
2758             }
2759         }
2760
2761         //
2762         // Apply invalidation to all other volume objects
2763         //
2764
2765         pCurrentObject = VolumeCB->ObjectInfoListHead;
2766
2767         if ( pCurrentObject)
2768         {
2769
2770             //
2771             // Reference the node so it won't be torn down
2772             //
2773
2774             lCount = AFSObjectInfoIncrement( pCurrentObject,
2775                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2776
2777             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2778                           AFS_TRACE_LEVEL_VERBOSE,
2779                           "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2780                           pCurrentObject,
2781                           lCount));
2782         }
2783
2784         while( pCurrentObject != NULL)
2785         {
2786
2787             pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
2788
2789             if ( pNextObject)
2790             {
2791
2792                 //
2793                 // Reference the node so it won't be torn down
2794                 //
2795
2796                 lCount = AFSObjectInfoIncrement( pNextObject,
2797                                                  AFS_OBJECT_REFERENCE_INVALIDATION);
2798
2799                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2800                               AFS_TRACE_LEVEL_VERBOSE,
2801                               "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2802                               pNextObject,
2803                               lCount));
2804             }
2805
2806             AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2807
2808             AFSInvalidateObject( &pCurrentObject,
2809                                  Reason);
2810
2811             AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2812                               TRUE);
2813
2814             if ( pCurrentObject )
2815             {
2816
2817                 lCount = AFSObjectInfoDecrement( pCurrentObject,
2818                                                  AFS_OBJECT_REFERENCE_INVALIDATION);
2819
2820                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2821                               AFS_TRACE_LEVEL_VERBOSE,
2822                               "AFSInvalidateVolumeObjects Decrement count on object %p Cnt %d\n",
2823                               pCurrentObject,
2824                               lCount));
2825             }
2826
2827             pCurrentObject = pNextObject;
2828         }
2829
2830         AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
2831     }
2832
2833     return ntStatus;
2834 }
2835
2836 VOID
2837 AFSInvalidateAllVolumes( VOID)
2838 {
2839     AFSVolumeCB *pVolumeCB = NULL;
2840     AFSVolumeCB *pNextVolumeCB = NULL;
2841     AFSDeviceExt *pRDRDeviceExt = NULL;
2842     LONG lCount;
2843
2844     pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2845
2846     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2847                   AFS_TRACE_LEVEL_VERBOSE,
2848                   "AFSInvalidateAllVolumes Acquiring RDR VolumeListLock lock %p SHARED %08lX\n",
2849                   &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2850                   PsGetCurrentThread()));
2851
2852     AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2853                       TRUE);
2854
2855     pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
2856
2857     if ( pVolumeCB)
2858     {
2859
2860         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2861                       AFS_TRACE_LEVEL_VERBOSE,
2862                       "AFSInvalidateAllVolumes Acquiring VolumeRoot ObjectInfoTree lock %p SHARED %08lX\n",
2863                       pVolumeCB->ObjectInfoTree.TreeLock,
2864                       PsGetCurrentThread()));
2865
2866         lCount = AFSVolumeIncrement( pVolumeCB,
2867                                      AFS_VOLUME_REFERENCE_INVALIDATE);
2868
2869         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2870                       AFS_TRACE_LEVEL_VERBOSE,
2871                       "AFSInvalidateAllVolumes Increment count on volume %p Cnt %d\n",
2872                       pVolumeCB,
2873                       lCount));
2874     }
2875
2876     while( pVolumeCB != NULL)
2877     {
2878
2879         pNextVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
2880
2881         if ( pNextVolumeCB)
2882         {
2883
2884             lCount = AFSVolumeIncrement( pNextVolumeCB,
2885                                          AFS_VOLUME_REFERENCE_INVALIDATE);
2886
2887             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2888                           AFS_TRACE_LEVEL_VERBOSE,
2889                           "AFSInvalidateAllVolumes Increment count on volume %p Cnt %d\n",
2890                           pVolumeCB,
2891                           lCount));
2892         }
2893
2894         AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2895
2896         // do I need to hold the volume lock here?
2897
2898         AFSInvalidateVolume( pVolumeCB, AFS_INVALIDATE_EXPIRED);
2899
2900         AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
2901                           TRUE);
2902
2903         lCount = AFSVolumeDecrement( pVolumeCB,
2904                                      AFS_VOLUME_REFERENCE_INVALIDATE);
2905
2906         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2907                       AFS_TRACE_LEVEL_VERBOSE,
2908                       "AFSInvalidateAllVolumes Decrement count on volume %p Cnt %d\n",
2909                       pVolumeCB,
2910                       lCount));
2911
2912         pVolumeCB = pNextVolumeCB;
2913     }
2914
2915     AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
2916 }
2917
2918 NTSTATUS
2919 AFSVerifyEntry( IN GUID *AuthGroup,
2920                 IN AFSDirectoryCB *DirEntry,
2921                 IN BOOLEAN bFollowMountPoint)
2922 {
2923
2924     NTSTATUS ntStatus = STATUS_SUCCESS;
2925     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2926     AFSDirEnumEntry *pDirEnumEntry = NULL;
2927     AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
2928     IO_STATUS_BLOCK stIoStatus;
2929
2930     __Enter
2931     {
2932
2933         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2934                       AFS_TRACE_LEVEL_VERBOSE_2,
2935                       "AFSVerifyEntry Verifying entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2936                       &DirEntry->NameInformation.FileName,
2937                       pObjectInfo->FileId.Cell,
2938                       pObjectInfo->FileId.Volume,
2939                       pObjectInfo->FileId.Vnode,
2940                       pObjectInfo->FileId.Unique));
2941
2942         ntStatus = AFSEvaluateTargetByID( pObjectInfo,
2943                                           AuthGroup,
2944                                           bFollowMountPoint ? FALSE : TRUE,
2945                                           &pDirEnumEntry);
2946
2947         if( !NT_SUCCESS( ntStatus))
2948         {
2949
2950             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2951                           AFS_TRACE_LEVEL_ERROR,
2952                           "AFSVerifyEntry Evaluate Target failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
2953                           &DirEntry->NameInformation.FileName,
2954                           pObjectInfo->FileId.Cell,
2955                           pObjectInfo->FileId.Volume,
2956                           pObjectInfo->FileId.Vnode,
2957                           pObjectInfo->FileId.Unique,
2958                           ntStatus));
2959
2960             try_return( ntStatus);
2961         }
2962
2963         //
2964         // Check the data version of the file
2965         //
2966
2967         if( pObjectInfo->DataVersion.QuadPart == pDirEnumEntry->DataVersion.QuadPart &&
2968             !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
2969         {
2970
2971             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2972                           AFS_TRACE_LEVEL_VERBOSE,
2973                           "AFSVerifyEntry No DV change %I64X for Fcb %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2974                           pObjectInfo->DataVersion.QuadPart,
2975                           &DirEntry->NameInformation.FileName,
2976                           pObjectInfo->FileId.Cell,
2977                           pObjectInfo->FileId.Volume,
2978                           pObjectInfo->FileId.Vnode,
2979                           pObjectInfo->FileId.Unique));
2980
2981             //
2982             // We are ok, just get out
2983             //
2984
2985             ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2986
2987             try_return( ntStatus = STATUS_SUCCESS);
2988         }
2989
2990         //
2991         // New data version so we will need to process the node based on the type
2992         //
2993
2994         switch( pDirEnumEntry->FileType)
2995         {
2996
2997             case AFS_FILE_TYPE_MOUNTPOINT:
2998             {
2999
3000                 //
3001                 // For a mount point we need to ensure the target is the same
3002                 //
3003
3004                 if( !AFSIsEqualFID( &pObjectInfo->TargetFileId,
3005                                     &pDirEnumEntry->TargetFileId))
3006                 {
3007
3008                 }
3009
3010                 //
3011                 // Update the metadata for the entry
3012                 //
3013
3014                 ntStatus = AFSUpdateMetaData( DirEntry,
3015                                               pDirEnumEntry);
3016
3017                 if( NT_SUCCESS( ntStatus))
3018                 {
3019
3020                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3021                 }
3022
3023                 break;
3024             }
3025
3026             case AFS_FILE_TYPE_SYMLINK:
3027             {
3028
3029                 //
3030                 // Update the metadata for the entry
3031                 //
3032
3033                 ntStatus = AFSUpdateMetaData( DirEntry,
3034                                               pDirEnumEntry);
3035
3036                 if( NT_SUCCESS( ntStatus))
3037                 {
3038
3039                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3040                 }
3041
3042                 break;
3043             }
3044
3045             case AFS_FILE_TYPE_FILE:
3046             {
3047                 FILE_OBJECT * pCCFileObject = NULL;
3048
3049                 if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
3050                 {
3051
3052                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3053                                   AFS_TRACE_LEVEL_VERBOSE,
3054                                   "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3055                                   &DirEntry->NameInformation.FileName,
3056                                   pObjectInfo->FileId.Cell,
3057                                   pObjectInfo->FileId.Volume,
3058                                   pObjectInfo->FileId.Vnode,
3059                                   pObjectInfo->FileId.Unique));
3060
3061                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
3062                 }
3063
3064                 if( pObjectInfo->Fcb != NULL)
3065                 {
3066
3067                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3068                                   AFS_TRACE_LEVEL_VERBOSE,
3069                                   "AFSVerifyEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3070                                   &DirEntry->NameInformation.FileName,
3071                                   pObjectInfo->FileId.Cell,
3072                                   pObjectInfo->FileId.Volume,
3073                                   pObjectInfo->FileId.Vnode,
3074                                   pObjectInfo->FileId.Unique));
3075
3076                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3077                                   AFS_TRACE_LEVEL_VERBOSE,
3078                                   "AFSVerifyEntry Acquiring Fcb lock %p EXCL %08lX\n",
3079                                   &pObjectInfo->Fcb->NPFcb->Resource,
3080                                   PsGetCurrentThread()));
3081
3082                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
3083                                     TRUE);
3084
3085                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
3086                                   AFS_TRACE_LEVEL_VERBOSE,
3087                                   "AFSVerifyEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
3088                                   &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3089                                   PsGetCurrentThread()));
3090
3091                     AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3092                                     TRUE);
3093
3094                     __try
3095                     {
3096
3097                         CcFlushCache( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
3098                                       NULL,
3099                                       0,
3100                                       &stIoStatus);
3101
3102                         if( !NT_SUCCESS( stIoStatus.Status))
3103                         {
3104
3105                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
3106                                           AFS_TRACE_LEVEL_ERROR,
3107                                           "AFSVerifyEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
3108                                           &DirEntry->NameInformation.FileName,
3109                                           pObjectInfo->FileId.Cell,
3110                                           pObjectInfo->FileId.Volume,
3111                                           pObjectInfo->FileId.Vnode,
3112                                           pObjectInfo->FileId.Unique,
3113                                           stIoStatus.Status,
3114                                           stIoStatus.Information));
3115
3116                             ntStatus = stIoStatus.Status;
3117                         }
3118
3119                         if ( pObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
3120                         {
3121
3122                             if ( !CcPurgeCacheSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
3123                                                        NULL,
3124                                                        0,
3125                                                        FALSE))
3126                             {
3127
3128                                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
3129                                               AFS_TRACE_LEVEL_WARNING,
3130                                               "AFSVerifyEntry CcPurgeCacheSection failure %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3131                                               &DirEntry->NameInformation.FileName,
3132                                               pObjectInfo->FileId.Cell,
3133                                               pObjectInfo->FileId.Volume,
3134                                               pObjectInfo->FileId.Vnode,
3135                                               pObjectInfo->FileId.Unique));
3136
3137                                 SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
3138                             }
3139                         }
3140                     }
3141                     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
3142                     {
3143                         ntStatus = GetExceptionCode();
3144
3145                         AFSDbgTrace(( 0,
3146                                       0,
3147                                       "EXCEPTION - AFSVerifyEntry CcFlushCache or CcPurgeCacheSection %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
3148                                       &DirEntry->NameInformation.FileName,
3149                                       pObjectInfo->FileId.Cell,
3150                                       pObjectInfo->FileId.Volume,
3151                                       pObjectInfo->FileId.Vnode,
3152                                       pObjectInfo->FileId.Unique,
3153                                       ntStatus));
3154
3155                         SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
3156                     }
3157
3158                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
3159                                   AFS_TRACE_LEVEL_VERBOSE,
3160                                   "AFSVerifyEntry Releasing Fcb SectionObject lock %p EXCL %08lX\n",
3161                                   &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3162                                   PsGetCurrentThread()));
3163
3164                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
3165
3166                     if( !BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
3167                     {
3168
3169                         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3170                                       AFS_TRACE_LEVEL_VERBOSE,
3171                                       "AFSVerifyEntry Releasing Fcb lock %p EXCL %08lX\n",
3172                                       &pObjectInfo->Fcb->NPFcb->Resource,
3173                                       PsGetCurrentThread()));
3174
3175                         AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
3176
3177                         AFSFlushExtents( pObjectInfo->Fcb,
3178                                          AuthGroup);
3179
3180                         //
3181                         // Acquire the Fcb to purge the cache
3182                         //
3183
3184                         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3185                                       AFS_TRACE_LEVEL_VERBOSE,
3186                                       "AFSVerifyEntry Acquiring Fcb lock %p EXCL %08lX\n",
3187                                       &pObjectInfo->Fcb->NPFcb->Resource,
3188                                       PsGetCurrentThread()));
3189
3190                         AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->Resource,
3191                                         TRUE);
3192                     }
3193
3194                     //
3195                     // Update the metadata for the entry
3196                     //
3197
3198                     ntStatus = AFSUpdateMetaData( DirEntry,
3199                                                   pDirEnumEntry);
3200
3201                     if( !NT_SUCCESS( ntStatus))
3202                     {
3203
3204                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3205                                       AFS_TRACE_LEVEL_ERROR,
3206                                       "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
3207                                       &DirEntry->NameInformation.FileName,
3208                                       pObjectInfo->FileId.Cell,
3209                                       pObjectInfo->FileId.Volume,
3210                                       pObjectInfo->FileId.Vnode,
3211                                       pObjectInfo->FileId.Unique,
3212                                       ntStatus));
3213                     }
3214                     else
3215                     {
3216
3217                         //
3218                         // Update file sizes
3219                         //
3220
3221                         pObjectInfo->Fcb->Header.AllocationSize.QuadPart  = pObjectInfo->AllocationSize.QuadPart;
3222                         pObjectInfo->Fcb->Header.FileSize.QuadPart        = pObjectInfo->EndOfFile.QuadPart;
3223                         pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
3224
3225                         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
3226                                       AFS_TRACE_LEVEL_VERBOSE,
3227                                       "AFSVerifyEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
3228                                       &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3229                                       PsGetCurrentThread()));
3230
3231                         AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3232                                         TRUE);
3233
3234                         __try
3235                         {
3236
3237                             pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
3238
3239                             if ( pCCFileObject != NULL)
3240                             {
3241                                 CcSetFileSizes( pCCFileObject,
3242                                                 (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
3243                             }
3244                         }
3245                         __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
3246                         {
3247
3248                             ntStatus = GetExceptionCode();
3249
3250                             AFSDbgTrace(( 0,
3251                                           0,
3252                                           "EXCEPTION - AFSVerifyEntry CcSetFileSized failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
3253                                           pObjectInfo->FileId.Cell,
3254                                           pObjectInfo->FileId.Volume,
3255                                           pObjectInfo->FileId.Vnode,
3256                                           pObjectInfo->FileId.Unique,
3257                                           ntStatus));
3258                         }
3259
3260                         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
3261                                       AFS_TRACE_LEVEL_VERBOSE,
3262                                       "AFSVerifyEntry Releasing Fcb SectionObject lock %p EXCL %08lX\n",
3263                                       &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3264                                       PsGetCurrentThread()));
3265
3266                         AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
3267                     }
3268
3269                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3270                                   AFS_TRACE_LEVEL_VERBOSE,
3271                                   "AFSVerifyEntry Releasing Fcb lock %p EXCL %08lX\n",
3272                                   &pObjectInfo->Fcb->NPFcb->Resource,
3273                                   PsGetCurrentThread()));
3274
3275                     AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->Resource);
3276                 }
3277                 else
3278                 {
3279
3280                     //
3281                     // Update the metadata for the entry
3282                     //
3283
3284                     ntStatus = AFSUpdateMetaData( DirEntry,
3285                                                   pDirEnumEntry);
3286
3287                     if( !NT_SUCCESS( ntStatus))
3288                     {
3289
3290                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3291                                       AFS_TRACE_LEVEL_ERROR,
3292                                       "AFSVerifyEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX ntStatus %08lX\n",
3293                                       &DirEntry->NameInformation.FileName,
3294                                       pObjectInfo->FileId.Cell,
3295                                       pObjectInfo->FileId.Volume,
3296                                       pObjectInfo->FileId.Vnode,
3297                                       pObjectInfo->FileId.Unique,
3298                                       ntStatus));
3299                     }
3300                     else
3301                     {
3302
3303                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3304                                       AFS_TRACE_LEVEL_WARNING,
3305                                       "AFSVerifyEntry Fcb NULL %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3306                                       &DirEntry->NameInformation.FileName,
3307                                       pObjectInfo->FileId.Cell,
3308                                       pObjectInfo->FileId.Volume,
3309                                       pObjectInfo->FileId.Vnode,
3310                                       pObjectInfo->FileId.Unique));
3311                     }
3312                 }
3313
3314                 if ( NT_SUCCESS( ntStatus))
3315                 {
3316
3317                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3318                 }
3319                 break;
3320             }
3321
3322             case AFS_FILE_TYPE_DIRECTORY:
3323             {
3324
3325                 //
3326                 // For a directory or root entry flush the content of
3327                 // the directory enumeration.
3328                 //
3329
3330                 if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
3331                 {
3332
3333                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3334                                   AFS_TRACE_LEVEL_VERBOSE_2,
3335                                   "AFSVerifyEntry Validating directory content for entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3336                                   &DirEntry->NameInformation.FileName,
3337                                   pObjectInfo->FileId.Cell,
3338                                   pObjectInfo->FileId.Volume,
3339                                   pObjectInfo->FileId.Vnode,
3340                                   pObjectInfo->FileId.Unique));
3341
3342                     AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3343                                     TRUE);
3344
3345                     ntStatus = AFSValidateDirectoryCache( pObjectInfo,
3346                                                           AuthGroup);
3347
3348                     AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3349
3350                     if ( !NT_SUCCESS( ntStatus))
3351                     {
3352
3353                         try_return( ntStatus);
3354                     }
3355                 }
3356
3357                 //
3358                 // Update the metadata for the entry
3359                 //
3360
3361                 ntStatus = AFSUpdateMetaData( DirEntry,
3362                                               pDirEnumEntry);
3363
3364                 if( NT_SUCCESS( ntStatus))
3365                 {
3366
3367                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3368                 }
3369
3370                 break;
3371             }
3372
3373             case AFS_FILE_TYPE_DFSLINK:
3374             {
3375
3376                 UNICODE_STRING uniTargetName;
3377
3378                 //
3379                 // For a DFS link need to check the target name has not changed
3380                 //
3381
3382                 uniTargetName.Length = (USHORT)pDirEnumEntry->TargetNameLength;
3383
3384                 uniTargetName.MaximumLength = uniTargetName.Length;
3385
3386                 uniTargetName.Buffer = (WCHAR *)((char *)pDirEnumEntry + pDirEnumEntry->TargetNameOffset);
3387
3388                 AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3389                                 TRUE);
3390
3391                 if( DirEntry->NameInformation.TargetName.Length == 0 ||
3392                     RtlCompareUnicodeString( &uniTargetName,
3393                                              &DirEntry->NameInformation.TargetName,
3394                                              TRUE) != 0)
3395                 {
3396
3397                     //
3398                     // Update the target name
3399                     //
3400
3401                     ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3402                                                     &DirEntry->Flags,
3403                                                     uniTargetName.Buffer,
3404                                                     uniTargetName.Length);
3405
3406                     if( !NT_SUCCESS( ntStatus))
3407                     {
3408
3409                         AFSReleaseResource( &DirEntry->NonPaged->Lock);
3410
3411                         break;
3412                     }
3413                 }
3414
3415                 AFSReleaseResource( &DirEntry->NonPaged->Lock);
3416
3417                 //
3418                 // Update the metadata for the entry
3419                 //
3420
3421                 ntStatus = AFSUpdateMetaData( DirEntry,
3422                                               pDirEnumEntry);
3423
3424                 if( NT_SUCCESS( ntStatus))
3425                 {
3426
3427                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
3428                 }
3429
3430                 break;
3431             }
3432
3433             default:
3434
3435                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3436                               AFS_TRACE_LEVEL_WARNING,
3437                               "AFSVerifyEntry Attempt to verify node of type %d %wZ FID %08lX-%08lX-%08lX-%08lX\n",
3438                               pObjectInfo->FileType,
3439                               &DirEntry->NameInformation.FileName,
3440                               pObjectInfo->FileId.Cell,
3441                               pObjectInfo->FileId.Volume,
3442                               pObjectInfo->FileId.Vnode,
3443                               pObjectInfo->FileId.Unique));
3444
3445                 break;
3446         }
3447
3448  try_exit:
3449
3450         if( pDirEnumEntry != NULL)
3451         {
3452
3453             AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_2_TAG);
3454         }
3455     }
3456
3457     return ntStatus;
3458 }
3459
3460 NTSTATUS
3461 AFSSetVolumeState( IN AFSVolumeStatusCB *VolumeStatus)
3462 {
3463
3464     NTSTATUS ntStatus = STATUS_SUCCESS;
3465     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
3466     ULONGLONG   ullIndex = 0;
3467     AFSVolumeCB *pVolumeCB = NULL;
3468     LONG lCount;
3469
3470     __Enter
3471     {
3472
3473         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3474                       AFS_TRACE_LEVEL_VERBOSE,
3475                       "AFSSetVolumeState Marking volume state %d Volume Cell %08lX Volume %08lX\n",
3476                       VolumeStatus->Online,
3477                       VolumeStatus->FileID.Cell,
3478                       VolumeStatus->FileID.Volume));
3479
3480         //
3481         // Need to locate the Fcb for the directory to purge
3482         //
3483
3484         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3485                       AFS_TRACE_LEVEL_VERBOSE,
3486                       "AFSSetVolumeState Acquiring RDR VolumeTreeLock lock %p SHARED %08lX\n",
3487                       &pDevExt->Specific.RDR.VolumeTreeLock,
3488                       PsGetCurrentThread()));
3489
3490         AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
3491
3492         //
3493         // Locate the volume node
3494         //
3495
3496         ullIndex = AFSCreateHighIndex( &VolumeStatus->FileID);
3497
3498         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
3499                                        ullIndex,
3500                                        (AFSBTreeEntry **)&pVolumeCB);
3501
3502         if( pVolumeCB != NULL)
3503         {
3504
3505             lCount = AFSVolumeIncrement( pVolumeCB,
3506                                          AFS_VOLUME_REFERENCE_INVALIDATE);
3507
3508             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
3509                           AFS_TRACE_LEVEL_VERBOSE,
3510                           "AFSSetVolumeState Increment count on volume %p Cnt %d\n",
3511                           pVolumeCB,
3512                           lCount));
3513
3514             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
3515
3516             //
3517             // Set the volume state accordingly
3518             //
3519
3520             if( VolumeStatus->Online)
3521             {
3522
3523                 InterlockedAnd( (LONG *)&(pVolumeCB->Flags), ~AFS_VOLUME_FLAGS_OFFLINE);
3524             }
3525             else
3526             {
3527
3528                 InterlockedOr( (LONG *)&(pVolumeCB->Flags), AFS_VOLUME_FLAGS_OFFLINE);
3529             }
3530         }
3531     }
3532
3533     return ntStatus;
3534 }
3535
3536 NTSTATUS
3537 AFSSetNetworkState( IN AFSNetworkStatusCB *NetworkStatus)
3538 {
3539
3540     NTSTATUS ntStatus = STATUS_SUCCESS;
3541
3542     __Enter
3543     {
3544
3545         if( AFSGlobalRoot == NULL)
3546         {
3547
3548             try_return( ntStatus);
3549         }
3550
3551         AFSAcquireExcl( AFSGlobalRoot->VolumeLock,
3552                         TRUE);
3553
3554         //
3555         // Set the network state according to the information
3556         //
3557
3558         if( NetworkStatus->Online)
3559         {
3560
3561             ClearFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3562         }
3563         else
3564         {
3565
3566             SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_FLAGS_OFFLINE);
3567         }
3568
3569         AFSReleaseResource( AFSGlobalRoot->VolumeLock);
3570
3571 try_exit:
3572
3573         NOTHING;
3574     }
3575
3576     return ntStatus;
3577 }
3578
3579 NTSTATUS
3580 AFSValidateDirectoryCache( IN AFSObjectInfoCB *ObjectInfo,
3581                            IN GUID *AuthGroup)
3582 {
3583
3584     NTSTATUS ntStatus = STATUS_SUCCESS;
3585     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
3586     BOOLEAN  bAcquiredLock = FALSE;
3587     AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
3588
3589     __Enter
3590     {
3591
3592         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3593                       AFS_TRACE_LEVEL_VERBOSE,
3594                       "AFSValidateDirectoryCache Validating content for FID %08lX-%08lX-%08lX-%08lX\n",
3595                       ObjectInfo->FileId.Cell,
3596                       ObjectInfo->FileId.Volume,
3597                       ObjectInfo->FileId.Vnode,
3598                       ObjectInfo->FileId.Unique));
3599
3600         if( !ExIsResourceAcquiredLite( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock))
3601         {
3602
3603             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
3604                           AFS_TRACE_LEVEL_VERBOSE,
3605                           "AFSValidateDirectoryCache Acquiring DirectoryNodeHdr.TreeLock lock %p EXCL %08lX\n",
3606                           ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3607                           PsGetCurrentThread()));
3608
3609             AFSAcquireExcl( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
3610                             TRUE);
3611
3612             bAcquiredLock = TRUE;
3613         }
3614
3615         //
3616         // Check for inconsistency between DirectoryNodeList and DirectoryNodeCount
3617         //
3618
3619         if ( ObjectInfo->Specific.Directory.DirectoryNodeListHead == NULL &&
3620              ObjectInfo->Specific.Directory.DirectoryNodeCount > 0)
3621         {
3622
3623             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3624                           AFS_TRACE_LEVEL_ERROR,
3625                           "AFSValidateDirectoryCache Empty Node List but Non-Zero Node Count %d for dir FID %08lX-%08lX-%08lX-%08lX\n",
3626                           ObjectInfo->Specific.Directory.DirectoryNodeCount,
3627                           ObjectInfo->FileId.Cell,
3628                           ObjectInfo->FileId.Volume,
3629                           ObjectInfo->FileId.Vnode,
3630                           ObjectInfo->FileId.Unique));
3631         }
3632
3633         //
3634         // Reset the directory list information by clearing all valid entries
3635         //
3636
3637         pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3638
3639         while( pCurrentDirEntry != NULL)
3640         {
3641
3642             pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3643
3644             if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
3645             {
3646
3647                 //
3648                 // If this entry has been deleted then process it here
3649                 //
3650
3651                 if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED) &&
3652                     pCurrentDirEntry->DirOpenReferenceCount <= 0 &&
3653                     pCurrentDirEntry->NameArrayReferenceCount <= 0)
3654                 {
3655
3656                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3657                                   AFS_TRACE_LEVEL_VERBOSE,
3658                                   "AFSValidateDirectoryCache Deleting dir entry %p name %wZ\n",
3659                                   pCurrentDirEntry,
3660                                   &pCurrentDirEntry->NameInformation.FileName));
3661
3662                     AFSDeleteDirEntry( ObjectInfo,
3663                                        &pCurrentDirEntry);
3664                 }
3665                 else
3666                 {
3667
3668                     ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID);
3669
3670                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3671                                   AFS_TRACE_LEVEL_VERBOSE,
3672                                   "AFSValidateDirectoryCache Clear VALID flag on DE %p Reference count %d\n",
3673                                   pCurrentDirEntry,
3674                                   pCurrentDirEntry->DirOpenReferenceCount));
3675
3676                     //
3677                     // We pull the short name from the parent tree since it could change below
3678                     //
3679
3680                     if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
3681                     {
3682
3683                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3684                                       AFS_TRACE_LEVEL_VERBOSE,
3685                                       "AFSValidateDirectoryCache Removing DE %p (%08lX) from shortname tree for %wZ\n",
3686                                       pCurrentDirEntry,
3687                                       pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3688                                       &pCurrentDirEntry->NameInformation.FileName));
3689
3690                         AFSRemoveShortNameDirEntry( &ObjectInfo->Specific.Directory.ShortNameTree,
3691                                                     pCurrentDirEntry);
3692
3693                         ClearFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3694                     }
3695                 }
3696             }
3697
3698             pCurrentDirEntry = pNextDirEntry;
3699         }
3700
3701         //
3702         // Reget the directory contents
3703         //
3704
3705         ntStatus = AFSVerifyDirectoryContent( ObjectInfo,
3706                                               AuthGroup);
3707
3708         if ( !NT_SUCCESS( ntStatus))
3709         {
3710             try_return( ntStatus);
3711         }
3712
3713         //
3714         // Now start again and tear down any entries not valid
3715         //
3716
3717         pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
3718
3719         while( pCurrentDirEntry != NULL)
3720         {
3721
3722             pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
3723
3724             if( BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_VALID))
3725             {
3726
3727                 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
3728                     !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME) &&
3729                     pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex > 0)
3730                 {
3731
3732                     if( ObjectInfo->Specific.Directory.ShortNameTree == NULL)
3733                     {
3734
3735                         ObjectInfo->Specific.Directory.ShortNameTree = pCurrentDirEntry;
3736
3737                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3738                                       AFS_TRACE_LEVEL_VERBOSE,
3739                                       "AFSValidateDirectoryCache Insert DE %p to head of shortname tree for %wZ\n",
3740                                       pCurrentDirEntry,
3741                                       &pCurrentDirEntry->NameInformation.FileName));
3742
3743                         SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3744                     }
3745                     else
3746                     {
3747
3748                         if( !NT_SUCCESS( AFSInsertShortNameDirEntry( ObjectInfo->Specific.Directory.ShortNameTree,
3749                                                                      pCurrentDirEntry)))
3750                         {
3751                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3752                                           AFS_TRACE_LEVEL_VERBOSE,
3753                                           "AFSValidateDirectoryCache Failed to insert DE %p (%08lX) to shortname tree for %wZ\n",
3754                                           pCurrentDirEntry,
3755                                           pCurrentDirEntry->Type.Data.ShortNameTreeEntry.HashIndex,
3756                                           &pCurrentDirEntry->NameInformation.FileName));
3757                         }
3758                         else
3759                         {
3760                             SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
3761
3762                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3763                                           AFS_TRACE_LEVEL_VERBOSE,
3764                                           "AFSValidateDirectoryCache Insert DE %p to shortname tree for %wZ\n",
3765                                           pCurrentDirEntry,
3766                                           &pCurrentDirEntry->NameInformation.FileName));
3767                         }
3768                     }
3769                 }
3770
3771                 pCurrentDirEntry = pNextDirEntry;
3772
3773                 continue;
3774             }
3775
3776             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3777                           AFS_TRACE_LEVEL_VERBOSE,
3778                           "AFSValidateDirectoryCache Processing INVALID DE %p Reference count %d\n",
3779                           pCurrentDirEntry,
3780                           pCurrentDirEntry->DirOpenReferenceCount));
3781
3782             if( pCurrentDirEntry->DirOpenReferenceCount <= 0 &&
3783                 pCurrentDirEntry->NameArrayReferenceCount <= 0)
3784             {
3785
3786                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3787                               AFS_TRACE_LEVEL_VERBOSE,
3788                               "AFSValidateDirectoryCache Deleting dir entry %wZ from parent FID %08lX-%08lX-%08lX-%08lX\n",
3789                               &pCurrentDirEntry->NameInformation.FileName,
3790                               ObjectInfo->FileId.Cell,
3791                               ObjectInfo->FileId.Volume,
3792                               ObjectInfo->FileId.Vnode,
3793                               ObjectInfo->FileId.Unique));
3794
3795                 AFSDeleteDirEntry( ObjectInfo,
3796                                    &pCurrentDirEntry);
3797             }
3798             else
3799             {
3800
3801                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3802                               AFS_TRACE_LEVEL_VERBOSE,
3803                               "AFSValidateDirectoryCache Setting dir entry %p Name %wZ DELETED in parent FID %08lX-%08lX-%08lX-%08lX\n",
3804                               pCurrentDirEntry,
3805                               &pCurrentDirEntry->NameInformation.FileName,
3806                               ObjectInfo->FileId.Cell,
3807                               ObjectInfo->FileId.Volume,
3808                               ObjectInfo->FileId.Vnode,
3809                               ObjectInfo->FileId.Unique));
3810
3811                 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
3812
3813                 AFSRemoveNameEntry( ObjectInfo,
3814                                     pCurrentDirEntry);
3815             }
3816
3817             pCurrentDirEntry = pNextDirEntry;
3818         }
3819
3820 #if DBG
3821         if( !AFSValidateDirList( ObjectInfo))
3822         {
3823
3824             AFSPrint("AFSValidateDirectoryCache Invalid count ...\n");
3825         }
3826 #endif
3827
3828 try_exit:
3829
3830         if( bAcquiredLock)
3831         {
3832
3833             AFSReleaseResource( ObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
3834         }
3835     }
3836
3837     return ntStatus;
3838 }
3839
3840 BOOLEAN
3841 AFSIsVolumeFID( IN AFSFileID *FileID)
3842 {
3843
3844     BOOLEAN bIsVolume = FALSE;
3845
3846     if( FileID->Vnode == 1 &&
3847         FileID->Unique == 1)
3848     {
3849
3850         bIsVolume = TRUE;
3851     }
3852
3853     return bIsVolume;
3854 }
3855
3856 BOOLEAN
3857 AFSIsFinalNode( IN AFSFcb *Fcb)
3858 {
3859
3860     BOOLEAN bIsFinalNode = FALSE;
3861
3862     if( Fcb->Header.NodeTypeCode == AFS_ROOT_FCB ||
3863         Fcb->Header.NodeTypeCode == AFS_DIRECTORY_FCB ||
3864         Fcb->Header.NodeTypeCode == AFS_FILE_FCB ||
3865         Fcb->Header.NodeTypeCode == AFS_DFS_LINK_FCB ||
3866         Fcb->Header.NodeTypeCode == AFS_INVALID_FCB )
3867     {
3868
3869         bIsFinalNode = TRUE;
3870     }
3871     else
3872     {
3873
3874         ASSERT( Fcb->Header.NodeTypeCode == AFS_MOUNT_POINT_FCB ||
3875                 Fcb->Header.NodeTypeCode == AFS_SYMBOLIC_LINK_FCB);
3876     }
3877
3878     return bIsFinalNode;
3879 }
3880
3881 NTSTATUS
3882 AFSUpdateMetaData( IN AFSDirectoryCB *DirEntry,
3883                    IN AFSDirEnumEntry *DirEnumEntry)
3884 {
3885
3886     NTSTATUS ntStatus = STATUS_SUCCESS;
3887     UNICODE_STRING uniTargetName;
3888     AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
3889
3890     __Enter
3891     {
3892
3893         pObjectInfo->TargetFileId = DirEnumEntry->TargetFileId;
3894
3895         pObjectInfo->Expiration = DirEnumEntry->Expiration;
3896
3897         pObjectInfo->DataVersion = DirEnumEntry->DataVersion;
3898
3899         pObjectInfo->FileType = DirEnumEntry->FileType;
3900
3901         pObjectInfo->CreationTime = DirEnumEntry->CreationTime;
3902
3903         pObjectInfo->LastAccessTime = DirEnumEntry->LastAccessTime;
3904
3905         pObjectInfo->LastWriteTime = DirEnumEntry->LastWriteTime;
3906
3907         pObjectInfo->ChangeTime = DirEnumEntry->ChangeTime;
3908
3909         pObjectInfo->EndOfFile = DirEnumEntry->EndOfFile;
3910
3911         pObjectInfo->AllocationSize = DirEnumEntry->AllocationSize;
3912
3913         pObjectInfo->FileAttributes = DirEnumEntry->FileAttributes;
3914
3915         if( pObjectInfo->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
3916             pObjectInfo->FileType == AFS_FILE_TYPE_DFSLINK)
3917         {
3918
3919             pObjectInfo->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
3920         }
3921
3922         if( pObjectInfo->FileType == AFS_FILE_TYPE_SYMLINK)
3923         {
3924
3925             if ( pObjectInfo->FileAttributes == FILE_ATTRIBUTE_NORMAL)
3926             {
3927
3928                 pObjectInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
3929             }
3930             else
3931             {
3932
3933                 pObjectInfo->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
3934             }
3935         }
3936
3937         pObjectInfo->EaSize = DirEnumEntry->EaSize;
3938
3939         pObjectInfo->Links = DirEnumEntry->Links;
3940
3941         if( DirEnumEntry->TargetNameLength > 0 &&
3942             ( DirEntry->NameInformation.TargetName.Length != DirEnumEntry->TargetNameLength ||
3943               DirEntry->ObjectInformation->DataVersion.QuadPart != DirEnumEntry->DataVersion.QuadPart))
3944         {
3945
3946             //
3947             // Update the target name information if needed
3948             //
3949
3950             uniTargetName.Length = (USHORT)DirEnumEntry->TargetNameLength;
3951
3952             uniTargetName.MaximumLength = uniTargetName.Length;
3953
3954             uniTargetName.Buffer = (WCHAR *)((char *)DirEnumEntry + DirEnumEntry->TargetNameOffset);
3955
3956             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3957                             TRUE);
3958
3959             if( DirEntry->NameInformation.TargetName.Length == 0 ||
3960                 RtlCompareUnicodeString( &uniTargetName,
3961                                          &DirEntry->NameInformation.TargetName,
3962                                          TRUE) != 0)
3963             {
3964
3965                 //
3966                 // Update the target name
3967                 //
3968
3969                 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
3970                                                 &DirEntry->Flags,
3971                                                 uniTargetName.Buffer,
3972                                                 uniTargetName.Length);
3973
3974                 if( !NT_SUCCESS( ntStatus))
3975                 {
3976
3977                     AFSReleaseResource( &DirEntry->NonPaged->Lock);
3978
3979                     try_return( ntStatus);
3980                 }
3981             }
3982
3983             AFSReleaseResource( &DirEntry->NonPaged->Lock);
3984         }
3985         else if( DirEntry->NameInformation.TargetName.Length > 0 &&
3986                  DirEntry->ObjectInformation->DataVersion.QuadPart != DirEnumEntry->DataVersion.QuadPart)
3987         {
3988
3989             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
3990                             TRUE);
3991
3992             if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER) &&
3993                 DirEntry->NameInformation.TargetName.Buffer != NULL)
3994             {
3995                 AFSExFreePoolWithTag( DirEntry->NameInformation.TargetName.Buffer, AFS_NAME_BUFFER_FIVE_TAG);
3996             }
3997
3998             ClearFlag( DirEntry->Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER);
3999
4000             DirEntry->NameInformation.TargetName.Length = 0;
4001             DirEntry->NameInformation.TargetName.MaximumLength = 0;
4002             DirEntry->NameInformation.TargetName.Buffer = NULL;
4003
4004             AFSReleaseResource( &DirEntry->NonPaged->Lock);
4005         }
4006
4007 try_exit:
4008
4009         NOTHING;
4010     }
4011
4012     return ntStatus;
4013 }
4014
4015 NTSTATUS
4016 AFSValidateEntry( IN AFSDirectoryCB *DirEntry,
4017                   IN GUID *AuthGroup,
4018                   IN BOOLEAN FastCall,
4019                   IN BOOLEAN bSafeToPurge)
4020 {
4021
4022     NTSTATUS ntStatus = STATUS_SUCCESS;
4023     AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
4024     LARGE_INTEGER liSystemTime;
4025     AFSDirEnumEntry *pDirEnumEntry = NULL;
4026     AFSFcb *pCurrentFcb = NULL;
4027     BOOLEAN bReleaseFcb = FALSE;
4028     AFSObjectInfoCB *pObjectInfo = DirEntry->ObjectInformation;
4029
4030     __Enter
4031     {
4032
4033         //
4034         // If we have an Fcb hanging off the directory entry then be sure to acquire the locks in the
4035         // correct order
4036         //
4037
4038         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4039                       AFS_TRACE_LEVEL_VERBOSE_2,
4040                       "AFSValidateEntry Validating entry %wZ FID %08lX-%08lX-%08lX-%08lX FastCall %u\n",
4041                       &DirEntry->NameInformation.FileName,
4042                       pObjectInfo->FileId.Cell,
4043                       pObjectInfo->FileId.Volume,
4044                       pObjectInfo->FileId.Vnode,
4045                       pObjectInfo->FileId.Unique,
4046                       FastCall));
4047
4048         //
4049         // If this is a fake node then bail since the service knows nothing about it
4050         //
4051
4052         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_FAKE))
4053         {
4054
4055             try_return( ntStatus);
4056         }
4057
4058         //
4059         // This routine ensures that the current entry is valid by:
4060         //
4061         //      1) Checking that the expiration time is non-zero and after where we
4062         //         currently are
4063         //
4064
4065         KeQuerySystemTime( &liSystemTime);
4066
4067         if( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) &&
4068             !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY) &&
4069             !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA) &&
4070             pObjectInfo->Expiration.QuadPart >= liSystemTime.QuadPart)
4071         {
4072
4073             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4074                           AFS_TRACE_LEVEL_VERBOSE_2,
4075                           "AFSValidateEntry Directory entry %wZ FID %08lX-%08lX-%08lX-%08lX VALID\n",
4076                           &DirEntry->NameInformation.FileName,
4077                           pObjectInfo->FileId.Cell,
4078                           pObjectInfo->FileId.Volume,
4079                           pObjectInfo->FileId.Vnode,
4080                           pObjectInfo->FileId.Unique));
4081
4082             try_return( ntStatus);
4083         }
4084
4085         //
4086         // This node requires updating
4087         //
4088
4089         ntStatus = AFSEvaluateTargetByID( pObjectInfo,
4090                                           AuthGroup,
4091                                           FastCall,
4092                                           &pDirEnumEntry);
4093
4094         if( !NT_SUCCESS( ntStatus))
4095         {
4096
4097             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4098                           AFS_TRACE_LEVEL_ERROR,
4099                           "AFSValidateEntry Failed to evaluate entry FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4100                           FastCall,
4101                           &DirEntry->NameInformation.FileName,
4102                           pObjectInfo->FileId.Cell,
4103                           pObjectInfo->FileId.Volume,
4104                           pObjectInfo->FileId.Vnode,
4105                           pObjectInfo->FileId.Unique,
4106                           ntStatus));
4107
4108             //
4109             // Failed validation of node so return access-denied
4110             //
4111
4112             try_return( ntStatus);
4113         }
4114
4115         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4116                       AFS_TRACE_LEVEL_VERBOSE,
4117                       "AFSValidateEntry Validating entry FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX DV %I64X returned DV %I64X FT %d\n",
4118                       FastCall,
4119                       &DirEntry->NameInformation.FileName,
4120                       pObjectInfo->FileId.Cell,
4121                       pObjectInfo->FileId.Volume,
4122                       pObjectInfo->FileId.Vnode,
4123                       pObjectInfo->FileId.Unique,
4124                       pObjectInfo->DataVersion.QuadPart,
4125                       pDirEnumEntry->DataVersion.QuadPart,
4126                       pDirEnumEntry->FileType));
4127
4128
4129         //
4130         // Based on the file type, process the node
4131         //
4132
4133         switch( pDirEnumEntry->FileType)
4134         {
4135
4136             case AFS_FILE_TYPE_MOUNTPOINT:
4137             {
4138
4139                 //
4140                 // Update the metadata for the entry
4141                 //
4142
4143                 ntStatus = AFSUpdateMetaData( DirEntry,
4144                                               pDirEnumEntry);
4145
4146                 if( NT_SUCCESS( ntStatus))
4147                 {
4148
4149                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
4150                 }
4151
4152                 break;
4153             }
4154
4155             case AFS_FILE_TYPE_SYMLINK:
4156             case AFS_FILE_TYPE_DFSLINK:
4157             {
4158
4159                 //
4160                 // Update the metadata for the entry
4161                 //
4162
4163                 ntStatus = AFSUpdateMetaData( DirEntry,
4164                                               pDirEnumEntry);
4165
4166                 if( NT_SUCCESS( ntStatus))
4167                 {
4168
4169                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
4170                 }
4171
4172                 break;
4173             }
4174
4175             case AFS_FILE_TYPE_FILE:
4176             {
4177
4178                 BOOLEAN bPurgeExtents = FALSE;
4179
4180                 //
4181                 // For a file where the data version has become invalid we need to
4182                 // fail any current extent requests and purge the cache for the file
4183                 // Can't hold the Fcb resource while doing this
4184                 //
4185
4186                 if( pObjectInfo->Fcb != NULL &&
4187                     (pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart ||
4188                       BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA)))
4189                 {
4190
4191                     pCurrentFcb = pObjectInfo->Fcb;
4192
4193                     if( !ExIsResourceAcquiredLite( &pCurrentFcb->NPFcb->Resource))
4194                     {
4195
4196                         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4197                                       AFS_TRACE_LEVEL_VERBOSE,
4198                                       "AFSValidateEntry Acquiring Fcb lock %p EXCL %08lX\n",
4199                                       &pCurrentFcb->NPFcb->Resource,
4200                                       PsGetCurrentThread()));
4201
4202                         AFSAcquireExcl( &pCurrentFcb->NPFcb->Resource,
4203                                         TRUE);
4204
4205                         bReleaseFcb = TRUE;
4206                     }
4207
4208                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4209                                   AFS_TRACE_LEVEL_VERBOSE_2,
4210                                   "AFSValidateEntry Flush/purge entry %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4211                                   &DirEntry->NameInformation.FileName,
4212                                   pObjectInfo->FileId.Cell,
4213                                   pObjectInfo->FileId.Volume,
4214                                   pObjectInfo->FileId.Vnode,
4215                                   pObjectInfo->FileId.Unique));
4216
4217                     if ( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
4218                     {
4219
4220                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4221                                       AFS_TRACE_LEVEL_VERBOSE,
4222                                       "AFSValidateEntry DV Change %wZ FID %08lX-%08lX-%08lX-%08lX (%08lX != %08lX)\n",
4223                                       &DirEntry->NameInformation.FileName,
4224                                       pObjectInfo->FileId.Cell,
4225                                       pObjectInfo->FileId.Volume,
4226                                       pObjectInfo->FileId.Vnode,
4227                                       pObjectInfo->FileId.Unique,
4228                                       pObjectInfo->DataVersion.LowPart,
4229                                       pDirEnumEntry->DataVersion.LowPart));
4230
4231                         bPurgeExtents = TRUE;
4232                     }
4233
4234                     if ( bSafeToPurge)
4235                     {
4236
4237                         if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA))
4238                         {
4239                             bPurgeExtents = TRUE;
4240
4241                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4242                                           AFS_TRACE_LEVEL_VERBOSE,
4243                                           "AFSVerifyEntry Clearing VERIFY_DATA flag %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4244                                           &DirEntry->NameInformation.FileName,
4245                                           pObjectInfo->FileId.Cell,
4246                                           pObjectInfo->FileId.Volume,
4247                                           pObjectInfo->FileId.Vnode,
4248                                           pObjectInfo->FileId.Unique));
4249
4250                             ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
4251                         }
4252
4253                         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
4254                                       AFS_TRACE_LEVEL_VERBOSE,
4255                                       "AFSValidateEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
4256                                       &pCurrentFcb->NPFcb->SectionObjectResource,
4257                                       PsGetCurrentThread()));
4258
4259                         AFSAcquireExcl( &pCurrentFcb->NPFcb->SectionObjectResource,
4260                                         TRUE);
4261
4262                         __try
4263                         {
4264
4265                             IO_STATUS_BLOCK stIoStatus;
4266
4267                             CcFlushCache( &pCurrentFcb->NPFcb->SectionObjectPointers,
4268                                           NULL,
4269                                           0,
4270                                           &stIoStatus);
4271
4272                             if( !NT_SUCCESS( stIoStatus.Status))
4273                             {
4274
4275                                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
4276                                               AFS_TRACE_LEVEL_ERROR,
4277                                               "AFSValidateEntry CcFlushCache failure %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
4278                                               &DirEntry->NameInformation.FileName,
4279                                               pObjectInfo->FileId.Cell,
4280                                               pObjectInfo->FileId.Volume,
4281                                               pObjectInfo->FileId.Vnode,
4282                                               pObjectInfo->FileId.Unique,
4283                                               stIoStatus.Status,
4284                                               stIoStatus.Information));
4285
4286                                 ntStatus = stIoStatus.Status;
4287                             }
4288
4289                             if ( bPurgeExtents &&
4290                                  pCurrentFcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
4291                             {
4292
4293                                 if ( !CcPurgeCacheSection( &pCurrentFcb->NPFcb->SectionObjectPointers,
4294                                                            NULL,
4295                                                            0,
4296                                                            FALSE))
4297                                 {
4298
4299                                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
4300                                                   AFS_TRACE_LEVEL_WARNING,
4301                                                   "AFSValidateEntry CcPurgeCacheSection failure %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4302                                                   &DirEntry->NameInformation.FileName,
4303                                                   pObjectInfo->FileId.Cell,
4304                                                   pObjectInfo->FileId.Volume,
4305                                                   pObjectInfo->FileId.Vnode,
4306                                                   pObjectInfo->FileId.Unique));
4307
4308                                     SetFlag( pObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
4309                                 }
4310                             }
4311                         }
4312                         __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
4313                         {
4314                             ntStatus = GetExceptionCode();
4315
4316                             AFSDbgTrace(( 0,
4317                                           0,
4318                                           "EXCEPTION - AFSValidateEntry CcFlushCache or CcPurgeCacheSection %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
4319                                           &DirEntry->NameInformation.FileName,
4320                                           pObjectInfo->FileId.Cell,
4321                                           pObjectInfo->FileId.Volume,
4322                                           pObjectInfo->FileId.Vnode,
4323                                           pObjectInfo->FileId.Unique,
4324                                           ntStatus));
4325
4326                             SetFlag( pCurrentFcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
4327                         }
4328
4329                         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
4330                                       AFS_TRACE_LEVEL_VERBOSE,
4331                                       "AFSValidateEntry Releasing Fcb SectionObject lock %p EXCL %08lX\n",
4332                                       &pCurrentFcb->NPFcb->SectionObjectResource,
4333                                       PsGetCurrentThread()));
4334
4335                         AFSReleaseResource( &pCurrentFcb->NPFcb->SectionObjectResource);
4336                     }
4337                     else
4338                     {
4339
4340                         if ( bPurgeExtents)
4341                         {
4342
4343                             SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
4344                         }
4345                     }
4346
4347                     if (bReleaseFcb)
4348                     {
4349                         AFSReleaseResource( &pCurrentFcb->NPFcb->Resource);
4350
4351                         bReleaseFcb = FALSE;
4352                     }
4353
4354                     if ( bPurgeExtents &&
4355                          bSafeToPurge)
4356                     {
4357
4358                         if( !BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
4359                         {
4360                             AFSFlushExtents( pCurrentFcb,
4361                                              AuthGroup);
4362                         }
4363                     }
4364                 }
4365
4366                 //
4367                 // Update the metadata for the entry but only if it is safe to do so.
4368                 // If it was determined that a data version change has occurred or
4369                 // that a pending data verification was required, do not update the
4370                 // ObjectInfo meta data or the FileObject size information.  That
4371                 // way it is consistent for the next time that the data is verified
4372                 // or validated.
4373                 //
4374
4375                 if ( !(bPurgeExtents && bSafeToPurge))
4376                 {
4377
4378                     ntStatus = AFSUpdateMetaData( DirEntry,
4379                                                   pDirEnumEntry);
4380
4381                     if( !NT_SUCCESS( ntStatus))
4382                     {
4383
4384                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4385                                       AFS_TRACE_LEVEL_ERROR,
4386                                       "AFSValidateEntry Meta Data Update failed %wZ FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
4387                                       &DirEntry->NameInformation.FileName,
4388                                       pObjectInfo->FileId.Cell,
4389                                       pObjectInfo->FileId.Volume,
4390                                       pObjectInfo->FileId.Vnode,
4391                                       pObjectInfo->FileId.Unique,
4392                                       ntStatus));
4393
4394                         break;
4395                     }
4396
4397                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
4398
4399                     //
4400                     // Update file sizes
4401                     //
4402
4403                     if( pObjectInfo->Fcb != NULL)
4404                     {
4405                         FILE_OBJECT *pCCFileObject;
4406
4407                         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
4408                                       AFS_TRACE_LEVEL_VERBOSE,
4409                                       "AFSValidateEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
4410                                       &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
4411                                       PsGetCurrentThread()));
4412
4413                         AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
4414                                         TRUE);
4415
4416                         __try
4417                         {
4418
4419                             pCCFileObject = CcGetFileObjectFromSectionPtrs( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers);
4420
4421                             pObjectInfo->Fcb->Header.AllocationSize.QuadPart  = pObjectInfo->AllocationSize.QuadPart;
4422                             pObjectInfo->Fcb->Header.FileSize.QuadPart        = pObjectInfo->EndOfFile.QuadPart;
4423                             pObjectInfo->Fcb->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
4424
4425                             if ( pCCFileObject != NULL)
4426                             {
4427                                 CcSetFileSizes( pCCFileObject,
4428                                                 (PCC_FILE_SIZES)&pObjectInfo->Fcb->Header.AllocationSize);
4429                             }
4430                         }
4431                         __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
4432                         {
4433
4434                             ntStatus = GetExceptionCode();
4435
4436                             AFSDbgTrace(( 0,
4437                                           0,
4438                                           "EXCEPTION - AFSValidateEntry CcSetFileSizes failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
4439                                           pObjectInfo->FileId.Cell,
4440                                           pObjectInfo->FileId.Volume,
4441                                           pObjectInfo->FileId.Vnode,
4442                                           pObjectInfo->FileId.Unique,
4443                                           ntStatus));
4444                         }
4445
4446                         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
4447                                       AFS_TRACE_LEVEL_VERBOSE,
4448                                       "AFSValidateEntry Releasing Fcb SectionObject lock %p EXCL %08lX\n",
4449                                       &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
4450                                       PsGetCurrentThread()));
4451
4452                         AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
4453                     }
4454                 }
4455                 break;
4456             }
4457
4458             case AFS_FILE_TYPE_DIRECTORY:
4459             {
4460
4461                 if( pObjectInfo->DataVersion.QuadPart != pDirEnumEntry->DataVersion.QuadPart)
4462                 {
4463
4464                     //
4465                     // For a directory or root entry flush the content of
4466                     // the directory enumeration.
4467                     //
4468
4469                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
4470                                   AFS_TRACE_LEVEL_VERBOSE,
4471                                   "AFSValidateEntry Acquiring DirectoryNodeHdr.TreeLock lock %p EXCL %08lX\n",
4472                                   pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
4473                                   PsGetCurrentThread()));
4474
4475                     if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
4476                     {
4477
4478                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4479                                       AFS_TRACE_LEVEL_VERBOSE_2,
4480                                       "AFSValidateEntry Validating directory content for %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4481                                       &DirEntry->NameInformation.FileName,
4482                                       pObjectInfo->FileId.Cell,
4483                                       pObjectInfo->FileId.Volume,
4484                                       pObjectInfo->FileId.Vnode,
4485                                       pObjectInfo->FileId.Unique));
4486
4487                         AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
4488                                         TRUE);
4489
4490                         ntStatus = AFSValidateDirectoryCache( pObjectInfo,
4491                                                               AuthGroup);
4492
4493                         AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
4494                     }
4495
4496                     if( !NT_SUCCESS( ntStatus))
4497                     {
4498
4499                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4500                                       AFS_TRACE_LEVEL_ERROR,
4501                                       "AFSValidateEntry Failed to re-enumerate %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
4502                                       &DirEntry->NameInformation.FileName,
4503                                       pObjectInfo->FileId.Cell,
4504                                       pObjectInfo->FileId.Volume,
4505                                       pObjectInfo->FileId.Vnode,
4506                                       pObjectInfo->FileId.Unique,
4507                                       ntStatus));
4508
4509                         break;
4510                     }
4511                 }
4512
4513                 //
4514                 // Update the metadata for the entry
4515                 //
4516
4517                 ntStatus = AFSUpdateMetaData( DirEntry,
4518                                               pDirEnumEntry);
4519
4520                 if( NT_SUCCESS( ntStatus))
4521                 {
4522
4523                     ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY | AFS_OBJECT_FLAGS_NOT_EVALUATED);
4524                 }
4525
4526                 break;
4527             }
4528
4529             default:
4530
4531                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4532                               AFS_TRACE_LEVEL_WARNING,
4533                               "AFSValidateEntry Attempt to verify node of type %d FastCall %d %wZ FID %08lX-%08lX-%08lX-%08lX\n",
4534                               pObjectInfo->FileType,
4535                               FastCall,
4536                               &DirEntry->NameInformation.FileName,
4537                               pObjectInfo->FileId.Cell,
4538                               pObjectInfo->FileId.Volume,
4539                               pObjectInfo->FileId.Vnode,
4540                               pObjectInfo->FileId.Unique));
4541
4542                 break;
4543         }
4544
4545  try_exit:
4546
4547         if( bReleaseFcb)
4548         {
4549
4550             AFSReleaseResource( &pCurrentFcb->NPFcb->Resource);
4551         }
4552
4553         if( pDirEnumEntry != NULL)
4554         {
4555
4556             AFSExFreePoolWithTag( pDirEnumEntry, AFS_GENERIC_MEMORY_2_TAG);
4557         }
4558     }
4559
4560     return ntStatus;
4561 }
4562
4563 NTSTATUS
4564 AFSInitializeSpecialShareNameList()
4565 {
4566
4567     NTSTATUS ntStatus = STATUS_SUCCESS;
4568     AFSDirectoryCB *pDirNode = NULL, *pLastDirNode = NULL;
4569     AFSObjectInfoCB *pObjectInfoCB = NULL;
4570     UNICODE_STRING uniShareName;
4571     ULONG ulEntryLength = 0;
4572     AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
4573     LONG lCount;
4574
4575     __Enter
4576     {
4577
4578         RtlInitUnicodeString( &uniShareName,
4579                               L"PIPE");
4580
4581         pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
4582                                                0);
4583
4584         if( pObjectInfoCB == NULL)
4585         {
4586
4587             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4588         }
4589
4590         lCount = AFSObjectInfoIncrement( pObjectInfoCB,
4591                                          AFS_OBJECT_REFERENCE_GLOBAL);
4592
4593         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4594                       AFS_TRACE_LEVEL_VERBOSE,
4595                       "AFSInitializeSpecialShareNameList (srvsvc) Increment count on object %p Cnt %d\n",
4596                       pObjectInfoCB,
4597                       lCount));
4598
4599         pObjectInfoCB->FileType = (ULONG) AFS_FILE_TYPE_SPECIAL_SHARE_NAME;
4600
4601         ulEntryLength = sizeof( AFSDirectoryCB) +
4602                                      uniShareName.Length;
4603
4604         pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
4605                                                                   ulEntryLength,
4606                                                                   AFS_DIR_ENTRY_TAG);
4607
4608         if( pDirNode == NULL)
4609         {
4610
4611             lCount = AFSObjectInfoDecrement( pObjectInfoCB,
4612                                              AFS_OBJECT_REFERENCE_GLOBAL);
4613
4614             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4615                           AFS_TRACE_LEVEL_VERBOSE,
4616                           "AFSInitializeSpecialShareNameList Decrement count on object %p Cnt %d\n",
4617                           pObjectInfoCB,
4618                           lCount));
4619
4620             if ( lCount == 0)
4621             {
4622
4623                 AFSDeleteObjectInfo( &pObjectInfoCB);
4624             }
4625
4626             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4627         }
4628
4629         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
4630                       AFS_TRACE_LEVEL_VERBOSE,
4631                       "AFSInitializeSpecialShareNameList (srvsvc) AFS_DIR_ENTRY_TAG allocated %p\n",
4632                       pDirNode));
4633
4634         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
4635                                                                                    sizeof( AFSNonPagedDirectoryCB),
4636                                                                                    AFS_DIR_ENTRY_NP_TAG);
4637
4638         if( pNonPagedDirEntry == NULL)
4639         {
4640
4641             AFSLibExFreePoolWithTag( pDirNode,
4642                                      AFS_DIR_ENTRY_TAG);
4643
4644             lCount = AFSObjectInfoDecrement( pObjectInfoCB,
4645                                              AFS_OBJECT_REFERENCE_GLOBAL);
4646
4647             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4648                           AFS_TRACE_LEVEL_VERBOSE,
4649                           "AFSInitializeSpecialShareNameList Decrement count on object %p Cnt %d\n",
4650                           pObjectInfoCB,
4651                           lCount));
4652
4653             if ( lCount == 0)
4654             {
4655
4656                 AFSDeleteObjectInfo( &pObjectInfoCB);
4657             }
4658
4659             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4660         }
4661
4662         RtlZeroMemory( pDirNode,
4663                        ulEntryLength);
4664
4665         RtlZeroMemory( pNonPagedDirEntry,
4666                        sizeof( AFSNonPagedDirectoryCB));
4667
4668         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
4669
4670         pDirNode->NonPaged = pNonPagedDirEntry;
4671
4672         pDirNode->ObjectInformation = pObjectInfoCB;
4673
4674         //
4675         // Set valid entry
4676         //
4677
4678         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_PIPE_SERVICE);
4679
4680         pDirNode->NameInformation.FileName.Length = uniShareName.Length;
4681
4682         pDirNode->NameInformation.FileName.MaximumLength = uniShareName.Length;
4683
4684         pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
4685
4686         RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
4687                        uniShareName.Buffer,
4688                        pDirNode->NameInformation.FileName.Length);
4689
4690         pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
4691                                                                        TRUE);
4692
4693         AFSSpecialShareNames = pDirNode;
4694
4695         pLastDirNode = pDirNode;
4696
4697
4698         RtlInitUnicodeString( &uniShareName,
4699                               L"IPC$");
4700
4701         pObjectInfoCB = AFSAllocateObjectInfo( &AFSGlobalRoot->ObjectInformation,
4702                                                0);
4703
4704         if( pObjectInfoCB == NULL)
4705         {
4706
4707             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4708         }
4709
4710         lCount = AFSObjectInfoIncrement( pObjectInfoCB,
4711                                          AFS_OBJECT_REFERENCE_GLOBAL);
4712
4713         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4714                       AFS_TRACE_LEVEL_VERBOSE,
4715                       "AFSInitializeSpecialShareNameList (ipc$) Incrementing count on object %p Cnt %d\n",
4716                       pObjectInfoCB,
4717                       lCount));
4718
4719         pObjectInfoCB->FileType = (ULONG) AFS_FILE_TYPE_SPECIAL_SHARE_NAME;
4720
4721         ulEntryLength = sizeof( AFSDirectoryCB) +
4722                                      uniShareName.Length;
4723
4724         pDirNode = (AFSDirectoryCB *)AFSLibExAllocatePoolWithTag( PagedPool,
4725                                                                   ulEntryLength,
4726                                                                   AFS_DIR_ENTRY_TAG);
4727
4728         if( pDirNode == NULL)
4729         {
4730
4731             lCount = AFSObjectInfoDecrement( pObjectInfoCB,
4732                                              AFS_OBJECT_REFERENCE_GLOBAL);
4733
4734             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4735                           AFS_TRACE_LEVEL_VERBOSE,
4736                           "AFSInitializeSpecialShareNameList Decrement count on object %p Cnt %d\n",
4737                           pObjectInfoCB,
4738                           lCount));
4739
4740             if ( lCount == 0)
4741             {
4742
4743                 AFSDeleteObjectInfo( &pObjectInfoCB);
4744             }
4745
4746             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4747         }
4748
4749         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
4750                       AFS_TRACE_LEVEL_VERBOSE,
4751                       "AFSInitializeSpecialShareNameList (ipc$) AFS_DIR_ENTRY_TAG allocated %p\n",
4752                       pDirNode));
4753
4754         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSLibExAllocatePoolWithTag( NonPagedPool,
4755                                                                                    sizeof( AFSNonPagedDirectoryCB),
4756                                                                                    AFS_DIR_ENTRY_NP_TAG);
4757
4758         if( pNonPagedDirEntry == NULL)
4759         {
4760
4761             AFSLibExFreePoolWithTag( pDirNode,
4762                                      AFS_DIR_ENTRY_TAG);
4763
4764             lCount = AFSObjectInfoDecrement( pObjectInfoCB,
4765                                              AFS_OBJECT_REFERENCE_GLOBAL);
4766
4767             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4768                           AFS_TRACE_LEVEL_VERBOSE,
4769                           "AFSInitializeSpecialShareNameList Decrement count on object %p Cnt %d\n",
4770                           pObjectInfoCB,
4771                           lCount));
4772
4773             if ( lCount == 0)
4774             {
4775
4776                 AFSDeleteObjectInfo( &pObjectInfoCB);
4777             }
4778
4779             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
4780         }
4781
4782         RtlZeroMemory( pDirNode,
4783                        ulEntryLength);
4784
4785         RtlZeroMemory( pNonPagedDirEntry,
4786                        sizeof( AFSNonPagedDirectoryCB));
4787
4788         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
4789
4790         pDirNode->NonPaged = pNonPagedDirEntry;
4791
4792         pDirNode->ObjectInformation = pObjectInfoCB;
4793
4794         //
4795         // Set valid entry
4796         //
4797
4798         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_IPC);
4799
4800         pDirNode->NameInformation.FileName.Length = uniShareName.Length;
4801
4802         pDirNode->NameInformation.FileName.MaximumLength = uniShareName.Length;
4803
4804         pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
4805
4806         RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
4807                        uniShareName.Buffer,
4808                        pDirNode->NameInformation.FileName.Length);
4809
4810         pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
4811                                                                        TRUE);
4812
4813         pLastDirNode->ListEntry.fLink = pDirNode;
4814
4815         pDirNode->ListEntry.bLink = pLastDirNode;
4816
4817 try_exit:
4818
4819         if( !NT_SUCCESS( ntStatus))
4820         {
4821
4822             if( AFSSpecialShareNames != NULL)
4823             {
4824
4825                 pDirNode = AFSSpecialShareNames;
4826
4827                 while( pDirNode != NULL)
4828                 {
4829
4830                     pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
4831
4832                     lCount = AFSObjectInfoDecrement( pDirNode->ObjectInformation,
4833                                                      AFS_OBJECT_REFERENCE_GLOBAL);
4834
4835                     AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
4836                                   AFS_TRACE_LEVEL_VERBOSE,
4837                                   "AFSInitializeSpecialShareNameList Decrement count on object %p Cnt %d\n",
4838                                   pDirNode->ObjectInformation,
4839                                   lCount));
4840
4841                     if ( lCount == 0)
4842                     {
4843
4844                         AFSDeleteObjectInfo( &pDirNode->ObjectInformation);
4845                     }
4846
4847                     ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
4848
4849                     AFSLibExFreePoolWithTag( pDirNode->NonPaged,
4850                                              AFS_DIR_ENTRY_NP_TAG);
4851
4852                     AFSLibExFreePoolWithTag( pDirNode,
4853                                              AFS_DIR_ENTRY_TAG);
4854
4855                     pDirNode = pLastDirNode;
4856                 }
4857
4858                 AFSSpecialShareNames = NULL;
4859             }
4860         }
4861     }
4862
4863     return ntStatus;
4864 }
4865
4866 AFSDirectoryCB *
4867 AFSGetSpecialShareNameEntry( IN UNICODE_STRING *ShareName,
4868                              IN UNICODE_STRING *SecondaryName)
4869 {
4870
4871     AFSDirectoryCB *pDirectoryCB = NULL;
4872     ULONGLONG ullHash = 0;
4873     UNICODE_STRING uniFullShareName;
4874
4875     __Enter
4876     {
4877
4878
4879         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
4880                       AFS_TRACE_LEVEL_VERBOSE_2,
4881                       "AFSGetSpecialShareNameEntry share name %wZ secondary name %wZ\n",
4882                       ShareName,
4883                       SecondaryName));
4884
4885         uniFullShareName = *ShareName;
4886
4887         //
4888         // Generate our hash value
4889         //
4890
4891         ullHash = AFSGenerateCRC( &uniFullShareName,
4892                                   TRUE);
4893
4894         //
4895         // Loop through our special share names to see if this is one of them
4896         //
4897
4898         pDirectoryCB = AFSSpecialShareNames;
4899
4900         while( pDirectoryCB != NULL)
4901         {
4902
4903             if( ullHash == pDirectoryCB->CaseInsensitiveTreeEntry.HashIndex)
4904             {
4905
4906                 break;
4907             }
4908
4909             pDirectoryCB = (AFSDirectoryCB *)pDirectoryCB->ListEntry.fLink;
4910         }
4911     }
4912
4913     return pDirectoryCB;
4914 }
4915
4916 void
4917 AFSWaitOnQueuedFlushes( IN AFSFcb *Fcb)
4918 {
4919
4920     //
4921     // Block on the queue flush event
4922     //
4923
4924     KeWaitForSingleObject( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
4925                            Executive,
4926                            KernelMode,
4927                            FALSE,
4928                            NULL);
4929
4930     return;
4931 }
4932
4933 void
4934 AFSWaitOnQueuedReleases()
4935 {
4936
4937     AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
4938
4939     //
4940     // Block on the queue flush event
4941     //
4942
4943     KeWaitForSingleObject( &pRDRDeviceExt->Specific.RDR.QueuedReleaseExtentEvent,
4944                            Executive,
4945                            KernelMode,
4946                            FALSE,
4947                            NULL);
4948
4949     return;
4950 }
4951
4952 BOOLEAN
4953 AFSIsEqualFID( IN AFSFileID *FileId1,
4954                IN AFSFileID *FileId2)
4955 {
4956
4957     BOOLEAN bIsEqual = FALSE;
4958
4959     if( FileId1->Hash == FileId2->Hash &&
4960         FileId1->Unique == FileId2->Unique &&
4961         FileId1->Vnode == FileId2->Vnode &&
4962         FileId1->Volume == FileId2->Volume &&
4963         FileId1->Cell == FileId2->Cell)
4964     {
4965
4966         bIsEqual = TRUE;
4967     }
4968
4969     return bIsEqual;
4970 }
4971
4972 NTSTATUS
4973 AFSResetDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB)
4974 {
4975
4976     NTSTATUS ntStatus = STATUS_SUCCESS;
4977     AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
4978
4979     __Enter
4980     {
4981
4982         ASSERT( ExIsResourceAcquiredExclusiveLite( ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.TreeLock));
4983
4984         //
4985         // Reset the directory list information
4986         //
4987
4988         pCurrentDirEntry = ObjectInfoCB->Specific.Directory.DirectoryNodeListHead;
4989
4990         while( pCurrentDirEntry != NULL)
4991         {
4992
4993             pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
4994
4995             if( pCurrentDirEntry->DirOpenReferenceCount <= 0 &&
4996                 pCurrentDirEntry->NameArrayReferenceCount <= 0)
4997             {
4998
4999                 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
5000                               AFS_TRACE_LEVEL_VERBOSE,
5001                               "AFSResetDirectoryContent Deleting dir entry %p for %wZ\n",
5002                               pCurrentDirEntry,
5003                               &pCurrentDirEntry->NameInformation.FileName));
5004
5005                 AFSDeleteDirEntry( ObjectInfoCB,
5006                                    &pCurrentDirEntry);
5007             }
5008             else
5009             {
5010
5011                 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
5012                               AFS_TRACE_LEVEL_VERBOSE,
5013                               "AFSResetDirectoryContent Setting DELETE flag in dir entry %p for %wZ\n",
5014                               pCurrentDirEntry,
5015                               &pCurrentDirEntry->NameInformation.FileName));
5016
5017                 SetFlag( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
5018
5019                 AFSRemoveNameEntry( ObjectInfoCB,
5020                                     pCurrentDirEntry);
5021             }
5022
5023             pCurrentDirEntry = pNextDirEntry;
5024         }
5025
5026         ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = NULL;
5027
5028         ObjectInfoCB->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = NULL;
5029
5030         ObjectInfoCB->Specific.Directory.ShortNameTree = NULL;
5031
5032         ObjectInfoCB->Specific.Directory.DirectoryNodeListHead = NULL;
5033
5034         ObjectInfoCB->Specific.Directory.DirectoryNodeListTail = NULL;
5035
5036         ObjectInfoCB->Specific.Directory.DirectoryNodeCount = 0;
5037
5038         AFSDbgTrace(( AFS_SUBSYSTEM_DIR_NODE_COUNT,
5039                       AFS_TRACE_LEVEL_VERBOSE,
5040                       "AFSResetDirectoryContent Reset count to 0 on parent FID %08lX-%08lX-%08lX-%08lX\n",
5041                       ObjectInfoCB->FileId.Cell,
5042                       ObjectInfoCB->FileId.Volume,
5043                       ObjectInfoCB->FileId.Vnode,
5044                       ObjectInfoCB->FileId.Unique));
5045     }
5046
5047     return ntStatus;
5048 }
5049
5050 NTSTATUS
5051 AFSEnumerateGlobalRoot( IN GUID *AuthGroup)
5052 {
5053
5054     NTSTATUS ntStatus = STATUS_SUCCESS;
5055     AFSDirectoryCB *pDirGlobalDirNode = NULL;
5056     UNICODE_STRING uniFullName;
5057
5058     __Enter
5059     {
5060
5061         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
5062                       AFS_TRACE_LEVEL_VERBOSE,
5063                       "AFSEnumerateGlobalRoot Acquiring GlobalRoot DirectoryNodeHdr.TreeLock lock %p EXCL %08lX\n",
5064                       AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
5065                       PsGetCurrentThread()));
5066
5067         AFSAcquireExcl( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
5068                         TRUE);
5069
5070         if( BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
5071         {
5072
5073             try_return( ntStatus);
5074         }
5075
5076         //
5077         // Initialize the root information
5078         //
5079
5080         AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.ContentIndex = 1;
5081
5082         //
5083         // Enumerate the shares in the volume
5084         //
5085
5086         ntStatus = AFSEnumerateDirectory( AuthGroup,
5087                                           &AFSGlobalRoot->ObjectInformation,
5088                                           TRUE);
5089
5090         if( !NT_SUCCESS( ntStatus))
5091         {
5092
5093             try_return( ntStatus);
5094         }
5095
5096         pDirGlobalDirNode = AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeListHead;
5097
5098         uniFullName.MaximumLength = PAGE_SIZE;
5099         uniFullName.Length = 0;
5100
5101         uniFullName.Buffer = (WCHAR *)AFSLibExAllocatePoolWithTag( PagedPool,
5102                                                                    uniFullName.MaximumLength,
5103                                                                    AFS_GENERIC_MEMORY_12_TAG);
5104
5105         if( uniFullName.Buffer == NULL)
5106         {
5107
5108             //
5109             // Reset the directory content
5110             //
5111
5112             AFSResetDirectoryContent( &AFSGlobalRoot->ObjectInformation);
5113
5114             ClearFlag( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
5115
5116             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5117         }
5118
5119         //
5120         // Populate our list of entries in the NP enumeration list
5121         //
5122
5123         while( pDirGlobalDirNode != NULL)
5124         {
5125
5126             uniFullName.Buffer[ 0] = L'\\';
5127             uniFullName.Buffer[ 1] = L'\\';
5128
5129             uniFullName.Length = 2 * sizeof( WCHAR);
5130
5131             RtlCopyMemory( &uniFullName.Buffer[ 2],
5132                            AFSServerName.Buffer,
5133                            AFSServerName.Length);
5134
5135             uniFullName.Length += AFSServerName.Length;
5136
5137             uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)] = L'\\';
5138
5139             uniFullName.Length += sizeof( WCHAR);
5140
5141             RtlCopyMemory( &uniFullName.Buffer[ uniFullName.Length/sizeof( WCHAR)],
5142                            pDirGlobalDirNode->NameInformation.FileName.Buffer,
5143                            pDirGlobalDirNode->NameInformation.FileName.Length);
5144
5145             uniFullName.Length += pDirGlobalDirNode->NameInformation.FileName.Length;
5146
5147             AFSAddConnectionEx( &uniFullName,
5148                                 RESOURCEDISPLAYTYPE_SHARE,
5149                                 0);
5150
5151             pDirGlobalDirNode = (AFSDirectoryCB *)pDirGlobalDirNode->ListEntry.fLink;
5152         }
5153
5154         AFSLibExFreePoolWithTag( uniFullName.Buffer,
5155                                  AFS_GENERIC_MEMORY_12_TAG);
5156
5157 try_exit:
5158
5159         AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
5160     }
5161
5162     return ntStatus;
5163 }
5164
5165 BOOLEAN
5166 AFSIsRelativeName( IN UNICODE_STRING *Name)
5167 {
5168
5169     BOOLEAN bIsRelative = FALSE;
5170
5171     if( Name->Length > 0 &&
5172         Name->Buffer[ 0] != L'\\')
5173     {
5174
5175         bIsRelative = TRUE;
5176     }
5177
5178     return bIsRelative;
5179 }
5180
5181 BOOLEAN
5182 AFSIsAbsoluteAFSName( IN UNICODE_STRING *Name)
5183 {
5184     UNICODE_STRING uniTempName;
5185     BOOLEAN        bIsAbsolute = FALSE;
5186
5187     //
5188     // An absolute AFS path must begin with \afs\... or equivalent
5189     //
5190
5191     if ( Name->Length == 0 ||
5192          Name->Length <= AFSMountRootName.Length + sizeof( WCHAR) ||
5193          Name->Buffer[ 0] != L'\\' ||
5194          Name->Buffer[ AFSMountRootName.Length/sizeof( WCHAR)] != L'\\')
5195     {
5196
5197         return FALSE;
5198     }
5199
5200     uniTempName.Length = AFSMountRootName.Length;
5201     uniTempName.MaximumLength = AFSMountRootName.Length;
5202
5203     uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5204                                                             uniTempName.MaximumLength,
5205                                                             AFS_NAME_BUFFER_TWO_TAG);
5206
5207     if( uniTempName.Buffer == NULL)
5208     {
5209
5210         return FALSE;
5211     }
5212
5213     RtlCopyMemory( uniTempName.Buffer,
5214                    Name->Buffer,
5215                    AFSMountRootName.Length);
5216
5217     bIsAbsolute = (0 == RtlCompareUnicodeString( &uniTempName,
5218                                                  &AFSMountRootName,
5219                                                  TRUE));
5220
5221     AFSExFreePoolWithTag( uniTempName.Buffer,
5222                           AFS_NAME_BUFFER_TWO_TAG);
5223
5224     return bIsAbsolute;
5225 }
5226
5227
5228 void
5229 AFSUpdateName( IN UNICODE_STRING *Name)
5230 {
5231
5232     USHORT usIndex = 0;
5233
5234     while( usIndex < Name->Length/sizeof( WCHAR))
5235     {
5236
5237         if( Name->Buffer[ usIndex] == L'/')
5238         {
5239
5240             Name->Buffer[ usIndex] = L'\\';
5241         }
5242
5243         usIndex++;
5244     }
5245
5246     return;
5247 }
5248
5249 NTSTATUS
5250 AFSUpdateTargetName( IN OUT UNICODE_STRING *TargetName,
5251                      IN OUT ULONG *Flags,
5252                      IN WCHAR *NameBuffer,
5253                      IN USHORT NameLength)
5254 {
5255
5256     NTSTATUS ntStatus = STATUS_SUCCESS;
5257     WCHAR *pTmpBuffer = NULL;
5258
5259     __Enter
5260     {
5261
5262         //
5263         // If we have enough space then just move in the name otherwise
5264         // allocate a new buffer
5265         //
5266
5267         if( TargetName->Length < NameLength)
5268         {
5269
5270             pTmpBuffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5271                                                             NameLength,
5272                                                             AFS_NAME_BUFFER_FIVE_TAG);
5273
5274             if( pTmpBuffer == NULL)
5275             {
5276
5277                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5278             }
5279
5280             if( BooleanFlagOn( *Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER))
5281             {
5282
5283                 AFSExFreePoolWithTag( TargetName->Buffer, AFS_NAME_BUFFER_FIVE_TAG);
5284             }
5285
5286             TargetName->MaximumLength = NameLength;
5287
5288             TargetName->Buffer = pTmpBuffer;
5289
5290             SetFlag( *Flags, AFS_DIR_RELEASE_TARGET_NAME_BUFFER);
5291         }
5292
5293         TargetName->Length = NameLength;
5294
5295         RtlCopyMemory( TargetName->Buffer,
5296                        NameBuffer,
5297                        TargetName->Length);
5298
5299         //
5300         // Update the name in the buffer
5301         //
5302
5303         AFSUpdateName( TargetName);
5304
5305 try_exit:
5306
5307         NOTHING;
5308     }
5309
5310     return ntStatus;
5311 }
5312
5313 void
5314 AFSSetEnumerationEvent( IN AFSFcb *Fcb)
5315 {
5316     LONG lCount;
5317
5318     //
5319     // Depending on the type of node, set the event
5320     //
5321
5322     switch( Fcb->Header.NodeTypeCode)
5323     {
5324
5325         case AFS_DIRECTORY_FCB:
5326         case AFS_ROOT_FCB:
5327         case AFS_ROOT_ALL:
5328         {
5329
5330             lCount = InterlockedIncrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
5331
5332             break;
5333         }
5334     }
5335
5336     return;
5337 }
5338
5339 void
5340 AFSClearEnumerationEvent( IN AFSFcb *Fcb)
5341 {
5342
5343     LONG lCount;
5344
5345     //
5346     // Depending on the type of node, set the event
5347     //
5348
5349     switch( Fcb->Header.NodeTypeCode)
5350     {
5351
5352         case AFS_DIRECTORY_FCB:
5353         case AFS_ROOT_FCB:
5354         case AFS_ROOT_ALL:
5355         {
5356
5357             ASSERT( Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0);
5358
5359             lCount = InterlockedDecrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
5360
5361             break;
5362         }
5363     }
5364
5365     return;
5366 }
5367
5368 BOOLEAN
5369 AFSIsEnumerationInProcess( IN AFSObjectInfoCB *ObjectInfo)
5370 {
5371
5372     BOOLEAN bIsInProcess = FALSE;
5373
5374     __Enter
5375     {
5376
5377         if( ObjectInfo->Fcb == NULL)
5378         {
5379
5380             try_return( bIsInProcess);
5381         }
5382
5383         switch( ObjectInfo->Fcb->Header.NodeTypeCode)
5384         {
5385
5386             case AFS_DIRECTORY_FCB:
5387             case AFS_ROOT_FCB:
5388             case AFS_ROOT_ALL:
5389             {
5390
5391                 if( ObjectInfo->Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0)
5392                 {
5393
5394                     bIsInProcess = TRUE;
5395                 }
5396
5397                 break;
5398             }
5399         }
5400
5401 try_exit:
5402
5403         NOTHING;
5404     }
5405
5406     return bIsInProcess;
5407 }
5408
5409 NTSTATUS
5410 AFSVerifyVolume( IN ULONGLONG ProcessId,
5411                  IN AFSVolumeCB *VolumeCB)
5412 {
5413
5414     UNREFERENCED_PARAMETER(ProcessId);
5415     UNREFERENCED_PARAMETER(VolumeCB);
5416     NTSTATUS ntStatus = STATUS_SUCCESS;
5417
5418
5419     return ntStatus;
5420 }
5421
5422 NTSTATUS
5423 AFSInitPIOCtlDirectoryCB( IN AFSObjectInfoCB *ParentObjectInfo)
5424 {
5425
5426     NTSTATUS ntStatus = STATUS_SUCCESS;
5427     AFSObjectInfoCB *pObjectInfoCB = NULL;
5428     AFSDirectoryCB *pDirNode = NULL;
5429     ULONG ulEntryLength = 0;
5430     AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
5431     LONG lCount;
5432
5433     __Enter
5434     {
5435
5436         AFSAcquireExcl( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
5437                         TRUE);
5438
5439         pObjectInfoCB = AFSAllocateObjectInfo( ParentObjectInfo,
5440                                                0);
5441
5442         if( pObjectInfoCB == NULL)
5443         {
5444
5445             AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
5446
5447             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5448         }
5449
5450         lCount = AFSObjectInfoIncrement( pObjectInfoCB,
5451                                          AFS_OBJECT_REFERENCE_PIOCTL);
5452
5453         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
5454                       AFS_TRACE_LEVEL_VERBOSE,
5455                       "AFSInitPIOCtlDirectoryCB Increment count on object %p Cnt %d\n",
5456                       pObjectInfoCB,
5457                       lCount));
5458
5459         AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
5460
5461         pObjectInfoCB->FileType = (ULONG) AFS_FILE_TYPE_PIOCTL;
5462
5463         pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
5464
5465         ulEntryLength = sizeof( AFSDirectoryCB) + AFSPIOCtlName.Length;
5466
5467         pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
5468                                                                ulEntryLength,
5469                                                                AFS_DIR_ENTRY_TAG);
5470
5471         if( pDirNode == NULL)
5472         {
5473
5474             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5475         }
5476
5477         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
5478                       AFS_TRACE_LEVEL_VERBOSE,
5479                       "AFSInitPIOCtlDirectoryCB AFS_DIR_ENTRY_TAG allocated %p\n",
5480                       pDirNode));
5481
5482         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
5483                                                                                 sizeof( AFSNonPagedDirectoryCB),
5484                                                                                 AFS_DIR_ENTRY_NP_TAG);
5485
5486         if( pNonPagedDirEntry == NULL)
5487         {
5488
5489             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5490         }
5491
5492         RtlZeroMemory( pDirNode,
5493                        ulEntryLength);
5494
5495         RtlZeroMemory( pNonPagedDirEntry,
5496                        sizeof( AFSNonPagedDirectoryCB));
5497
5498         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
5499
5500         pDirNode->NonPaged = pNonPagedDirEntry;
5501
5502         pDirNode->ObjectInformation = pObjectInfoCB;
5503
5504         pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_PIOCTL_INDEX;
5505
5506         //
5507         // Set valid entry
5508         //
5509
5510         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_FAKE);
5511
5512         pDirNode->NameInformation.FileName.Length = AFSPIOCtlName.Length;
5513
5514         pDirNode->NameInformation.FileName.MaximumLength = AFSPIOCtlName.Length;
5515
5516         pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
5517
5518         RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
5519                        AFSPIOCtlName.Buffer,
5520                        pDirNode->NameInformation.FileName.Length);
5521
5522         pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
5523                                                                        TRUE);
5524
5525         if ( InterlockedCompareExchangePointer( (PVOID *)&ParentObjectInfo->Specific.Directory.PIOCtlDirectoryCB, pDirNode, NULL) != NULL)
5526         {
5527
5528             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5529                           AFS_TRACE_LEVEL_WARNING,
5530                           "AFSInitPIOCtlDirectoryCB Raced PIOCtlDirectoryCB %p pFcb %p\n",
5531                           ParentObjectInfo->Specific.Directory.PIOCtlDirectoryCB,
5532                           pDirNode));
5533
5534             try_return( ntStatus = STATUS_REPARSE);
5535         }
5536
5537 try_exit:
5538
5539         if ( ntStatus != STATUS_SUCCESS)
5540         {
5541
5542             if ( pDirNode != NULL)
5543             {
5544
5545                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
5546                               AFS_TRACE_LEVEL_VERBOSE,
5547                               "AFSInitPIOCtlDirectoryCB AFS_DIR_ENTRY_TAG deallocating %p\n",
5548                               pDirNode));
5549
5550                 AFSExFreePoolWithTag( pDirNode, AFS_DIR_ENTRY_TAG);
5551             }
5552
5553             if( pNonPagedDirEntry != NULL)
5554             {
5555
5556                 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
5557
5558                 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
5559             }
5560
5561             if ( pObjectInfoCB != NULL)
5562             {
5563
5564                 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
5565                                                  AFS_OBJECT_REFERENCE_PIOCTL);
5566
5567                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
5568                               AFS_TRACE_LEVEL_VERBOSE,
5569                               "AFSInitPIOCtlDirectoryCB Decrement count on object %p Cnt %d\n",
5570                               pObjectInfoCB,
5571                               lCount));
5572
5573                 if ( lCount == 0)
5574                 {
5575
5576                     AFSDeleteObjectInfo( &pObjectInfoCB);
5577                 }
5578             }
5579         }
5580     }
5581
5582     return ntStatus;
5583 }
5584
5585 NTSTATUS
5586 AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB,
5587                            IN AFSDirectoryCB *DirectoryCB,
5588                            IN UNICODE_STRING *ParentPathName,
5589                            IN AFSNameArrayHdr *RelatedNameArray,
5590                            IN GUID           *AuthGroup,
5591                            OUT AFSFileInfoCB *FileInfo)
5592 {
5593
5594     NTSTATUS ntStatus = STATUS_SUCCESS;
5595     AFSDirEnumEntry *pDirEntry = NULL;
5596     UNICODE_STRING uniFullPathName = {0};
5597     AFSNameArrayHdr    *pNameArray = NULL;
5598     AFSVolumeCB *pVolumeCB = NULL;
5599     LONG VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
5600     AFSVolumeCB *pNewVolumeCB = NULL;
5601     LONG NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
5602     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
5603     AFSDirectoryCB *pNewParentDirEntry = NULL;
5604     WCHAR *pwchBuffer = NULL;
5605     UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
5606     ULONG ulNameDifference = 0;
5607     LONG lCount;
5608
5609     __Enter
5610     {
5611
5612         //
5613         // Retrieve a target name for the entry
5614         //
5615
5616         AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
5617                           TRUE);
5618
5619         if( DirectoryCB->NameInformation.TargetName.Length == 0)
5620         {
5621
5622             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5623
5624             ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
5625                                               AuthGroup,
5626                                               FALSE,
5627                                               &pDirEntry);
5628
5629             if( !NT_SUCCESS( ntStatus) ||
5630                 pDirEntry->TargetNameLength == 0)
5631             {
5632
5633                 if( pDirEntry != NULL)
5634                 {
5635
5636                     ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
5637                 }
5638
5639                 try_return( ntStatus);
5640             }
5641
5642             AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
5643                             TRUE);
5644
5645             if( DirectoryCB->NameInformation.TargetName.Length == 0)
5646             {
5647
5648                 //
5649                 // Update the target name
5650                 //
5651
5652                 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
5653                                                 &DirectoryCB->Flags,
5654                                                 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
5655                                                 (USHORT)pDirEntry->TargetNameLength);
5656
5657                 if( !NT_SUCCESS( ntStatus))
5658                 {
5659
5660                     AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5661
5662                     try_return( ntStatus);
5663                 }
5664             }
5665
5666             AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
5667         }
5668
5669         //
5670         // Need to pass the full path in for parsing.
5671         //
5672
5673         if( AFSIsRelativeName( &DirectoryCB->NameInformation.TargetName))
5674         {
5675
5676             uniFullPathName.Length = 0;
5677             uniFullPathName.MaximumLength = ParentPathName->Length +
5678                                                     sizeof( WCHAR) +
5679                                                     DirectoryCB->NameInformation.TargetName.Length;
5680
5681             uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5682                                                                         uniFullPathName.MaximumLength,
5683                                                                         AFS_NAME_BUFFER_SIX_TAG);
5684
5685             if( uniFullPathName.Buffer == NULL)
5686             {
5687
5688                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5689
5690                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5691             }
5692
5693             pwchBuffer = uniFullPathName.Buffer;
5694
5695             RtlZeroMemory( uniFullPathName.Buffer,
5696                            uniFullPathName.MaximumLength);
5697
5698             RtlCopyMemory( uniFullPathName.Buffer,
5699                            ParentPathName->Buffer,
5700                            ParentPathName->Length);
5701
5702             uniFullPathName.Length = ParentPathName->Length;
5703
5704             if( uniFullPathName.Buffer[ (uniFullPathName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
5705                 DirectoryCB->NameInformation.TargetName.Buffer[ 0] != L'\\')
5706             {
5707
5708                 uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)] = L'\\';
5709
5710                 uniFullPathName.Length += sizeof( WCHAR);
5711             }
5712
5713             RtlCopyMemory( &uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)],
5714                            DirectoryCB->NameInformation.TargetName.Buffer,
5715                            DirectoryCB->NameInformation.TargetName.Length);
5716
5717             uniFullPathName.Length += DirectoryCB->NameInformation.TargetName.Length;
5718
5719             uniParsedName.Length = uniFullPathName.Length - ParentPathName->Length;
5720             uniParsedName.MaximumLength = uniParsedName.Length;
5721
5722             uniParsedName.Buffer = &uniFullPathName.Buffer[ ParentPathName->Length/sizeof( WCHAR)];
5723
5724             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5725
5726             //
5727             // We populate up to the current parent
5728             //
5729
5730             if( RelatedNameArray != NULL)
5731             {
5732
5733                 pNameArray = AFSInitNameArray( NULL,
5734                                                RelatedNameArray->MaxElementCount);
5735
5736                 if( pNameArray == NULL)
5737                 {
5738
5739                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5740                 }
5741
5742                 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
5743                                                                  RelatedNameArray,
5744                                                                  ParentDirectoryCB);
5745             }
5746             else
5747             {
5748
5749                 pNameArray = AFSInitNameArray( NULL,
5750                                                0);
5751
5752                 if( pNameArray == NULL)
5753                 {
5754
5755                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5756                 }
5757
5758                 ntStatus = AFSPopulateNameArray( pNameArray,
5759                                                  NULL,
5760                                                  ParentDirectoryCB);
5761             }
5762
5763             if( !NT_SUCCESS( ntStatus))
5764             {
5765
5766                 try_return( ntStatus);
5767             }
5768
5769             pVolumeCB = ParentDirectoryCB->ObjectInformation->VolumeCB;
5770
5771             pParentDirEntry = ParentDirectoryCB;
5772         }
5773         else
5774         {
5775
5776             uniFullPathName.Length = 0;
5777             uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
5778
5779             uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5780                                                                         uniFullPathName.MaximumLength,
5781                                                                         AFS_NAME_BUFFER_SEVEN_TAG);
5782
5783             if( uniFullPathName.Buffer == NULL)
5784             {
5785
5786                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5787
5788                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5789             }
5790
5791             pwchBuffer = uniFullPathName.Buffer;
5792
5793             RtlZeroMemory( uniFullPathName.Buffer,
5794                            uniFullPathName.MaximumLength);
5795
5796             RtlCopyMemory( uniFullPathName.Buffer,
5797                            DirectoryCB->NameInformation.TargetName.Buffer,
5798                            DirectoryCB->NameInformation.TargetName.Length);
5799
5800             uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
5801
5802             //
5803             // This name should begin with the \afs server so parse it off and check it
5804             //
5805
5806             FsRtlDissectName( uniFullPathName,
5807                               &uniComponentName,
5808                               &uniRemainingPath);
5809
5810             if( RtlCompareUnicodeString( &uniComponentName,
5811                                          &AFSServerName,
5812                                          TRUE) != 0)
5813             {
5814
5815                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5816
5817                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5818                               AFS_TRACE_LEVEL_ERROR,
5819                               "AFSRetrieveFileAttributes Name %wZ contains invalid server name\n",
5820                               &uniFullPathName));
5821
5822                 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
5823             }
5824
5825             uniFullPathName = uniRemainingPath;
5826
5827             uniParsedName = uniFullPathName;
5828
5829             ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
5830
5831             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5832
5833             //
5834             // Our name array
5835             //
5836
5837             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
5838                                            0);
5839
5840             if( pNameArray == NULL)
5841             {
5842
5843                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5844             }
5845
5846             pVolumeCB = AFSGlobalRoot;
5847
5848             pParentDirEntry = AFSGlobalRoot->DirectoryCB;
5849         }
5850
5851         //
5852         // Increment the ref count on the volume and dir entry for correct processing below
5853         //
5854
5855         VolumeReferenceReason = AFS_VOLUME_REFERENCE_FILE_ATTRS;
5856
5857         lCount = AFSVolumeIncrement( pVolumeCB,
5858                                      VolumeReferenceReason);
5859
5860         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
5861                       AFS_TRACE_LEVEL_VERBOSE,
5862                       "AFSRetrieveFileAttributes Increment count on volume %p Reason %u Cnt %d\n",
5863                       pVolumeCB,
5864                       VolumeReferenceReason,
5865                       lCount));
5866
5867         lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
5868
5869         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5870                       AFS_TRACE_LEVEL_VERBOSE,
5871                       "AFSRetrieveFileAttributes Increment count on %wZ DE %p Ccb %p Cnt %d\n",
5872                       &pParentDirEntry->NameInformation.FileName,
5873                       pParentDirEntry,
5874                       NULL,
5875                       lCount));
5876
5877         ntStatus = AFSLocateNameEntry( NULL,
5878                                        NULL,
5879                                        &uniFullPathName,
5880                                        &uniParsedName,
5881                                        pNameArray,
5882                                        AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL,
5883                                        pVolumeCB,
5884                                        pParentDirEntry,
5885                                        &pNewVolumeCB,
5886                                        &NewVolumeReferenceReason,
5887                                        &pNewParentDirEntry,
5888                                        &pDirectoryEntry,
5889                                        NULL);
5890
5891         if ( pNewVolumeCB != NULL)
5892         {
5893             //
5894             // AFSLocateNameEntry returns pNewVolumeCB with a reference held
5895             // even if pVolumeCB == pNewVolumeCB.  It is always safe to release
5896             // the reference on pVolumeCB that was held prior to the call.
5897             // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
5898             // will be released second.
5899             //
5900
5901             lCount = AFSVolumeDecrement( pVolumeCB,
5902                                          VolumeReferenceReason);
5903
5904             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
5905                           AFS_TRACE_LEVEL_VERBOSE,
5906                           "AFSRetrieveFileAttributes Decrement count on volume %p Reason %u Cnt %d\n",
5907                           pVolumeCB,
5908                           VolumeReferenceReason,
5909                           lCount));
5910
5911             pVolumeCB = pNewVolumeCB;
5912
5913             pNewVolumeCB = NULL;
5914
5915             VolumeReferenceReason = NewVolumeReferenceReason;
5916
5917             NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
5918         }
5919
5920         //
5921         // AFSLocateNameEntry does not alter the reference count of
5922         // pParentDirectoryCB and it returns pNewParentDirectoryCB with
5923         // a reference held.
5924         //
5925
5926         lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
5927
5928         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5929                       AFS_TRACE_LEVEL_VERBOSE,
5930                       "AFSRetrieveFileAttributes DecrementX count on %wZ DE %p Cnt %d\n",
5931                       &pParentDirEntry->NameInformation.FileName,
5932                       pParentDirEntry,
5933                       lCount));
5934
5935         pParentDirEntry = pNewParentDirEntry;
5936
5937         pNewParentDirEntry = NULL;
5938
5939         if( !NT_SUCCESS( ntStatus) ||
5940             ntStatus == STATUS_REPARSE)
5941         {
5942
5943             try_return( ntStatus);
5944         }
5945
5946         //
5947         // Store off the information
5948         //
5949
5950         FileInfo->FileAttributes = pDirectoryEntry->ObjectInformation->FileAttributes;
5951
5952         //
5953         // Check for the mount point being returned
5954         //
5955
5956         if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
5957             pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DFSLINK)
5958         {
5959
5960             FileInfo->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
5961         }
5962         else if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
5963         {
5964
5965             if ( FileInfo->FileAttributes == FILE_ATTRIBUTE_NORMAL)
5966             {
5967
5968                 FileInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
5969             }
5970             else
5971             {
5972
5973                 FileInfo->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
5974             }
5975         }
5976
5977         FileInfo->AllocationSize = pDirectoryEntry->ObjectInformation->AllocationSize;
5978
5979         FileInfo->EndOfFile = pDirectoryEntry->ObjectInformation->EndOfFile;
5980
5981         FileInfo->CreationTime = pDirectoryEntry->ObjectInformation->CreationTime;
5982
5983         FileInfo->LastAccessTime = pDirectoryEntry->ObjectInformation->LastAccessTime;
5984
5985         FileInfo->LastWriteTime = pDirectoryEntry->ObjectInformation->LastWriteTime;
5986
5987         FileInfo->ChangeTime = pDirectoryEntry->ObjectInformation->ChangeTime;
5988
5989 try_exit:
5990
5991         if( pDirEntry != NULL)
5992         {
5993
5994             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
5995         }
5996
5997         if( pDirectoryEntry != NULL)
5998         {
5999
6000             lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
6001
6002             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6003                           AFS_TRACE_LEVEL_VERBOSE,
6004                           "AFSRetrieveFileAttributes Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6005                           &pDirectoryEntry->NameInformation.FileName,
6006                           pDirectoryEntry,
6007                           NULL,
6008                           lCount));
6009
6010             ASSERT( lCount >= 0);
6011         }
6012
6013         if ( pParentDirEntry != NULL)
6014         {
6015
6016             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
6017
6018             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6019                           AFS_TRACE_LEVEL_VERBOSE,
6020                           "AFSRetrieveFileAttributes Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
6021                           &pParentDirEntry->NameInformation.FileName,
6022                           pParentDirEntry,
6023                           NULL,
6024                           lCount));
6025
6026             ASSERT( lCount >= 0);
6027         }
6028
6029         if( pVolumeCB != NULL)
6030         {
6031
6032             lCount = AFSVolumeDecrement( pVolumeCB,
6033                                          VolumeReferenceReason);
6034
6035             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6036                           AFS_TRACE_LEVEL_VERBOSE,
6037                           "AFSRetrieveFileAttributes Decrement2 count on volume %p Reason %u Cnt %d\n",
6038                           pVolumeCB,
6039                           VolumeReferenceReason,
6040                           lCount));
6041         }
6042
6043         if( pNameArray != NULL)
6044         {
6045
6046             AFSFreeNameArray( pNameArray);
6047         }
6048
6049         if( pwchBuffer != NULL)
6050         {
6051
6052             //
6053             // Always free the buffer that we allocated as AFSLocateNameEntry
6054             // will not free it.  If uniFullPathName.Buffer was allocated by
6055             // AFSLocateNameEntry, then we must free that as well.
6056             // Check that the uniFullPathName.Buffer in the string is not the same
6057             // offset by the length of the server name
6058             //
6059
6060             if( uniFullPathName.Length > 0 &&
6061                 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
6062             {
6063
6064                 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
6065             }
6066
6067             AFSExFreePoolWithTag( pwchBuffer, 0);
6068         }
6069     }
6070
6071     return ntStatus;
6072 }
6073
6074 AFSObjectInfoCB *
6075 AFSAllocateObjectInfo( IN AFSObjectInfoCB *ParentObjectInfo,
6076                        IN ULONGLONG HashIndex)
6077 {
6078
6079     NTSTATUS ntStatus = STATUS_SUCCESS;
6080     AFSObjectInfoCB *pObjectInfo = NULL;
6081     LONG lCount;
6082
6083     __Enter
6084     {
6085
6086         pObjectInfo = (AFSObjectInfoCB *)AFSExAllocatePoolWithTag( PagedPool,
6087                                                                    sizeof( AFSObjectInfoCB),
6088                                                                    AFS_OBJECT_INFO_TAG);
6089
6090         if( pObjectInfo == NULL)
6091         {
6092
6093             try_return( pObjectInfo);
6094         }
6095
6096         RtlZeroMemory( pObjectInfo,
6097                        sizeof( AFSObjectInfoCB));
6098
6099         pObjectInfo->NonPagedInfo = (AFSNonPagedObjectInfoCB *)AFSExAllocatePoolWithTag( NonPagedPool,
6100                                                                                          sizeof( AFSNonPagedObjectInfoCB),
6101                                                                                          AFS_NP_OBJECT_INFO_TAG);
6102
6103         if( pObjectInfo->NonPagedInfo == NULL)
6104         {
6105
6106             AFSExFreePoolWithTag( pObjectInfo, AFS_OBJECT_INFO_TAG);
6107
6108             try_return( pObjectInfo = NULL);
6109         }
6110
6111         ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6112
6113         ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
6114
6115         pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock = &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock;
6116
6117         if( ParentObjectInfo != NULL)
6118         {
6119
6120             pObjectInfo->VolumeCB = ParentObjectInfo->VolumeCB;
6121
6122             pObjectInfo->ParentFileId = ParentObjectInfo->FileId;
6123
6124             SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID);
6125
6126             AFSAcquireShared( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
6127                               TRUE);
6128
6129             lCount = AFSObjectInfoIncrement( ParentObjectInfo,
6130                                              AFS_OBJECT_REFERENCE_CHILD);
6131
6132             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
6133                           AFS_TRACE_LEVEL_VERBOSE,
6134                           "AFSAllocateObjectInfo Increment count on parent object %p Cnt %d\n",
6135                           ParentObjectInfo,
6136                           lCount));
6137
6138             AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
6139         }
6140
6141         //
6142         // Initialize the access time
6143         //
6144
6145         KeQueryTickCount( &pObjectInfo->LastAccessCount);
6146
6147         if( HashIndex != 0)
6148         {
6149
6150             ASSERT( ParentObjectInfo);
6151
6152             //
6153             // Insert the entry into the object tree and list
6154             //
6155
6156             pObjectInfo->TreeEntry.HashIndex = HashIndex;
6157
6158             if( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead == NULL)
6159             {
6160
6161                 ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead = &pObjectInfo->TreeEntry;
6162             }
6163             else
6164             {
6165
6166                 ntStatus = AFSInsertHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
6167                                                &pObjectInfo->TreeEntry);
6168
6169                 ASSERT( NT_SUCCESS( ntStatus));
6170             }
6171
6172             //
6173             // And the object list in the volume
6174             //
6175
6176             if( ParentObjectInfo->VolumeCB->ObjectInfoListHead == NULL)
6177             {
6178
6179                 ParentObjectInfo->VolumeCB->ObjectInfoListHead = pObjectInfo;
6180             }
6181             else
6182             {
6183
6184                 ParentObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = (void *)pObjectInfo;
6185
6186                 pObjectInfo->ListEntry.bLink = (void *)ParentObjectInfo->VolumeCB->ObjectInfoListTail;
6187             }
6188
6189             ParentObjectInfo->VolumeCB->ObjectInfoListTail = pObjectInfo;
6190
6191             //
6192             // Indicate the object is in the hash tree and linked list in the volume
6193             //
6194
6195             SetFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE | AFS_OBJECT_INSERTED_VOLUME_LIST);
6196         }
6197
6198 try_exit:
6199
6200         NOTHING;
6201     }
6202
6203     return pObjectInfo;
6204 }
6205
6206 LONG
6207 AFSObjectInfoIncrement( IN AFSObjectInfoCB *ObjectInfo,
6208                         IN LONG Reason)
6209 {
6210
6211     LONG lCount;
6212
6213     if ( ObjectInfo->ObjectReferenceCount == 0)
6214     {
6215
6216         AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6217                         TRUE);
6218
6219         lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6220     }
6221     else
6222     {
6223
6224         AFSAcquireShared( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6225                           TRUE);
6226
6227         lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6228
6229         if ( lCount == 1)
6230         {
6231
6232             AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6233
6234             AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6235                             TRUE);
6236         }
6237     }
6238
6239     InterlockedIncrement( &ObjectInfo->ObjectReferences[ Reason]);
6240
6241     AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6242
6243     return lCount;
6244 }
6245
6246 LONG
6247 AFSObjectInfoDecrement( IN AFSObjectInfoCB *ObjectInfo,
6248                         IN LONG Reason)
6249 {
6250
6251     LONG lCount, lCount2;
6252
6253     AFSAcquireShared( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6254                       TRUE);
6255
6256     lCount = InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);
6257
6258     if ( lCount == 0)
6259     {
6260
6261         lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6262
6263         AFSReleaseResource(&ObjectInfo->NonPagedInfo->ObjectInfoLock);
6264
6265         AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6266                         TRUE);
6267
6268         lCount = InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);
6269     }
6270
6271     lCount2 = InterlockedDecrement( &ObjectInfo->ObjectReferences[ Reason]);
6272
6273     ASSERT( lCount2 >= 0);
6274
6275     AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6276
6277     return lCount;
6278 }
6279
6280 AFSObjectInfoCB *
6281 AFSFindObjectInfo( IN AFSVolumeCB *VolumeCB,
6282                    IN AFSFileID   *FileId,
6283                    IN BOOLEAN      bUpdateLastUse)
6284 {
6285     DWORD            ntStatus = STATUS_SUCCESS;
6286     ULONGLONG        ullIndex;
6287     AFSObjectInfoCB *pObjectInfo = NULL;
6288     LONG             lCount;
6289
6290     ullIndex = AFSCreateLowIndex( FileId);
6291
6292     AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
6293                       TRUE);
6294
6295     if ( AFSIsEqualFID( &VolumeCB->ObjectInformation.FileId, FileId))
6296     {
6297
6298         pObjectInfo = &VolumeCB->ObjectInformation;
6299     }
6300     else
6301     {
6302
6303         ntStatus = AFSLocateHashEntry( VolumeCB->ObjectInfoTree.TreeHead,
6304                                        ullIndex,
6305                                        (AFSBTreeEntry **)&pObjectInfo);
6306     }
6307
6308     if ( NT_SUCCESS( ntStatus)) {
6309
6310         lCount = AFSObjectInfoIncrement( pObjectInfo,
6311                                          AFS_OBJECT_REFERENCE_FIND);
6312
6313         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
6314                       AFS_TRACE_LEVEL_VERBOSE,
6315                       "AFSFindObjectInfo Decrement count on object %p Cnt %d\n",
6316                       pObjectInfo,
6317                       lCount));
6318
6319         if ( bUpdateLastUse)
6320         {
6321
6322             KeQueryTickCount( &pObjectInfo->LastAccessCount);
6323         }
6324     }
6325
6326     AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
6327
6328     return pObjectInfo;
6329 }
6330
6331 void
6332 AFSReleaseObjectInfo( IN AFSObjectInfoCB **ppObjectInfo)
6333 {
6334     LONG lCount;
6335
6336     lCount = AFSObjectInfoDecrement( *ppObjectInfo,
6337                                      AFS_OBJECT_REFERENCE_FIND);
6338
6339     AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
6340                   AFS_TRACE_LEVEL_VERBOSE,
6341                   "AFSReleaseObjectInfo Decrement count on object %p Cnt %d\n",
6342                   *ppObjectInfo,
6343                   lCount));
6344
6345     *ppObjectInfo = NULL;
6346 }
6347
6348 void
6349 AFSDeleteObjectInfo( IN AFSObjectInfoCB **ppObjectInfo)
6350 {
6351     BOOLEAN bAcquiredTreeLock = FALSE;
6352     AFSObjectInfoCB *pObjectInfo = NULL;
6353     AFSVolumeCB * pVolume = NULL;
6354     BOOLEAN bHeldInService;
6355     AFSObjectInfoCB * pParentObjectInfo = NULL;
6356     AFSFileID FileId;
6357     LONG lCount;
6358
6359     __Enter
6360     {
6361         if ( BooleanFlagOn( (*ppObjectInfo)->Flags, AFS_OBJECT_ROOT_VOLUME))
6362         {
6363
6364             //
6365             // AFSDeleteObjectInfo should never be called on the ObjectInformationCB
6366             // embedded in the VolumeCB.
6367             //
6368
6369             ASSERT( FALSE);
6370
6371             return;
6372         }
6373
6374         pVolume = (*ppObjectInfo)->VolumeCB;
6375
6376         if( !ExIsResourceAcquiredExclusiveLite( pVolume->ObjectInfoTree.TreeLock))
6377         {
6378
6379             ASSERT( !ExIsResourceAcquiredLite( pVolume->ObjectInfoTree.TreeLock));
6380
6381             AFSAcquireExcl( pVolume->ObjectInfoTree.TreeLock,
6382                             TRUE);
6383
6384             bAcquiredTreeLock = TRUE;
6385         }
6386
6387         for ( lCount = 0; lCount < AFS_OBJECT_REFERENCE_MAX; lCount++)
6388         {
6389
6390             ASSERT( (*ppObjectInfo)->ObjectReferences[ lCount] >= 0);
6391         }
6392
6393         ASSERT( (*ppObjectInfo)->ObjectReferenceCount == 0);
6394
6395         pObjectInfo = (AFSObjectInfoCB *) InterlockedCompareExchangePointer( (PVOID *)ppObjectInfo,
6396                                                                              NULL,
6397                                                                              *ppObjectInfo);
6398
6399         if ( pObjectInfo == NULL)
6400         {
6401
6402             try_return( NOTHING);
6403         }
6404
6405         ASSERT( *ppObjectInfo == NULL);
6406
6407         if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
6408         {
6409
6410             pParentObjectInfo = AFSFindObjectInfo( pVolume,
6411                                                    &pObjectInfo->ParentFileId,
6412                                                    FALSE);
6413
6414             if( pParentObjectInfo != NULL)
6415             {
6416
6417                 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID);
6418
6419                 AFSAcquireShared( pParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
6420                                   TRUE);
6421
6422                 lCount = AFSObjectInfoDecrement( pParentObjectInfo,
6423                                                  AFS_OBJECT_REFERENCE_CHILD);
6424
6425                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
6426                               AFS_TRACE_LEVEL_VERBOSE,
6427                               "AFSDeleteObjectInfo Decrement count on parent object %p Cnt %d\n",
6428                               pParentObjectInfo,
6429                               lCount));
6430
6431                 AFSReleaseResource( pParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
6432
6433                 AFSReleaseObjectInfo( &pParentObjectInfo);
6434             }
6435         }
6436
6437         //
6438         // Remove it from the tree and list if it was inserted
6439         //
6440
6441         if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
6442         {
6443
6444             AFSRemoveHashEntry( &pVolume->ObjectInfoTree.TreeHead,
6445                                 &pObjectInfo->TreeEntry);
6446         }
6447
6448         if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_VOLUME_LIST))
6449         {
6450
6451             if( pObjectInfo->ListEntry.fLink == NULL)
6452             {
6453
6454                 pVolume->ObjectInfoListTail = (AFSObjectInfoCB *)pObjectInfo->ListEntry.bLink;
6455
6456                 if( pVolume->ObjectInfoListTail != NULL)
6457                 {
6458
6459                     pVolume->ObjectInfoListTail->ListEntry.fLink = NULL;
6460                 }
6461             }
6462             else
6463             {
6464
6465                 ((AFSObjectInfoCB *)(pObjectInfo->ListEntry.fLink))->ListEntry.bLink = pObjectInfo->ListEntry.bLink;
6466             }
6467
6468             if( pObjectInfo->ListEntry.bLink == NULL)
6469             {
6470
6471                 pVolume->ObjectInfoListHead = (AFSObjectInfoCB *)pObjectInfo->ListEntry.fLink;
6472
6473                 if( pVolume->ObjectInfoListHead != NULL)
6474                 {
6475
6476                     pVolume->ObjectInfoListHead->ListEntry.bLink = NULL;
6477                 }
6478             }
6479             else
6480             {
6481
6482                 ((AFSObjectInfoCB *)(pObjectInfo->ListEntry.bLink))->ListEntry.fLink = pObjectInfo->ListEntry.fLink;
6483             }
6484         }
6485
6486         bHeldInService = BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_HELD_IN_SERVICE);
6487
6488         if( bHeldInService)
6489         {
6490
6491             FileId = pObjectInfo->FileId;
6492         }
6493
6494         ASSERT( pObjectInfo->ObjectReferenceCount == 0);
6495
6496         ExDeleteResourceLite( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
6497
6498         ExDeleteResourceLite( &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6499
6500         AFSExFreePoolWithTag( pObjectInfo->NonPagedInfo, AFS_NP_OBJECT_INFO_TAG);
6501
6502         AFSExFreePoolWithTag( pObjectInfo, AFS_OBJECT_INFO_TAG);
6503
6504 try_exit:
6505
6506         if( bAcquiredTreeLock)
6507         {
6508
6509             AFSReleaseResource( pVolume->ObjectInfoTree.TreeLock);
6510         }
6511
6512         //
6513         // Release the fid in the service
6514         //
6515
6516         if( bHeldInService)
6517         {
6518
6519             AFSReleaseFid( &FileId);
6520         }
6521     }
6522
6523     return;
6524 }
6525
6526 NTSTATUS
6527 AFSEvaluateRootEntry( IN AFSDirectoryCB *DirectoryCB,
6528                       OUT AFSDirectoryCB **TargetDirEntry)
6529 {
6530
6531     NTSTATUS ntStatus = STATUS_SUCCESS;
6532     AFSDirEnumEntry *pDirEntry = NULL;
6533     UNICODE_STRING uniFullPathName = {0};
6534     AFSNameArrayHdr    *pNameArray = NULL;
6535     AFSVolumeCB *pVolumeCB = NULL;
6536     LONG VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
6537     AFSVolumeCB *pNewVolumeCB = NULL;
6538     LONG NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
6539     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
6540     AFSDirectoryCB *pNewParentDirEntry = NULL;
6541     WCHAR *pwchBuffer = NULL;
6542     UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
6543     ULONG ulNameDifference = 0;
6544     GUID    stAuthGroup;
6545     LONG lCount;
6546
6547     __Enter
6548     {
6549
6550         ntStatus = AFSRetrieveValidAuthGroup( NULL,
6551                                               DirectoryCB->ObjectInformation,
6552                                               FALSE,
6553                                               &stAuthGroup);
6554
6555         if( !NT_SUCCESS( ntStatus))
6556         {
6557             try_return( ntStatus);
6558         }
6559
6560         //
6561         // Retrieve a target name for the entry
6562         //
6563
6564         AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
6565                           TRUE);
6566
6567         if( DirectoryCB->NameInformation.TargetName.Length == 0)
6568         {
6569
6570             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6571
6572             ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
6573                                               &stAuthGroup,
6574                                               FALSE,
6575                                               &pDirEntry);
6576
6577             if( !NT_SUCCESS( ntStatus) ||
6578                 pDirEntry->TargetNameLength == 0)
6579             {
6580
6581                 if( pDirEntry != NULL)
6582                 {
6583
6584                     ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
6585                 }
6586
6587                 try_return( ntStatus);
6588             }
6589
6590             AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
6591                             TRUE);
6592
6593             if( DirectoryCB->NameInformation.TargetName.Length == 0)
6594             {
6595
6596                 //
6597                 // Update the target name
6598                 //
6599
6600                 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
6601                                                 &DirectoryCB->Flags,
6602                                                 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
6603                                                 (USHORT)pDirEntry->TargetNameLength);
6604
6605                 if( !NT_SUCCESS( ntStatus))
6606                 {
6607
6608                     AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6609
6610                     try_return( ntStatus);
6611                 }
6612             }
6613
6614             AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
6615         }
6616
6617         //
6618         // Need to pass the full path in for parsing.
6619         //
6620
6621         uniFullPathName.Length = 0;
6622         uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
6623
6624         uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6625                                                                     uniFullPathName.MaximumLength,
6626                                                                     AFS_NAME_BUFFER_EIGHT_TAG);
6627
6628         if( uniFullPathName.Buffer == NULL)
6629         {
6630
6631             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6632
6633             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6634         }
6635
6636         pwchBuffer = uniFullPathName.Buffer;
6637
6638         RtlZeroMemory( uniFullPathName.Buffer,
6639                        uniFullPathName.MaximumLength);
6640
6641         RtlCopyMemory( uniFullPathName.Buffer,
6642                        DirectoryCB->NameInformation.TargetName.Buffer,
6643                        DirectoryCB->NameInformation.TargetName.Length);
6644
6645         uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6646
6647         //
6648         // This name should begin with the \afs server so parse it off and chech it
6649         //
6650
6651         FsRtlDissectName( uniFullPathName,
6652                           &uniComponentName,
6653                           &uniRemainingPath);
6654
6655         if( RtlCompareUnicodeString( &uniComponentName,
6656                                      &AFSServerName,
6657                                      TRUE) != 0)
6658         {
6659
6660             //
6661             // Try evaluating the full path
6662             //
6663
6664             uniFullPathName.Buffer = pwchBuffer;
6665
6666             uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6667
6668             uniFullPathName.MaximumLength = uniFullPathName.Length;
6669         }
6670         else
6671         {
6672
6673             uniFullPathName = uniRemainingPath;
6674         }
6675
6676         uniParsedName = uniFullPathName;
6677
6678         ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
6679
6680         AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6681
6682         //
6683         // Our name array
6684         //
6685
6686         pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
6687                                        0);
6688
6689         if( pNameArray == NULL)
6690         {
6691
6692             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6693         }
6694
6695         pVolumeCB = AFSGlobalRoot;
6696
6697         pParentDirEntry = AFSGlobalRoot->DirectoryCB;
6698
6699         VolumeReferenceReason = AFS_VOLUME_REFERENCE_EVAL_ROOT;
6700
6701         lCount = AFSVolumeIncrement( pVolumeCB,
6702                                      VolumeReferenceReason);
6703
6704         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6705                       AFS_TRACE_LEVEL_VERBOSE,
6706                       "AFSEvaluateRootEntry Increment count on volume %p Reason %u Cnt %d\n",
6707                       pVolumeCB,
6708                       VolumeReferenceReason,
6709                       lCount));
6710
6711         lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
6712
6713         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6714                       AFS_TRACE_LEVEL_VERBOSE,
6715                       "AFSEvaluateRootEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
6716                       &pParentDirEntry->NameInformation.FileName,
6717                       pParentDirEntry,
6718                       NULL,
6719                       lCount));
6720
6721         ntStatus = AFSLocateNameEntry( NULL,
6722                                        NULL,
6723                                        &uniFullPathName,
6724                                        &uniParsedName,
6725                                        pNameArray,
6726                                        0,
6727                                        pVolumeCB,
6728                                        pParentDirEntry,
6729                                        &pNewVolumeCB,
6730                                        &VolumeReferenceReason,
6731                                        &pNewParentDirEntry,
6732                                        &pDirectoryEntry,
6733                                        NULL);
6734
6735         if ( pNewVolumeCB != NULL)
6736         {
6737             //
6738             // AFSLocateNameEntry returns pNewVolumeCB with a reference held
6739             // even if pVolumeCB == pNewVolumeCB.  It is always safe to release
6740             // the reference on pVolumeCB that was held prior to the call.
6741             // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
6742             // will be released second.
6743             //
6744
6745             lCount = AFSVolumeDecrement( pVolumeCB,
6746                                          VolumeReferenceReason);
6747
6748             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6749                           AFS_TRACE_LEVEL_VERBOSE,
6750                           "AFSEvaluateRootEntry Decrement count on volume %p Reason %u Cnt %d\n",
6751                           pVolumeCB,
6752                           VolumeReferenceReason,
6753                           lCount));
6754
6755             pVolumeCB = pNewVolumeCB;
6756
6757             pNewVolumeCB = NULL;
6758
6759             VolumeReferenceReason = NewVolumeReferenceReason;
6760
6761             NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
6762         }
6763
6764         //
6765         // AFSLocateNameEntry does not alter the reference count of
6766         // pParentDirectoryCB and it returns pNewParentDirectoryCB with
6767         // a reference held.
6768         //
6769
6770         lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
6771
6772         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6773                       AFS_TRACE_LEVEL_VERBOSE,
6774                       "AFSEvaluateRootEntry DecrementX count on %wZ DE %p Cnt %d\n",
6775                       &pParentDirEntry->NameInformation.FileName,
6776                       pParentDirEntry,
6777                       lCount));
6778
6779         pParentDirEntry = pNewParentDirEntry;
6780
6781         pNewParentDirEntry = NULL;
6782
6783         if( !NT_SUCCESS( ntStatus) ||
6784             ntStatus == STATUS_REPARSE)
6785         {
6786
6787             pVolumeCB = NULL;
6788
6789             try_return( ntStatus);
6790         }
6791
6792         //
6793         // Pass back the target dir entry for this request
6794         // The caller must release the DirOpenReferenceCount
6795         //
6796
6797         *TargetDirEntry = pDirectoryEntry;
6798
6799         pDirectoryEntry = NULL;
6800
6801 try_exit:
6802
6803         if( pDirectoryEntry != NULL)
6804         {
6805
6806             lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
6807
6808             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6809                           AFS_TRACE_LEVEL_VERBOSE,
6810                           "AFSEvaluateRootEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6811                           &pDirectoryEntry->NameInformation.FileName,
6812                           pDirectoryEntry,
6813                           NULL,
6814                           lCount));
6815
6816             ASSERT( lCount >= 0);
6817         }
6818
6819         if ( pParentDirEntry != NULL)
6820         {
6821
6822             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
6823
6824             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6825                           AFS_TRACE_LEVEL_VERBOSE,
6826                           "AFSEvaluateRootEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
6827                           &pParentDirEntry->NameInformation.FileName,
6828                           pParentDirEntry,
6829                           NULL,
6830                           lCount));
6831
6832             ASSERT( lCount >= 0);
6833         }
6834
6835         if( pDirEntry != NULL)
6836         {
6837
6838             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
6839         }
6840
6841         if( pVolumeCB != NULL)
6842         {
6843
6844             lCount = AFSVolumeDecrement( pVolumeCB,
6845                                          VolumeReferenceReason);
6846
6847             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6848                           AFS_TRACE_LEVEL_VERBOSE,
6849                           "AFSEvaluateRootEntry Decrement2 count on volume %p Reason %u Cnt %d\n",
6850                           pVolumeCB,
6851                           VolumeReferenceReason,
6852                           lCount));
6853         }
6854
6855         if( pNameArray != NULL)
6856         {
6857
6858             AFSFreeNameArray( pNameArray);
6859         }
6860
6861         if( pwchBuffer != NULL)
6862         {
6863
6864             //
6865             // Always free the buffer that we allocated as AFSLocateNameEntry
6866             // will not free it.  If uniFullPathName.Buffer was allocated by
6867             // AFSLocateNameEntry, then we must free that as well.
6868             // Check that the uniFullPathName.Buffer in the string is not the same
6869             // offset by the length of the server name
6870             //
6871
6872             if( uniFullPathName.Length > 0 &&
6873                 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
6874             {
6875
6876                 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
6877             }
6878
6879             AFSExFreePoolWithTag( pwchBuffer, 0);
6880         }
6881     }
6882
6883     return ntStatus;
6884 }
6885
6886 NTSTATUS
6887 AFSCleanupFcb( IN AFSFcb *Fcb,
6888                IN BOOLEAN ForceFlush)
6889 {
6890
6891     NTSTATUS ntStatus = STATUS_SUCCESS;
6892     AFSDeviceExt *pRDRDeviceExt = NULL, *pControlDeviceExt = NULL;
6893     LARGE_INTEGER liTime;
6894     IO_STATUS_BLOCK stIoStatus;
6895
6896     __Enter
6897     {
6898
6899         pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
6900
6901         pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
6902
6903         if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
6904         {
6905
6906             if( !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) &&
6907                 !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
6908             {
6909
6910                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
6911                               AFS_TRACE_LEVEL_VERBOSE,
6912                               "AFSCleanupEntry Acquiring Fcb lock %p EXCL %08lX\n",
6913                               &Fcb->NPFcb->Resource,
6914                               PsGetCurrentThread()));
6915
6916                 AFSAcquireExcl( &Fcb->NPFcb->Resource,
6917                                   TRUE);
6918
6919                 if( Fcb->OpenReferenceCount > 0)
6920                 {
6921
6922                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
6923                                   AFS_TRACE_LEVEL_VERBOSE,
6924                                   "AFSCleanupEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
6925                                   &Fcb->NPFcb->SectionObjectResource,
6926                                   PsGetCurrentThread()));
6927
6928                     AFSAcquireExcl( &Fcb->NPFcb->SectionObjectResource,
6929                                     TRUE);
6930
6931                     __try
6932                     {
6933
6934                         CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
6935                                       NULL,
6936                                       0,
6937                                       &stIoStatus);
6938
6939                         if( !NT_SUCCESS( stIoStatus.Status))
6940                         {
6941
6942                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
6943                                           AFS_TRACE_LEVEL_ERROR,
6944                                           "AFSCleanupFcb CcFlushCache [1] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
6945                                           Fcb->ObjectInformation->FileId.Cell,
6946                                           Fcb->ObjectInformation->FileId.Volume,
6947                                           Fcb->ObjectInformation->FileId.Vnode,
6948                                           Fcb->ObjectInformation->FileId.Unique,
6949                                           stIoStatus.Status,
6950                                           stIoStatus.Information));
6951
6952                             ntStatus = stIoStatus.Status;
6953                         }
6954
6955                         if (  Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
6956                         {
6957
6958                             if ( !CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
6959                                                        NULL,
6960                                                        0,
6961                                                        FALSE))
6962                             {
6963
6964                                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
6965                                               AFS_TRACE_LEVEL_WARNING,
6966                                               "AFSCleanupFcb CcPurgeCacheSection [1] failure FID %08lX-%08lX-%08lX-%08lX\n",
6967                                               Fcb->ObjectInformation->FileId.Cell,
6968                                               Fcb->ObjectInformation->FileId.Volume,
6969                                               Fcb->ObjectInformation->FileId.Vnode,
6970                                               Fcb->ObjectInformation->FileId.Unique));
6971
6972                                 SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
6973                             }
6974                         }
6975                     }
6976                     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
6977                     {
6978
6979                         ntStatus = GetExceptionCode();
6980
6981                         AFSDbgTrace(( 0,
6982                                       0,
6983                                       "EXCEPTION - AFSCleanupFcb Cc [1] FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
6984                                       Fcb->ObjectInformation->FileId.Cell,
6985                                       Fcb->ObjectInformation->FileId.Volume,
6986                                       Fcb->ObjectInformation->FileId.Vnode,
6987                                       Fcb->ObjectInformation->FileId.Unique,
6988                                       ntStatus));
6989
6990                         SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
6991                     }
6992
6993                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
6994                                   AFS_TRACE_LEVEL_VERBOSE,
6995                                   "AFSCleanupFcb Releasing Fcb SectionObject lock %p EXCL %08lX\n",
6996                                   &Fcb->NPFcb->SectionObjectResource,
6997                                   PsGetCurrentThread()));
6998
6999                     AFSReleaseResource( &Fcb->NPFcb->SectionObjectResource);
7000                 }
7001
7002                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
7003                               AFS_TRACE_LEVEL_VERBOSE,
7004                               "AFSCleanupEntry Releasing Fcb lock %p EXCL %08lX\n",
7005                               &Fcb->NPFcb->Resource,
7006                               PsGetCurrentThread()));
7007
7008                 AFSReleaseResource( &Fcb->NPFcb->Resource);
7009
7010                 if( !BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
7011                 {
7012                     //
7013                     // Wait for any currently running flush or release requests to complete
7014                     //
7015
7016                     AFSWaitOnQueuedFlushes( Fcb);
7017
7018                     //
7019                     // Now perform another flush on the file
7020                     //
7021
7022                     if( !NT_SUCCESS( AFSFlushExtents( Fcb,
7023                                                       NULL)))
7024                     {
7025
7026                         AFSReleaseExtentsWithFlush( Fcb,
7027                                                     NULL,
7028                                                     TRUE);
7029                     }
7030                 }
7031             }
7032
7033             if( !BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
7034             {
7035
7036                 if( Fcb->OpenReferenceCount == 0 ||
7037                     BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
7038                     BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
7039                 {
7040
7041                     AFSTearDownFcbExtents( Fcb,
7042                                            NULL);
7043                 }
7044             }
7045
7046             try_return( ntStatus);
7047         }
7048
7049         KeQueryTickCount( &liTime);
7050
7051         if( !BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
7052         {
7053             //
7054             // First up are there dirty extents in the cache to flush?
7055             //
7056
7057             if( BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
7058                 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
7059             {
7060
7061                 //
7062                 // The file has been marked as invalid.  Dump it
7063                 //
7064
7065                 AFSTearDownFcbExtents( Fcb,
7066                                        NULL);
7067             }
7068             else if( ForceFlush ||
7069                      ( ( Fcb->Specific.File.ExtentsDirtyCount ||
7070                          Fcb->Specific.File.ExtentCount) &&
7071                        (liTime.QuadPart - Fcb->Specific.File.LastServerFlush.QuadPart)
7072                        >= pControlDeviceExt->Specific.Control.FcbFlushTimeCount.QuadPart))
7073             {
7074
7075                 if( !NT_SUCCESS( AFSFlushExtents( Fcb,
7076                                                   NULL)) &&
7077                     Fcb->OpenReferenceCount == 0)
7078                 {
7079
7080                     AFSReleaseExtentsWithFlush( Fcb,
7081                                                 NULL,
7082                                                 TRUE);
7083                 }
7084             }
7085         }
7086
7087         //
7088         // If there are extents and they haven't been used recently *and*
7089         // are not being used
7090         //
7091
7092         if( ( ForceFlush ||
7093               ( 0 != Fcb->Specific.File.ExtentCount &&
7094                 0 != Fcb->Specific.File.LastExtentAccess.QuadPart &&
7095                 (liTime.QuadPart - Fcb->Specific.File.LastExtentAccess.QuadPart) >=
7096                                         (AFS_SERVER_PURGE_SLEEP * pControlDeviceExt->Specific.Control.FcbPurgeTimeCount.QuadPart))))
7097         {
7098
7099             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
7100                           AFS_TRACE_LEVEL_VERBOSE,
7101                           "AFSCleanupFcb Acquiring Fcb lock %p EXCL %08lX\n",
7102                           &Fcb->NPFcb->Resource,
7103                           PsGetCurrentThread()));
7104
7105             if ( AFSAcquireExcl( &Fcb->NPFcb->Resource, ForceFlush) == FALSE)
7106             {
7107
7108                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
7109                               AFS_TRACE_LEVEL_VERBOSE,
7110                               "AFSCleanupFcb Failed to Acquire Fcb lock %p EXCL %08lX\n",
7111                               &Fcb->NPFcb->Resource,
7112                               PsGetCurrentThread()));
7113
7114                 try_return( ntStatus = STATUS_RETRY);
7115             }
7116
7117             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
7118                           AFS_TRACE_LEVEL_VERBOSE,
7119                           "AFSCleanupFcb Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
7120                           &Fcb->NPFcb->SectionObjectResource,
7121                           PsGetCurrentThread()));
7122
7123             if ( AFSAcquireExcl( &Fcb->NPFcb->SectionObjectResource, ForceFlush))
7124             {
7125
7126                 __try
7127                 {
7128
7129                     CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
7130                                   NULL,
7131                                   0,
7132                                   &stIoStatus);
7133
7134                     if( !NT_SUCCESS( stIoStatus.Status))
7135                     {
7136
7137                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
7138                                       AFS_TRACE_LEVEL_ERROR,
7139                                       "AFSCleanupFcb CcFlushCache [2] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
7140                                       Fcb->ObjectInformation->FileId.Cell,
7141                                       Fcb->ObjectInformation->FileId.Volume,
7142                                       Fcb->ObjectInformation->FileId.Vnode,
7143                                       Fcb->ObjectInformation->FileId.Unique,
7144                                       stIoStatus.Status,
7145                                       stIoStatus.Information));
7146
7147                         ntStatus = stIoStatus.Status;
7148                     }
7149
7150                     if( ForceFlush &&
7151                         Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
7152                     {
7153
7154                         if ( !CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
7155                                                    NULL,
7156                                                    0,
7157                                                    FALSE))
7158                         {
7159
7160                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
7161                                           AFS_TRACE_LEVEL_WARNING,
7162                                           "AFSCleanupFcb CcPurgeCacheSection [2] failure FID %08lX-%08lX-%08lX-%08lX\n",
7163                                           Fcb->ObjectInformation->FileId.Cell,
7164                                           Fcb->ObjectInformation->FileId.Volume,
7165                                           Fcb->ObjectInformation->FileId.Vnode,
7166                                           Fcb->ObjectInformation->FileId.Unique));
7167
7168                             SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
7169                         }
7170                     }
7171                 }
7172                 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
7173                 {
7174
7175                     ntStatus = GetExceptionCode();
7176
7177                     AFSDbgTrace(( 0,
7178                                   0,
7179                                   "EXCEPTION - AFSCleanupFcb Cc [2] FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
7180                                   Fcb->ObjectInformation->FileId.Cell,
7181                                   Fcb->ObjectInformation->FileId.Volume,
7182                                   Fcb->ObjectInformation->FileId.Vnode,
7183                                   Fcb->ObjectInformation->FileId.Unique,
7184                                   ntStatus));
7185                 }
7186
7187                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
7188                               AFS_TRACE_LEVEL_VERBOSE,
7189                               "AFSCleanupFcb Releasing Fcb SectionObject lock %p EXCL %08lX\n",
7190                               &Fcb->NPFcb->SectionObjectResource,
7191                               PsGetCurrentThread()));
7192
7193                 AFSReleaseResource( &Fcb->NPFcb->SectionObjectResource);
7194
7195                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
7196                               AFS_TRACE_LEVEL_VERBOSE,
7197                               "AFSCleanupFcb Releasing Fcb lock %p EXCL %08lX\n",
7198                               &Fcb->NPFcb->Resource,
7199                               PsGetCurrentThread()));
7200
7201                 AFSReleaseResource( &Fcb->NPFcb->Resource);
7202
7203                 if( !BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
7204                 {
7205
7206                     if( Fcb->OpenReferenceCount <= 0)
7207                     {
7208
7209                         //
7210                         // Tear em down we'll not be needing them again
7211                         //
7212
7213                         AFSTearDownFcbExtents( Fcb,
7214                                                NULL);
7215                     }
7216                 }
7217             }
7218             else
7219             {
7220
7221                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
7222                               AFS_TRACE_LEVEL_VERBOSE,
7223                               "AFSCleanupFcb Failed to Acquire Fcb SectionObject lock %p EXCL %08lX\n",
7224                               &Fcb->NPFcb->SectionObjectResource,
7225                               PsGetCurrentThread()));
7226
7227                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
7228                               AFS_TRACE_LEVEL_VERBOSE,
7229                               "AFSCleanupFcb Releasing Fcb lock %p EXCL %08lX\n",
7230                               &Fcb->NPFcb->Resource,
7231                               PsGetCurrentThread()));
7232
7233                 AFSReleaseResource( &Fcb->NPFcb->Resource);
7234
7235                 ntStatus = STATUS_RETRY;
7236             }
7237         }
7238
7239 try_exit:
7240
7241         NOTHING;
7242     }
7243
7244     return ntStatus;
7245 }
7246
7247 NTSTATUS
7248 AFSUpdateDirEntryName( IN AFSDirectoryCB *DirectoryCB,
7249                        IN UNICODE_STRING *NewFileName)
7250 {
7251
7252     NTSTATUS ntStatus = STATUS_SUCCESS;
7253     WCHAR *pTmpBuffer = NULL;
7254
7255     __Enter
7256     {
7257
7258         if( NewFileName->Length > DirectoryCB->NameInformation.FileName.Length)
7259         {
7260
7261             if( BooleanFlagOn( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
7262             {
7263
7264                 AFSExFreePoolWithTag( DirectoryCB->NameInformation.FileName.Buffer, 0);
7265
7266                 ClearFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
7267
7268                 DirectoryCB->NameInformation.FileName.Buffer = NULL;
7269             }
7270
7271             //
7272             // OK, we need to allocate a new name buffer
7273             //
7274
7275             pTmpBuffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
7276                                                             NewFileName->Length,
7277                                                             AFS_NAME_BUFFER_NINE_TAG);
7278
7279             if( pTmpBuffer == NULL)
7280             {
7281
7282                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7283             }
7284
7285             DirectoryCB->NameInformation.FileName.Buffer = pTmpBuffer;
7286
7287             DirectoryCB->NameInformation.FileName.MaximumLength = NewFileName->Length;
7288
7289             SetFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
7290         }
7291
7292         DirectoryCB->NameInformation.FileName.Length = NewFileName->Length;
7293
7294         RtlCopyMemory( DirectoryCB->NameInformation.FileName.Buffer,
7295                        NewFileName->Buffer,
7296                        NewFileName->Length);
7297
7298 try_exit:
7299
7300         NOTHING;
7301     }
7302
7303     return ntStatus;
7304 }
7305
7306 NTSTATUS
7307 AFSReadCacheFile( IN void *ReadBuffer,
7308                   IN LARGE_INTEGER *ReadOffset,
7309                   IN ULONG RequestedDataLength,
7310                   IN OUT PULONG BytesRead)
7311 {
7312
7313     NTSTATUS            ntStatus = STATUS_SUCCESS;
7314     PIRP                pIrp = NULL;
7315     KEVENT              kEvent;
7316     PIO_STACK_LOCATION  pIoStackLocation = NULL;
7317     DEVICE_OBJECT      *pTargetDeviceObject = NULL;
7318     FILE_OBJECT        *pCacheFileObject = NULL;
7319
7320     __Enter
7321     {
7322
7323         pCacheFileObject = AFSReferenceCacheFileObject();
7324
7325         if( pCacheFileObject == NULL)
7326         {
7327             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
7328         }
7329
7330         pTargetDeviceObject = IoGetRelatedDeviceObject( pCacheFileObject);
7331
7332         //
7333         // Initialize the event
7334         //
7335
7336         KeInitializeEvent( &kEvent,
7337                            SynchronizationEvent,
7338                            FALSE);
7339
7340         //
7341         // Allocate an irp for this request.  This could also come from a
7342         // private pool, for instance.
7343         //
7344
7345         pIrp = IoAllocateIrp( pTargetDeviceObject->StackSize,
7346                               FALSE);
7347
7348         if( pIrp == NULL)
7349         {
7350
7351             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7352         }
7353
7354         //
7355         // Build the IRP's main body
7356         //
7357
7358         pIrp->UserBuffer = ReadBuffer;
7359
7360         pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
7361         pIrp->RequestorMode = KernelMode;
7362         pIrp->Flags |= IRP_READ_OPERATION;
7363
7364         //
7365         // Set up the I/O stack location.
7366         //
7367
7368         pIoStackLocation = IoGetNextIrpStackLocation( pIrp);
7369         pIoStackLocation->MajorFunction = IRP_MJ_READ;
7370         pIoStackLocation->DeviceObject = pTargetDeviceObject;
7371         pIoStackLocation->FileObject = pCacheFileObject;
7372         pIoStackLocation->Parameters.Read.Length = RequestedDataLength;
7373
7374         pIoStackLocation->Parameters.Read.ByteOffset.QuadPart = ReadOffset->QuadPart;
7375
7376         //
7377         // Set the completion routine.
7378         //
7379
7380         IoSetCompletionRoutine( pIrp,
7381                                 AFSIrpComplete,
7382                                 &kEvent,
7383                                 TRUE,
7384                                 TRUE,
7385                                 TRUE);
7386
7387         //
7388         // Send it to the FSD
7389         //
7390
7391         ntStatus = IoCallDriver( pTargetDeviceObject,
7392                                  pIrp);
7393
7394         if( NT_SUCCESS( ntStatus))
7395         {
7396
7397             //
7398             // Wait for the I/O
7399             //
7400
7401             ntStatus = KeWaitForSingleObject( &kEvent,
7402                                               Executive,
7403                                               KernelMode,
7404                                               FALSE,
7405                                               0);
7406
7407             if( NT_SUCCESS( ntStatus))
7408             {
7409
7410                 ntStatus = pIrp->IoStatus.Status;
7411
7412                 *BytesRead = (ULONG)pIrp->IoStatus.Information;
7413             }
7414         }
7415
7416 try_exit:
7417
7418         if( pCacheFileObject != NULL)
7419         {
7420             AFSReleaseCacheFileObject( pCacheFileObject);
7421         }
7422
7423         if( pIrp != NULL)
7424         {
7425
7426             if( pIrp->MdlAddress != NULL)
7427             {
7428
7429                 if( FlagOn( pIrp->MdlAddress->MdlFlags, MDL_PAGES_LOCKED))
7430                 {
7431
7432                     MmUnlockPages( pIrp->MdlAddress);
7433                 }
7434
7435                 IoFreeMdl( pIrp->MdlAddress);
7436             }
7437
7438             pIrp->MdlAddress = NULL;
7439
7440             //
7441             // Free the Irp
7442             //
7443
7444             IoFreeIrp( pIrp);
7445         }
7446     }
7447
7448     return ntStatus;
7449 }
7450
7451 NTSTATUS
7452 AFSIrpComplete( IN PDEVICE_OBJECT DeviceObject,
7453                 IN PIRP           Irp,
7454                 IN PVOID          Context)
7455 {
7456
7457     UNREFERENCED_PARAMETER(Irp);
7458     UNREFERENCED_PARAMETER(DeviceObject);
7459     KEVENT *pEvent = (KEVENT *)Context;
7460
7461     KeSetEvent( pEvent,
7462                 0,
7463                 FALSE);
7464
7465     return STATUS_MORE_PROCESSING_REQUIRED;
7466 }
7467
7468 BOOLEAN
7469 AFSIsDirectoryEmptyForDelete( IN AFSFcb *Fcb)
7470 {
7471
7472     BOOLEAN bIsEmpty = FALSE;
7473     AFSDirectoryCB *pDirEntry = NULL;
7474
7475     __Enter
7476     {
7477
7478         ASSERT( Fcb->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY);
7479
7480         AFSAcquireShared( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
7481                           TRUE);
7482
7483         bIsEmpty = TRUE;
7484
7485         if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
7486         {
7487
7488             pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
7489
7490             while( pDirEntry != NULL)
7491             {
7492
7493                 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
7494                     !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
7495                 {
7496
7497                     bIsEmpty = FALSE;
7498
7499                     break;
7500                 }
7501
7502                 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
7503             }
7504
7505         }
7506
7507         AFSReleaseResource( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
7508     }
7509
7510     return bIsEmpty;
7511 }
7512
7513 void
7514 AFSRemoveNameEntry( IN AFSObjectInfoCB *ParentObjectInfo,
7515                     IN AFSDirectoryCB *DirEntry)
7516 {
7517
7518     NTSTATUS ntStatus = STATUS_SUCCESS;
7519
7520     __Enter
7521     {
7522
7523         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7524         {
7525
7526             AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7527                           AFS_TRACE_LEVEL_VERBOSE,
7528                           "AFSRemoveNameEntry DE %p for %wZ has NOT_IN flag set\n",
7529                           DirEntry,
7530                           &DirEntry->NameInformation.FileName));
7531
7532             try_return( ntStatus);
7533         }
7534
7535         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
7536
7537         //
7538         // Remove the entry from the parent tree
7539         //
7540
7541         AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7542                       AFS_TRACE_LEVEL_VERBOSE,
7543                       "AFSRemoveNameEntry DE %p for %wZ removing from case sensitive tree\n",
7544                       DirEntry,
7545                       &DirEntry->NameInformation.FileName));
7546
7547         AFSRemoveCaseSensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7548                                         DirEntry);
7549
7550         AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7551                       AFS_TRACE_LEVEL_VERBOSE,
7552                       "AFSRemoveNameEntry DE %p for %wZ removing from case insensitive tree\n",
7553                       DirEntry,
7554                       &DirEntry->NameInformation.FileName));
7555
7556         AFSRemoveCaseInsensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
7557                                           DirEntry);
7558
7559         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
7560         {
7561
7562             //
7563             // From the short name tree
7564             //
7565
7566             AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7567                           AFS_TRACE_LEVEL_VERBOSE,
7568                           "AFSRemoveNameEntry DE %p for %wZ removing from shortname tree\n",
7569                           DirEntry,
7570                           &DirEntry->NameInformation.FileName));
7571
7572             AFSRemoveShortNameDirEntry( &ParentObjectInfo->Specific.Directory.ShortNameTree,
7573                                         DirEntry);
7574
7575             ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
7576         }
7577
7578         AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7579                       AFS_TRACE_LEVEL_VERBOSE,
7580                       "AFSRemoveNameEntry DE %p for %wZ setting NOT_IN flag\n",
7581                       DirEntry,
7582                       &DirEntry->NameInformation.FileName));
7583
7584         SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
7585
7586         ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
7587
7588 try_exit:
7589
7590         NOTHING;
7591     }
7592
7593     return;
7594 }
7595
7596 LARGE_INTEGER
7597 AFSGetAuthenticationId()
7598 {
7599
7600     LARGE_INTEGER liAuthId = {0,0};
7601     NTSTATUS ntStatus = STATUS_SUCCESS;
7602     PACCESS_TOKEN hToken = NULL;
7603     PTOKEN_STATISTICS pTokenInfo = NULL;
7604     BOOLEAN bCopyOnOpen = FALSE;
7605     BOOLEAN bEffectiveOnly = FALSE;
7606     BOOLEAN bPrimaryToken = FALSE;
7607     SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
7608
7609     __Enter
7610     {
7611
7612         hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
7613                                                 &bCopyOnOpen,
7614                                                 &bEffectiveOnly,
7615                                                 &stImpersonationLevel);
7616
7617         if( hToken == NULL)
7618         {
7619
7620             hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
7621
7622             if( hToken == NULL)
7623             {
7624
7625                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7626                               AFS_TRACE_LEVEL_ERROR,
7627                               "AFSGetAuthenticationId Failed to retrieve impersonation or primary token\n"));
7628
7629                 try_return( ntStatus);
7630             }
7631
7632             bPrimaryToken = TRUE;
7633         }
7634
7635         ntStatus = SeQueryInformationToken( hToken,
7636                                             TokenStatistics,
7637                                             (PVOID *)&pTokenInfo);
7638
7639         if( !NT_SUCCESS( ntStatus))
7640         {
7641
7642             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7643                           AFS_TRACE_LEVEL_ERROR,
7644                           "AFSGetAuthenticationId Failed to retrieve information Status %08lX\n",
7645                           ntStatus));
7646
7647             try_return( ntStatus);
7648         }
7649
7650         liAuthId.HighPart = pTokenInfo->AuthenticationId.HighPart;
7651         liAuthId.LowPart = pTokenInfo->AuthenticationId.LowPart;
7652
7653         AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7654                       AFS_TRACE_LEVEL_VERBOSE,
7655                       "AFSGetAuthenticationId Successfully retrieved authentication ID %I64X\n",
7656                       liAuthId.QuadPart));
7657
7658 try_exit:
7659
7660         if( hToken != NULL)
7661         {
7662
7663             if( !bPrimaryToken)
7664             {
7665
7666                 PsDereferenceImpersonationToken( hToken);
7667             }
7668             else
7669             {
7670
7671                 PsDereferencePrimaryToken( hToken);
7672             }
7673         }
7674
7675         if( pTokenInfo != NULL)
7676         {
7677
7678             ExFreePool( pTokenInfo);    // Allocated by SeQueryInformationToken
7679         }
7680     }
7681
7682     return liAuthId;
7683 }
7684
7685 void
7686 AFSUnwindFileInfo( IN AFSFcb *Fcb,
7687                    IN AFSCcb *Ccb)
7688 {
7689
7690     UNREFERENCED_PARAMETER(Fcb);
7691     if( Ccb->FileUnwindInfo.FileAttributes != (ULONG)-1)
7692     {
7693         Fcb->ObjectInformation->FileAttributes = Ccb->FileUnwindInfo.FileAttributes;
7694     }
7695
7696     if( Ccb->FileUnwindInfo.CreationTime.QuadPart != (ULONGLONG)-1)
7697     {
7698         Fcb->ObjectInformation->CreationTime.QuadPart = Ccb->FileUnwindInfo.CreationTime.QuadPart;
7699     }
7700
7701     if( Ccb->FileUnwindInfo.LastAccessTime.QuadPart != (ULONGLONG)-1)
7702     {
7703         Fcb->ObjectInformation->LastAccessTime.QuadPart = Ccb->FileUnwindInfo.LastAccessTime.QuadPart;
7704     }
7705
7706     if( Ccb->FileUnwindInfo.LastWriteTime.QuadPart != (ULONGLONG)-1)
7707     {
7708         Fcb->ObjectInformation->LastWriteTime.QuadPart = Ccb->FileUnwindInfo.LastWriteTime.QuadPart;
7709     }
7710
7711     if( Ccb->FileUnwindInfo.ChangeTime.QuadPart != (ULONGLONG)-1)
7712     {
7713         Fcb->ObjectInformation->ChangeTime.QuadPart = Ccb->FileUnwindInfo.ChangeTime.QuadPart;
7714     }
7715
7716     return;
7717 }
7718
7719 BOOLEAN
7720 AFSValidateDirList( IN AFSObjectInfoCB *ObjectInfo)
7721 {
7722
7723     BOOLEAN bIsValid = TRUE;
7724     ULONG ulCount = 0;
7725     AFSDirectoryCB *pCurrentDirEntry = NULL, *pDirEntry = NULL;
7726
7727     pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
7728
7729     while( pCurrentDirEntry != NULL)
7730     {
7731
7732         if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
7733         {
7734             ulCount++;
7735
7736             if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7737             {
7738
7739                 pDirEntry = NULL;
7740
7741                 AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7742                                                 (ULONG)pCurrentDirEntry->CaseSensitiveTreeEntry.HashIndex,
7743                                                 &pDirEntry);
7744
7745                 if( pDirEntry == NULL)
7746                 {
7747                     DbgBreakPoint();
7748                 }
7749             }
7750         }
7751
7752         pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
7753     }
7754
7755     if( ulCount != (ULONG) ObjectInfo->Specific.Directory.DirectoryNodeCount)
7756     {
7757
7758         AFSPrint("AFSValidateDirList Count off Calc: %d Stored: %d\n",
7759                   ulCount,
7760                   ObjectInfo->Specific.Directory.DirectoryNodeCount);
7761
7762         ObjectInfo->Specific.Directory.DirectoryNodeCount = ulCount;
7763
7764         bIsValid = FALSE;
7765     }
7766
7767     return bIsValid;
7768 }
7769
7770 PFILE_OBJECT
7771 AFSReferenceCacheFileObject()
7772 {
7773
7774     AFSDeviceExt       *pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
7775     FILE_OBJECT        *pCacheFileObject = NULL;
7776
7777     AFSAcquireShared( &pRdrDevExt->Specific.RDR.CacheFileLock,
7778                       TRUE);
7779
7780     pCacheFileObject = pRdrDevExt->Specific.RDR.CacheFileObject;
7781
7782     if( pCacheFileObject != NULL)
7783     {
7784         ObReferenceObject( pCacheFileObject);
7785     }
7786
7787     AFSReleaseResource( &pRdrDevExt->Specific.RDR.CacheFileLock);
7788
7789     return pCacheFileObject;
7790 }
7791
7792 void
7793 AFSReleaseCacheFileObject( IN PFILE_OBJECT CacheFileObject)
7794 {
7795
7796     ASSERT( CacheFileObject != NULL);
7797
7798     ObDereferenceObject( CacheFileObject);
7799
7800     return;
7801 }
7802
7803 NTSTATUS
7804 AFSInitializeLibrary( IN AFSLibraryInitCB *LibraryInit)
7805 {
7806
7807     NTSTATUS ntStatus = STATUS_SUCCESS;
7808     AFSDeviceExt *pControlDevExt = NULL;
7809     ULONG ulTimeIncrement = 0;
7810     LONG lCount;
7811
7812     __Enter
7813     {
7814
7815         AFSControlDeviceObject = LibraryInit->AFSControlDeviceObject;
7816
7817         AFSRDRDeviceObject = LibraryInit->AFSRDRDeviceObject;
7818
7819         AFSServerName = LibraryInit->AFSServerName;
7820
7821         AFSMountRootName = LibraryInit->AFSMountRootName;
7822
7823         AFSDebugFlags = LibraryInit->AFSDebugFlags;
7824
7825         //
7826         // Callbacks in the framework
7827         //
7828
7829         AFSProcessRequest = LibraryInit->AFSProcessRequest;
7830
7831         AFSDbgLogMsg = LibraryInit->AFSDbgLogMsg;
7832
7833         AFSDebugTraceFnc = AFSDbgLogMsg;
7834
7835         AFSAddConnectionEx = LibraryInit->AFSAddConnectionEx;
7836
7837         AFSExAllocatePoolWithTag = LibraryInit->AFSExAllocatePoolWithTag;
7838
7839         AFSExFreePoolWithTag = LibraryInit->AFSExFreePoolWithTag;
7840
7841         AFSDumpTraceFilesFnc = LibraryInit->AFSDumpTraceFiles;
7842
7843         AFSRetrieveAuthGroupFnc = LibraryInit->AFSRetrieveAuthGroup;
7844
7845         AFSLibCacheManagerCallbacks = LibraryInit->AFSCacheManagerCallbacks;
7846
7847         if( LibraryInit->AFSCacheBaseAddress != NULL)
7848         {
7849
7850             SetFlag( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE);
7851
7852             AFSLibCacheBaseAddress = LibraryInit->AFSCacheBaseAddress;
7853
7854             AFSLibCacheLength = LibraryInit->AFSCacheLength;
7855         }
7856
7857         //
7858         // Initialize some flush parameters
7859         //
7860
7861         pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
7862
7863         ulTimeIncrement = KeQueryTimeIncrement();
7864
7865         pControlDevExt->Specific.Control.ObjectLifeTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_OBJECT_LIFETIME / (ULONGLONG)ulTimeIncrement);
7866         pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart = AFS_SERVER_PURGE_DELAY;
7867         pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart /= ulTimeIncrement;
7868         pControlDevExt->Specific.Control.FcbFlushTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_SERVER_FLUSH_DELAY / (ULONGLONG)ulTimeIncrement);
7869         pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_EXTENT_REQUEST_TIME/(ULONGLONG)ulTimeIncrement);
7870
7871         //
7872         // Initialize the global root entry
7873         //
7874
7875         ntStatus = AFSInitVolume( NULL,
7876                                   &LibraryInit->GlobalRootFid,
7877                                   AFS_VOLUME_REFERENCE_GLOBAL_ROOT,
7878                                   &AFSGlobalRoot);
7879
7880         if( !NT_SUCCESS( ntStatus))
7881         {
7882
7883             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
7884                           AFS_TRACE_LEVEL_ERROR,
7885                           "AFSInitializeLibrary AFSInitVolume failure %08lX\n",
7886                           ntStatus));
7887
7888             try_return( ntStatus);
7889         }
7890
7891         ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
7892                                    AFSGlobalRoot);
7893
7894         if( !NT_SUCCESS( ntStatus))
7895         {
7896
7897             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
7898                           AFS_TRACE_LEVEL_ERROR,
7899                           "AFSInitializeLibrary AFSInitRootFcb failure %08lX\n",
7900                           ntStatus));
7901
7902             lCount = AFSVolumeDecrement( AFSGlobalRoot,
7903                                          AFS_VOLUME_REFERENCE_GLOBAL_ROOT);
7904
7905             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7906                           AFS_TRACE_LEVEL_VERBOSE,
7907                           "AFSInitializeLibrary Decrement count on volume %p Cnt %d\n",
7908                           AFSGlobalRoot,
7909                           lCount));
7910
7911             AFSReleaseResource( AFSGlobalRoot->VolumeLock);
7912
7913             try_return( ntStatus);
7914         }
7915
7916         //
7917         // Update the node type code to AFS_ROOT_ALL
7918         //
7919
7920         AFSGlobalRoot->ObjectInformation.Fcb->Header.NodeTypeCode = AFS_ROOT_ALL;
7921
7922         SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_ACTIVE_GLOBAL_ROOT);
7923
7924         //
7925         // Invalidate all known volumes since contact with the service and therefore
7926         // the file server was lost.
7927         //
7928
7929         AFSInvalidateAllVolumes();
7930
7931         //
7932         // Drop the locks acquired above
7933         //
7934
7935         AFSInitVolumeWorker( AFSGlobalRoot);
7936
7937         lCount = AFSVolumeDecrement( AFSGlobalRoot,
7938                                      AFS_VOLUME_REFERENCE_GLOBAL_ROOT);
7939
7940         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7941                       AFS_TRACE_LEVEL_VERBOSE,
7942                       "AFSInitializeLibrary Decrement count on volume %p Cnt %d\n",
7943                       AFSGlobalRoot,
7944                       lCount));
7945
7946         AFSReleaseResource( AFSGlobalRoot->VolumeLock);
7947
7948         AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Fcb->Header.Resource);
7949
7950 try_exit:
7951
7952         NOTHING;
7953     }
7954
7955     return ntStatus;
7956 }
7957
7958 NTSTATUS
7959 AFSCloseLibrary()
7960 {
7961
7962     NTSTATUS ntStatus = STATUS_SUCCESS;
7963     AFSDirectoryCB *pDirNode = NULL, *pLastDirNode = NULL;
7964     LONG lCount;
7965
7966     __Enter
7967     {
7968
7969         if( AFSGlobalDotDirEntry != NULL)
7970         {
7971
7972             lCount = AFSObjectInfoDecrement( AFSGlobalDotDirEntry->ObjectInformation,
7973                                              AFS_OBJECT_REFERENCE_GLOBAL);
7974
7975             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
7976                           AFS_TRACE_LEVEL_VERBOSE,
7977                           "AFSCloseLibrary Decrement count on parent object %p Cnt %d\n",
7978                           AFSGlobalDotDirEntry->ObjectInformation,
7979                           lCount));
7980
7981             if ( lCount == 0)
7982             {
7983
7984                 AFSDeleteObjectInfo( &AFSGlobalDotDirEntry->ObjectInformation);
7985             }
7986
7987             ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
7988
7989             AFSLibExFreePoolWithTag( AFSGlobalDotDirEntry->NonPaged,
7990                                      AFS_DIR_ENTRY_NP_TAG);
7991
7992             AFSLibExFreePoolWithTag( AFSGlobalDotDirEntry,
7993                                      AFS_DIR_ENTRY_TAG);
7994
7995             AFSGlobalDotDirEntry = NULL;
7996         }
7997
7998         if( AFSGlobalDotDotDirEntry != NULL)
7999         {
8000
8001             lCount = AFSObjectInfoDecrement( AFSGlobalDotDotDirEntry->ObjectInformation,
8002                                              AFS_OBJECT_REFERENCE_GLOBAL);
8003
8004             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8005                           AFS_TRACE_LEVEL_VERBOSE,
8006                           "AFSCloseLibrary Decrement count on parent object %p Cnt %d\n",
8007                           AFSGlobalDotDotDirEntry->ObjectInformation,
8008                           lCount));
8009
8010             if ( lCount == 0)
8011             {
8012
8013                 AFSDeleteObjectInfo( &AFSGlobalDotDotDirEntry->ObjectInformation);
8014             }
8015
8016             ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
8017
8018             AFSLibExFreePoolWithTag( AFSGlobalDotDotDirEntry->NonPaged,
8019                                   AFS_DIR_ENTRY_NP_TAG);
8020
8021             AFSLibExFreePoolWithTag( AFSGlobalDotDotDirEntry,
8022                                   AFS_DIR_ENTRY_TAG);
8023
8024             AFSGlobalDotDotDirEntry = NULL;
8025         }
8026
8027         if( AFSSpecialShareNames != NULL)
8028         {
8029
8030             pDirNode = AFSSpecialShareNames;
8031
8032             while( pDirNode != NULL)
8033             {
8034
8035                 pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
8036
8037                 lCount = AFSObjectInfoDecrement( pDirNode->ObjectInformation,
8038                                                  AFS_OBJECT_REFERENCE_GLOBAL);
8039
8040                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8041                               AFS_TRACE_LEVEL_VERBOSE,
8042                               "AFSCloseLibrary Decrement count on parent object %p Cnt %d\n",
8043                               pDirNode->ObjectInformation,
8044                               lCount));
8045
8046                 if ( lCount == 0)
8047                 {
8048
8049                     AFSDeleteObjectInfo( &pDirNode->ObjectInformation);
8050                 }
8051
8052                 ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
8053
8054                 AFSLibExFreePoolWithTag( pDirNode->NonPaged,
8055                                          AFS_DIR_ENTRY_NP_TAG);
8056
8057                 AFSLibExFreePoolWithTag( pDirNode,
8058                                          AFS_DIR_ENTRY_TAG);
8059
8060                 pDirNode = pLastDirNode;
8061             }
8062
8063             AFSSpecialShareNames = NULL;
8064         }
8065     }
8066
8067     return ntStatus;
8068 }
8069
8070 NTSTATUS
8071 AFSDefaultLogMsg( IN ULONG Subsystem,
8072                   IN ULONG Level,
8073                   IN PCCH Format,
8074                   ...)
8075 {
8076
8077     UNREFERENCED_PARAMETER(Subsystem);
8078     UNREFERENCED_PARAMETER(Level);
8079     NTSTATUS ntStatus = STATUS_SUCCESS;
8080     va_list va_args;
8081     char chDebugBuffer[ 256];
8082
8083     __Enter
8084     {
8085
8086         va_start( va_args, Format);
8087
8088         ntStatus = RtlStringCbVPrintfA( chDebugBuffer,
8089                                         256,
8090                                         Format,
8091                                         va_args);
8092
8093         if( NT_SUCCESS( ntStatus))
8094         {
8095             DbgPrint( chDebugBuffer);
8096         }
8097
8098         va_end( va_args);
8099     }
8100
8101     return ntStatus;
8102 }
8103
8104 NTSTATUS
8105 AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
8106                     IN ULONG InputBufferLength,
8107                     IN AFSStatusInfoCB *StatusInfo,
8108                     OUT ULONG *ReturnLength)
8109 {
8110
8111     NTSTATUS ntStatus = STATUS_SUCCESS;
8112     AFSVolumeCB *pVolumeCB = NULL;
8113     LONG VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
8114     AFSVolumeCB *pNewVolumeCB = NULL;
8115     LONG NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
8116     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
8117     AFSObjectInfoCB *pObjectInfo = NULL;
8118     ULONGLONG   ullIndex = 0;
8119     UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName, uniParsedName;
8120     AFSNameArrayHdr *pNameArray = NULL;
8121     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
8122     AFSDirectoryCB *pNewParentDirEntry = NULL;
8123     LONG lCount;
8124
8125     __Enter
8126     {
8127
8128         //
8129         // If we are given a FID then look up the entry by that, otherwise
8130         // do it by name
8131         //
8132
8133         if( GetStatusInfo->FileID.Cell != 0 &&
8134             GetStatusInfo->FileID.Volume != 0 &&
8135             GetStatusInfo->FileID.Vnode != 0 &&
8136             GetStatusInfo->FileID.Unique != 0)
8137         {
8138
8139             AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
8140
8141             //
8142             // Locate the volume node
8143             //
8144
8145             ullIndex = AFSCreateHighIndex( &GetStatusInfo->FileID);
8146
8147             ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
8148                                            ullIndex,
8149                                            (AFSBTreeEntry **)&pVolumeCB);
8150
8151             if( pVolumeCB != NULL)
8152             {
8153
8154                 VolumeReferenceReason = AFS_VOLUME_REFERENCE_GET_OBJECT;
8155
8156                 lCount = AFSVolumeIncrement( pVolumeCB,
8157                                              VolumeReferenceReason);
8158
8159                 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8160                               AFS_TRACE_LEVEL_VERBOSE,
8161                               "AFSGetObjectStatus Increment count on volume %p Reason %u Cnt %d\n",
8162                               pVolumeCB,
8163                               VolumeReferenceReason,
8164                               lCount));
8165             }
8166
8167             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
8168
8169             if( !NT_SUCCESS( ntStatus) ||
8170                 pVolumeCB == NULL)
8171             {
8172                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8173             }
8174
8175             if( AFSIsVolumeFID( &GetStatusInfo->FileID))
8176             {
8177
8178                 pObjectInfo = &pVolumeCB->ObjectInformation;
8179
8180                 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
8181                                   TRUE);
8182
8183                 lCount = AFSObjectInfoIncrement( pObjectInfo,
8184                                                  AFS_OBJECT_REFERENCE_STATUS);
8185
8186                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8187                               AFS_TRACE_LEVEL_VERBOSE,
8188                               "AFSGetObjectStatus Increment1 count on object %p Cnt %d\n",
8189                               pObjectInfo,
8190                               lCount));
8191
8192                 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
8193             }
8194             else
8195             {
8196
8197                 AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
8198                                 TRUE);
8199
8200                 ullIndex = AFSCreateLowIndex( &GetStatusInfo->FileID);
8201
8202                 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
8203                                                ullIndex,
8204                                                (AFSBTreeEntry **)&pObjectInfo);
8205
8206                 if( pObjectInfo != NULL)
8207                 {
8208
8209                     //
8210                     // Reference the node so it won't be torn down
8211                     //
8212
8213                     lCount = AFSObjectInfoIncrement( pObjectInfo,
8214                                                      AFS_OBJECT_REFERENCE_STATUS);
8215
8216                     AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8217                                   AFS_TRACE_LEVEL_VERBOSE,
8218                                   "AFSGetObjectStatus Increment2 count on object %p Cnt %d\n",
8219                                   pObjectInfo,
8220                                   lCount));
8221
8222                     KeQueryTickCount( &pObjectInfo->LastAccessCount);
8223                 }
8224
8225                 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
8226
8227                 if( !NT_SUCCESS( ntStatus) ||
8228                     pObjectInfo == NULL)
8229                 {
8230                     try_return( ntStatus = STATUS_INVALID_PARAMETER);
8231                 }
8232             }
8233         }
8234         else
8235         {
8236
8237             if( GetStatusInfo->FileNameLength == 0 ||
8238                 InputBufferLength < (ULONG)(FIELD_OFFSET( AFSGetStatusInfoCB, FileName) + GetStatusInfo->FileNameLength))
8239             {
8240                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8241             }
8242
8243             uniFullPathName.Length = GetStatusInfo->FileNameLength;
8244             uniFullPathName.MaximumLength = uniFullPathName.Length;
8245
8246             uniFullPathName.Buffer = (WCHAR *)GetStatusInfo->FileName;
8247
8248             //
8249             // This name should begin with the \afs server so parse it off and check it
8250             //
8251
8252             FsRtlDissectName( uniFullPathName,
8253                               &uniComponentName,
8254                               &uniRemainingPath);
8255
8256             if( RtlCompareUnicodeString( &uniComponentName,
8257                                          &AFSServerName,
8258                                          TRUE) != 0)
8259             {
8260                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8261                               AFS_TRACE_LEVEL_ERROR,
8262                               "AFSGetObjectStatus Name %wZ contains invalid server name\n",
8263                               &uniFullPathName));
8264
8265                 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
8266             }
8267
8268             uniFullPathName = uniRemainingPath;
8269
8270             uniParsedName = uniFullPathName;
8271
8272             //
8273             // Our name array
8274             //
8275
8276             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
8277                                            0);
8278
8279             if( pNameArray == NULL)
8280             {
8281                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8282             }
8283
8284             pVolumeCB = AFSGlobalRoot;
8285
8286             pParentDirEntry = AFSGlobalRoot->DirectoryCB;
8287
8288             //
8289             // Increment the ref count on the volume and dir entry for correct processing below
8290             //
8291
8292             VolumeReferenceReason = AFS_VOLUME_REFERENCE_GET_OBJECT;
8293
8294             lCount = AFSVolumeIncrement( pVolumeCB,
8295                                          VolumeReferenceReason);
8296
8297             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8298                           AFS_TRACE_LEVEL_VERBOSE,
8299                           "AFSGetObjectStatus Increment2 count on volume %p Reason %u Cnt %d\n",
8300                           pVolumeCB,
8301                           VolumeReferenceReason,
8302                           lCount));
8303
8304             lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
8305
8306             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8307                           AFS_TRACE_LEVEL_VERBOSE,
8308                           "AFSGetObjectStatus Increment count on %wZ DE %p Ccb %p Cnt %d\n",
8309                           &pParentDirEntry->NameInformation.FileName,
8310                           pParentDirEntry,
8311                           NULL,
8312                           lCount));
8313
8314             ntStatus = AFSLocateNameEntry( NULL,
8315                                            NULL,
8316                                            &uniFullPathName,
8317                                            &uniParsedName,
8318                                            pNameArray,
8319                                            AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL |
8320                                                AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL,
8321                                            pVolumeCB,
8322                                            pParentDirEntry,
8323                                            &pNewVolumeCB,
8324                                            &NewVolumeReferenceReason,
8325                                            &pNewParentDirEntry,
8326                                            &pDirectoryEntry,
8327                                            NULL);
8328
8329             if ( pNewVolumeCB != NULL)
8330             {
8331
8332                 //
8333                 // AFSLocateNameEntry returns pNewVolumeCB with a reference held
8334                 // even if pVolumeCB == pNewVolumeCB.  It is always safe to release
8335                 // the reference on pVolumeCB that was held prior to the call.
8336                 // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
8337                 // will be released second.
8338                 //
8339
8340                 lCount = AFSVolumeDecrement( pVolumeCB,
8341                                              VolumeReferenceReason);
8342
8343                 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8344                               AFS_TRACE_LEVEL_VERBOSE,
8345                               "AFSGetObjectStatus Decrement count on volume %p Reason %u Cnt %d\n",
8346                               pVolumeCB,
8347                               VolumeReferenceReason,
8348                               lCount));
8349
8350                 pVolumeCB = pNewVolumeCB;
8351
8352                 pNewVolumeCB = NULL;
8353
8354                 VolumeReferenceReason = NewVolumeReferenceReason;
8355
8356                 NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
8357             }
8358
8359             //
8360             // AFSLocateNameEntry does not alter the reference count of
8361             // pParentDirectoryCB and it returns pNewParentDirectoryCB with
8362             // a reference held.
8363             //
8364
8365             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
8366
8367             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8368                           AFS_TRACE_LEVEL_VERBOSE,
8369                           "AFSGetObjectStatus DecrementX count on %wZ DE %p Cnt %d\n",
8370                           &pParentDirEntry->NameInformation.FileName,
8371                           pParentDirEntry,
8372                           lCount));
8373
8374             pParentDirEntry = pNewParentDirEntry;
8375
8376             pNewParentDirEntry = NULL;
8377
8378             if( !NT_SUCCESS( ntStatus) ||
8379                 ntStatus == STATUS_REPARSE)
8380             {
8381
8382                 pVolumeCB = NULL;
8383
8384                 try_return( ntStatus);
8385             }
8386
8387             pObjectInfo = pDirectoryEntry->ObjectInformation;
8388
8389             AFSAcquireExcl( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
8390                             TRUE);
8391
8392             lCount = AFSObjectInfoIncrement( pObjectInfo,
8393                                              AFS_OBJECT_REFERENCE_STATUS);
8394
8395             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8396                           AFS_TRACE_LEVEL_VERBOSE,
8397                           "AFSGetObjectStatus Increment3 count on object %p Cnt %d\n",
8398                           pObjectInfo,
8399                           lCount));
8400
8401             AFSReleaseResource( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
8402         }
8403
8404         //
8405         // At this point we have an object info block, return the information
8406         //
8407
8408         StatusInfo->FileId = pObjectInfo->FileId;
8409
8410         StatusInfo->TargetFileId = pObjectInfo->TargetFileId;
8411
8412         StatusInfo->Expiration = pObjectInfo->Expiration;
8413
8414         StatusInfo->DataVersion = pObjectInfo->DataVersion;
8415
8416         StatusInfo->FileType = pObjectInfo->FileType;
8417
8418         StatusInfo->ObjectFlags = pObjectInfo->Flags;
8419
8420         StatusInfo->CreationTime = pObjectInfo->CreationTime;
8421
8422         StatusInfo->LastAccessTime = pObjectInfo->LastAccessTime;
8423
8424         StatusInfo->LastWriteTime = pObjectInfo->LastWriteTime;
8425
8426         StatusInfo->ChangeTime = pObjectInfo->ChangeTime;
8427
8428         StatusInfo->FileAttributes = pObjectInfo->FileAttributes;
8429
8430         StatusInfo->EndOfFile = pObjectInfo->EndOfFile;
8431
8432         StatusInfo->AllocationSize = pObjectInfo->AllocationSize;
8433
8434         StatusInfo->EaSize = pObjectInfo->EaSize;
8435
8436         StatusInfo->Links = pObjectInfo->Links;
8437
8438         //
8439         // Return the information length
8440         //
8441
8442         *ReturnLength = sizeof( AFSStatusInfoCB);
8443
8444 try_exit:
8445
8446         if( pDirectoryEntry != NULL)
8447         {
8448
8449             lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
8450
8451             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8452                           AFS_TRACE_LEVEL_VERBOSE,
8453                           "AFSGetObjectStatus Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
8454                           &pDirectoryEntry->NameInformation.FileName,
8455                           pDirectoryEntry,
8456                           NULL,
8457                           lCount));
8458
8459             ASSERT( lCount >= 0);
8460         }
8461
8462         if ( pParentDirEntry != NULL)
8463         {
8464
8465             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
8466
8467             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8468                           AFS_TRACE_LEVEL_VERBOSE,
8469                           "AFSGetObjectStatus Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
8470                           &pParentDirEntry->NameInformation.FileName,
8471                           pParentDirEntry,
8472                           NULL,
8473                           lCount));
8474
8475             ASSERT( lCount >= 0);
8476         }
8477
8478         if( pVolumeCB != NULL)
8479         {
8480
8481             if( pObjectInfo != NULL)
8482             {
8483
8484                 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
8485                                   TRUE);
8486
8487                 lCount = AFSObjectInfoDecrement( pObjectInfo,
8488                                                  AFS_OBJECT_REFERENCE_STATUS);
8489
8490                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8491                               AFS_TRACE_LEVEL_VERBOSE,
8492                               "AFSGetObjectStatus Decrement count on object %p Cnt %d\n",
8493                               pObjectInfo,
8494                               lCount));
8495
8496                 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
8497             }
8498
8499             lCount = AFSVolumeDecrement( pVolumeCB,
8500                                          VolumeReferenceReason);
8501
8502             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8503                           AFS_TRACE_LEVEL_VERBOSE,
8504                           "AFSGetObjectStatus Decrement4 count on volume %p Reason %u Cnt %d\n",
8505                           pVolumeCB,
8506                           VolumeReferenceReason,
8507                           lCount));
8508         }
8509
8510         if( pNameArray != NULL)
8511         {
8512
8513             AFSFreeNameArray( pNameArray);
8514         }
8515     }
8516
8517     return ntStatus;
8518 }
8519
8520 NTSTATUS
8521 AFSCheckSymlinkAccess( IN AFSDirectoryCB *ParentDirectoryCB,
8522                        IN UNICODE_STRING *ComponentName)
8523 {
8524
8525     NTSTATUS ntStatus = STATUS_SUCCESS;
8526     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
8527     AFSDirectoryCB *pDirEntry = NULL;
8528     ULONG ulCRC = 0;
8529     LONG lCount;
8530
8531     __Enter
8532     {
8533
8534         //
8535         // Search for the entry in the parent
8536         //
8537
8538         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8539                       AFS_TRACE_LEVEL_VERBOSE_2,
8540                       "AFSCheckSymlinkAccess Searching for entry %wZ case sensitive\n",
8541                       ComponentName));
8542
8543         ulCRC = AFSGenerateCRC( ComponentName,
8544                                 FALSE);
8545
8546         AFSAcquireShared( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
8547                           TRUE);
8548
8549         AFSLocateCaseSensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
8550                                         ulCRC,
8551                                         &pDirEntry);
8552
8553         if( pDirEntry == NULL)
8554         {
8555
8556             //
8557             // Missed so perform a case insensitive lookup
8558             //
8559
8560             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8561                           AFS_TRACE_LEVEL_VERBOSE_2,
8562                           "AFSCheckSymlinkAccess Searching for entry %wZ case insensitive\n",
8563                           ComponentName));
8564
8565             ulCRC = AFSGenerateCRC( ComponentName,
8566                                     TRUE);
8567
8568             AFSLocateCaseInsensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
8569                                               ulCRC,
8570                                               &pDirEntry);
8571
8572             if( pDirEntry == NULL)
8573             {
8574
8575                 //
8576                 // OK, if this component is a valid short name then try
8577                 // a lookup in the short name tree
8578                 //
8579
8580                 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
8581                     RtlIsNameLegalDOS8Dot3( ComponentName,
8582                                             NULL,
8583                                             NULL))
8584                 {
8585
8586                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8587                                   AFS_TRACE_LEVEL_VERBOSE_2,
8588                                   "AFSCheckSymlinkAccess Searching for entry %wZ short name\n",
8589                                   ComponentName));
8590
8591                     AFSLocateShortNameDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.ShortNameTree,
8592                                                 ulCRC,
8593                                                 &pDirEntry);
8594                 }
8595             }
8596         }
8597
8598         if( pDirEntry != NULL)
8599         {
8600             lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
8601
8602             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8603                           AFS_TRACE_LEVEL_VERBOSE,
8604                           "AFSCheckSymlinkAccess Increment count on %wZ DE %p Ccb %p Cnt %d\n",
8605                           &pDirEntry->NameInformation.FileName,
8606                           pDirEntry,
8607                           NULL,
8608                           lCount));
8609
8610             ASSERT( lCount >= 0);
8611         }
8612
8613         AFSReleaseResource( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
8614
8615         if( pDirEntry == NULL)
8616         {
8617
8618             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8619                           AFS_TRACE_LEVEL_VERBOSE_2,
8620                           "AFSCheckSymlinkAccess Failed to locate entry %wZ ntStatus %08X\n",
8621                           ComponentName,
8622                           STATUS_OBJECT_NAME_NOT_FOUND));
8623
8624             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
8625         }
8626
8627         //
8628         // We have the symlink object but previously failed to process it so return access
8629         // denied.
8630         //
8631
8632         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8633                       AFS_TRACE_LEVEL_VERBOSE_2,
8634                       "AFSCheckSymlinkAccess Failing symlink access to entry %wZ REPARSE_POINT_NOT_RESOLVED\n",
8635                       ComponentName));
8636
8637         ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
8638
8639         lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
8640
8641         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8642                       AFS_TRACE_LEVEL_VERBOSE,
8643                       "AFSCheckSymlinkAccess Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
8644                       &pDirEntry->NameInformation.FileName,
8645                       pDirEntry,
8646                       NULL,
8647                       lCount));
8648
8649         ASSERT( lCount >= 0);
8650
8651 try_exit:
8652
8653         NOTHING;
8654     }
8655
8656     return ntStatus;
8657 }
8658
8659 NTSTATUS
8660 AFSRetrieveFinalComponent( IN UNICODE_STRING *FullPathName,
8661                            OUT UNICODE_STRING *ComponentName)
8662 {
8663
8664     NTSTATUS ntStatus = STATUS_SUCCESS;
8665     UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName;
8666
8667     uniFullPathName = *FullPathName;
8668
8669     while( TRUE)
8670     {
8671
8672         FsRtlDissectName( uniFullPathName,
8673                           &uniComponentName,
8674                           &uniRemainingPath);
8675
8676         if( uniRemainingPath.Length == 0)
8677         {
8678             break;
8679         }
8680
8681         uniFullPathName = uniRemainingPath;
8682     }
8683
8684     if( uniComponentName.Length > 0)
8685     {
8686         *ComponentName = uniComponentName;
8687     }
8688
8689     return ntStatus;
8690 }
8691
8692 void
8693 AFSDumpTraceFiles_Default()
8694 {
8695     return;
8696 }
8697
8698 BOOLEAN
8699 AFSValidNameFormat( IN UNICODE_STRING *FileName)
8700 {
8701
8702     BOOLEAN bIsValidName = TRUE;
8703     USHORT usIndex = 0;
8704
8705     __Enter
8706     {
8707
8708         while( usIndex < FileName->Length/sizeof( WCHAR))
8709         {
8710
8711             if( FileName->Buffer[ usIndex] == L':' ||
8712                 FileName->Buffer[ usIndex] == L'*' ||
8713                 FileName->Buffer[ usIndex] == L'?' ||
8714                 FileName->Buffer[ usIndex] == L'"' ||
8715                 FileName->Buffer[ usIndex] == L'<' ||
8716                 FileName->Buffer[ usIndex] == L'>')
8717             {
8718                 bIsValidName = FALSE;
8719                 break;
8720             }
8721
8722             usIndex++;
8723         }
8724     }
8725
8726     return bIsValidName;
8727 }
8728
8729 NTSTATUS
8730 AFSCreateDefaultSecurityDescriptor()
8731 {
8732
8733     NTSTATUS ntStatus = STATUS_SUCCESS;
8734     PACL pSACL = NULL;
8735     ULONG ulSACLSize = 0;
8736     SYSTEM_MANDATORY_LABEL_ACE* pACE = NULL;
8737     ULONG ulACESize = 0;
8738     SECURITY_DESCRIPTOR *pSecurityDescr = NULL;
8739     ULONG ulSDLength = 0;
8740     SECURITY_DESCRIPTOR *pRelativeSecurityDescr = NULL;
8741     PSID pWorldSID = NULL;
8742     ULONG *pulSubAuthority = NULL;
8743     ULONG ulWorldSIDLEngth = 0;
8744
8745     __Enter
8746     {
8747
8748         ulWorldSIDLEngth = RtlLengthRequiredSid( 1);
8749
8750         pWorldSID = (PSID)ExAllocatePoolWithTag( PagedPool,
8751                                                  ulWorldSIDLEngth,
8752                                                  AFS_GENERIC_MEMORY_29_TAG);
8753
8754         if( pWorldSID == NULL)
8755         {
8756             AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate World SID\n");
8757
8758             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8759         }
8760
8761         RtlZeroMemory( pWorldSID,
8762                        ulWorldSIDLEngth);
8763
8764         RtlInitializeSid( pWorldSID,
8765                           &SeWorldSidAuthority,
8766                           1);
8767
8768         pulSubAuthority = RtlSubAuthoritySid(pWorldSID, 0);
8769         *pulSubAuthority = SECURITY_WORLD_RID;
8770
8771         if( AFSRtlSetSaclSecurityDescriptor == NULL)
8772         {
8773
8774             AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor == NULL\n");
8775         }
8776         else
8777         {
8778
8779             ulACESize = sizeof( SYSTEM_MANDATORY_LABEL_ACE) + 128;
8780
8781             pACE = (SYSTEM_MANDATORY_LABEL_ACE *)ExAllocatePoolWithTag( PagedPool,
8782                                                                         ulACESize,
8783                                                                         AFS_GENERIC_MEMORY_29_TAG);
8784
8785             if( pACE == NULL)
8786             {
8787
8788                 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8789
8790                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8791             }
8792
8793             RtlZeroMemory( pACE,
8794                            ulACESize);
8795
8796             pACE->Header.AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
8797             pACE->Header.AceType = SYSTEM_MANDATORY_LABEL_ACE_TYPE;
8798             pACE->Header.AceSize = FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + (USHORT)RtlLengthSid( SeExports->SeLowMandatorySid);
8799             pACE->Mask = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP;
8800
8801             RtlCopySid( RtlLengthSid( SeExports->SeLowMandatorySid),
8802                         &pACE->SidStart,
8803                         SeExports->SeLowMandatorySid);
8804
8805             ulSACLSize = sizeof(ACL) + RtlLengthSid( SeExports->SeLowMandatorySid) +
8806                 FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + ulACESize;
8807
8808             pSACL = (PACL)ExAllocatePoolWithTag( PagedPool,
8809                                                  ulSACLSize,
8810                                                  AFS_GENERIC_MEMORY_29_TAG);
8811
8812             if( pSACL == NULL)
8813             {
8814
8815                 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8816
8817                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8818             }
8819
8820             ntStatus = RtlCreateAcl( pSACL,
8821                                      ulSACLSize,
8822                                      ACL_REVISION);
8823
8824             if( !NT_SUCCESS( ntStatus))
8825             {
8826
8827                 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateAcl ntStatus %08lX\n",
8828                           ntStatus);
8829
8830                 try_return( ntStatus);
8831             }
8832
8833             ntStatus = RtlAddAce( pSACL,
8834                                   ACL_REVISION,
8835                                   0,
8836                                   pACE,
8837                                   pACE->Header.AceSize);
8838
8839             if( !NT_SUCCESS( ntStatus))
8840             {
8841
8842                 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAddAce ntStatus %08lX\n",
8843                           ntStatus);
8844
8845                 try_return( ntStatus);
8846             }
8847         }
8848
8849         pSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
8850                                                                        sizeof( SECURITY_DESCRIPTOR),
8851                                                                        AFS_GENERIC_MEMORY_27_TAG);
8852
8853         if( pSecurityDescr == NULL)
8854         {
8855
8856             AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8857
8858             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8859         }
8860
8861         ntStatus = RtlCreateSecurityDescriptor( pSecurityDescr,
8862                                                 SECURITY_DESCRIPTOR_REVISION);
8863
8864         if( !NT_SUCCESS( ntStatus))
8865         {
8866
8867             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateSecurityDescriptor ntStatus %08lX\n",
8868                       ntStatus);
8869
8870             try_return( ntStatus);
8871         }
8872
8873         if( AFSRtlSetSaclSecurityDescriptor != NULL)
8874         {
8875             ntStatus = AFSRtlSetSaclSecurityDescriptor( pSecurityDescr,
8876                                                         TRUE,
8877                                                         pSACL,
8878                                                         FALSE);
8879
8880             if( !NT_SUCCESS( ntStatus))
8881             {
8882
8883                 AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor ntStatus %08lX\n",
8884                           ntStatus);
8885
8886                 try_return( ntStatus);
8887             }
8888         }
8889
8890         //
8891         // Add in the group and owner to the SD
8892         //
8893
8894         if( AFSRtlSetGroupSecurityDescriptor != NULL)
8895         {
8896             ntStatus = AFSRtlSetGroupSecurityDescriptor( pSecurityDescr,
8897                                                          pWorldSID,
8898                                                          FALSE);
8899
8900             if( !NT_SUCCESS( ntStatus))
8901             {
8902
8903                 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetGroupSecurityDescriptor failed ntStatus %08lX\n",
8904                           ntStatus);
8905
8906                 try_return( ntStatus);
8907             }
8908         }
8909
8910         ntStatus = RtlSetOwnerSecurityDescriptor( pSecurityDescr,
8911                                                   pWorldSID,
8912                                                   FALSE);
8913
8914         if( !NT_SUCCESS( ntStatus))
8915         {
8916
8917             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetOwnerSecurityDescriptor failed ntStatus %08lX\n",
8918                       ntStatus);
8919
8920             try_return( ntStatus);
8921         }
8922
8923         if( !RtlValidSecurityDescriptor( pSecurityDescr))
8924         {
8925
8926             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlValidSecurityDescriptor NOT\n");
8927
8928             try_return( ntStatus = STATUS_INVALID_PARAMETER);
8929         }
8930
8931         pRelativeSecurityDescr = (SECURITY_DESCRIPTOR *)AFSLibExAllocatePoolWithTag( NonPagedPool,
8932                                                                                      PAGE_SIZE,
8933                                                                                      AFS_GENERIC_MEMORY_27_TAG);
8934
8935         if( pRelativeSecurityDescr == NULL)
8936         {
8937
8938             AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8939
8940             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8941         }
8942
8943         ulSDLength = PAGE_SIZE;
8944
8945         ntStatus = RtlAbsoluteToSelfRelativeSD( pSecurityDescr,
8946                                                 pRelativeSecurityDescr,
8947                                                 &ulSDLength);
8948
8949         if( !NT_SUCCESS( ntStatus))
8950         {
8951
8952             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAbsoluteToSelfRelativeSD ntStatus %08lX\n",
8953                       ntStatus);
8954
8955             try_return( ntStatus);
8956         }
8957
8958         AFSDefaultSD = pRelativeSecurityDescr;
8959
8960 try_exit:
8961
8962         if( !NT_SUCCESS( ntStatus))
8963         {
8964
8965             if( pRelativeSecurityDescr != NULL)
8966             {
8967
8968                 AFSLibExFreePoolWithTag( pRelativeSecurityDescr,
8969                                          AFS_GENERIC_MEMORY_27_TAG);
8970             }
8971         }
8972
8973         if( pSecurityDescr != NULL)
8974         {
8975
8976             AFSLibExFreePoolWithTag( pSecurityDescr,
8977                                      AFS_GENERIC_MEMORY_27_TAG);
8978         }
8979
8980         if( pSACL != NULL)
8981         {
8982
8983             AFSLibExFreePoolWithTag( pSACL,
8984                                      AFS_GENERIC_MEMORY_29_TAG);
8985         }
8986
8987         if( pACE != NULL)
8988         {
8989
8990             AFSLibExFreePoolWithTag( pACE,
8991                                      AFS_GENERIC_MEMORY_29_TAG);
8992         }
8993
8994         if( pWorldSID != NULL)
8995         {
8996
8997             AFSLibExFreePoolWithTag( pWorldSID,
8998                                      AFS_GENERIC_MEMORY_29_TAG);
8999         }
9000     }
9001
9002     return ntStatus;
9003 }
9004
9005 void
9006 AFSRetrieveParentPath( IN UNICODE_STRING *FullFileName,
9007                        OUT UNICODE_STRING *ParentPath)
9008 {
9009
9010     *ParentPath = *FullFileName;
9011
9012     //
9013     // If the final character is a \, jump over it
9014     //
9015
9016     if( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] == L'\\')
9017     {
9018         ParentPath->Length -= sizeof( WCHAR);
9019     }
9020
9021     while( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] != L'\\')
9022     {
9023         ParentPath->Length -= sizeof( WCHAR);
9024     }
9025
9026     //
9027     // And the separator
9028     //
9029
9030     ParentPath->Length -= sizeof( WCHAR);
9031
9032     return;
9033 }
9034
9035 NTSTATUS
9036 AFSRetrieveValidAuthGroup( IN AFSFcb *Fcb,
9037                            IN AFSObjectInfoCB *ObjectInfo,
9038                            IN BOOLEAN WriteAccess,
9039                            OUT GUID *AuthGroup)
9040 {
9041
9042     NTSTATUS ntStatus = STATUS_SUCCESS;
9043     GUID     stAuthGroup, stZeroAuthGroup;
9044     BOOLEAN  bFoundAuthGroup = FALSE;
9045     AFSCcb  *pCcb = NULL;
9046     AFSFcb *pFcb = Fcb;
9047
9048     __Enter
9049     {
9050
9051         RtlZeroMemory( &stAuthGroup,
9052                        sizeof( GUID));
9053
9054         RtlZeroMemory( &stZeroAuthGroup,
9055                        sizeof( GUID));
9056
9057         if( Fcb == NULL)
9058         {
9059
9060             if( ObjectInfo != NULL &&
9061                 ObjectInfo->Fcb != NULL)
9062             {
9063                 pFcb = ObjectInfo->Fcb;
9064             }
9065         }
9066
9067         if( pFcb != NULL)
9068         {
9069
9070             AFSAcquireShared( &Fcb->NPFcb->CcbListLock,
9071                               TRUE);
9072
9073             pCcb = Fcb->CcbListHead;
9074
9075             while( pCcb != NULL)
9076             {
9077
9078                 if( WriteAccess &&
9079                     pCcb->GrantedAccess & FILE_WRITE_DATA)
9080                 {
9081                     RtlCopyMemory( &stAuthGroup,
9082                                    &pCcb->AuthGroup,
9083                                    sizeof( GUID));
9084
9085                     bFoundAuthGroup = TRUE;
9086
9087                     break;
9088                 }
9089                 else if( pCcb->GrantedAccess & FILE_READ_DATA)
9090                 {
9091                     //
9092                     // At least get the read-only access
9093                     //
9094
9095                     RtlCopyMemory( &stAuthGroup,
9096                                    &pCcb->AuthGroup,
9097                                    sizeof( GUID));
9098
9099                     bFoundAuthGroup = TRUE;
9100                 }
9101
9102                 pCcb = (AFSCcb *)pCcb->ListEntry.fLink;
9103             }
9104
9105             AFSReleaseResource( &Fcb->NPFcb->CcbListLock);
9106         }
9107
9108         if( !bFoundAuthGroup)
9109         {
9110
9111             AFSRetrieveAuthGroupFnc( (ULONGLONG)PsGetCurrentProcessId(),
9112                                      (ULONGLONG)PsGetCurrentThreadId(),
9113                                       &stAuthGroup);
9114
9115             if( RtlCompareMemory( &stZeroAuthGroup,
9116                                   &stAuthGroup,
9117                                   sizeof( GUID)) == sizeof( GUID))
9118             {
9119
9120                 DbgPrint("AFSRetrieveValidAuthGroup Failed to locate PAG\n");
9121
9122                 try_return( ntStatus = STATUS_ACCESS_DENIED);
9123             }
9124         }
9125
9126         RtlCopyMemory( AuthGroup,
9127                        &stAuthGroup,
9128                        sizeof( GUID));
9129
9130 try_exit:
9131
9132         NOTHING;
9133     }
9134
9135     return ntStatus;
9136 }
9137
9138 NTSTATUS
9139 AFSPerformObjectInvalidate( IN AFSObjectInfoCB *ObjectInfo,
9140                             IN ULONG InvalidateReason)
9141 {
9142
9143     AFSDeviceExt       *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
9144     NTSTATUS            ntStatus = STATUS_SUCCESS;
9145     LONG                lCount;
9146
9147     __Enter
9148     {
9149
9150         switch( InvalidateReason)
9151         {
9152
9153             case AFS_INVALIDATE_DELETED:
9154             {
9155
9156                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
9157                               AFS_TRACE_LEVEL_VERBOSE,
9158                               "AFSPerformObjectInvalidation on node type %d for FID %08lX-%08lX-%08lX-%08lX Reason DELETED\n",
9159                               ObjectInfo->FileType,
9160                               ObjectInfo->FileId.Cell,
9161                               ObjectInfo->FileId.Volume,
9162                               ObjectInfo->FileId.Vnode,
9163                               ObjectInfo->FileId.Unique));
9164
9165                 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
9166                     ObjectInfo->Fcb != NULL)
9167                 {
9168
9169                     if( !BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
9170                     {
9171
9172                         AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9173                                         TRUE);
9174
9175                         ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
9176
9177                         KeSetEvent( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
9178                                     0,
9179                                     FALSE);
9180
9181                         //
9182                         // Clear out the extents
9183                         // And get rid of them (note this involves waiting
9184                         // for any writes or reads to the cache to complete)
9185                         //
9186
9187                         AFSTearDownFcbExtents( ObjectInfo->Fcb,
9188                                                NULL);
9189
9190                         AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
9191                     }
9192                 }
9193
9194                 ObjectInfo->Links = 0;
9195
9196                 break;
9197             }
9198
9199             case AFS_INVALIDATE_DATA_VERSION:
9200             {
9201
9202                 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
9203                     ObjectInfo->Fcb != NULL)
9204                 {
9205
9206                     if( BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
9207                     {
9208
9209                         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9210                                       AFS_TRACE_LEVEL_VERBOSE,
9211                                       "AFSPerformObjectInvalidate Acquiring Fcb lock %p EXCL %08lX\n",
9212                                       &ObjectInfo->Fcb->NPFcb->Resource,
9213                                       PsGetCurrentThread()));
9214
9215                         AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Resource,
9216                                         TRUE);
9217
9218                         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
9219                                       AFS_TRACE_LEVEL_VERBOSE,
9220                                       "AFSPerformObjectInvalidation DirectIO Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
9221                                       &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9222                                       PsGetCurrentThread()));
9223
9224                         AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9225                                         TRUE);
9226
9227                         __try
9228                         {
9229
9230                             if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
9231                                 !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9232                                                       NULL,
9233                                                       0,
9234                                                       FALSE))
9235                             {
9236
9237                                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9238                                               AFS_TRACE_LEVEL_WARNING,
9239                                               "AFSPerformObjectInvalidation DirectIO CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9240                                               ObjectInfo->FileId.Cell,
9241                                               ObjectInfo->FileId.Volume,
9242                                               ObjectInfo->FileId.Vnode,
9243                                               ObjectInfo->FileId.Unique));
9244
9245                                 SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9246                             }
9247                         }
9248                         __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
9249                         {
9250
9251                             ntStatus = GetExceptionCode();
9252
9253                             AFSDbgTrace(( 0,
9254                                           0,
9255                                           "EXCEPTION - AFSPerformObjectInvalidation DirectIO FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
9256                                           ObjectInfo->FileId.Cell,
9257                                           ObjectInfo->FileId.Volume,
9258                                           ObjectInfo->FileId.Vnode,
9259                                           ObjectInfo->FileId.Unique,
9260                                           ntStatus));
9261
9262                             SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9263                         }
9264
9265                         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
9266                                       AFS_TRACE_LEVEL_VERBOSE,
9267                                       "AFSPerformObjectInvalidation DirectIO Releasing Fcb SectionObject lock %p EXCL %08lX\n",
9268                                       &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9269                                       PsGetCurrentThread()));
9270
9271                         AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
9272
9273                         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9274                                       AFS_TRACE_LEVEL_VERBOSE,
9275                                       "AFSPerformObjectInvalidation DirectIO Releasing Fcb lock %p EXCL %08lX\n",
9276                                       &ObjectInfo->Fcb->NPFcb->Resource,
9277                                       PsGetCurrentThread()));
9278
9279                         AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9280                     }
9281                     else
9282                     {
9283                         LIST_ENTRY         *le;
9284                         AFSExtent          *pEntry;
9285                         ULONG               ulProcessCount = 0;
9286                         ULONG               ulCount = 0;
9287                         LARGE_INTEGER liCurrentOffset = {0,0};
9288                         LARGE_INTEGER liFlushLength = {0,0};
9289                         ULONG ulFlushLength = 0;
9290                         BOOLEAN bLocked = FALSE;
9291                         BOOLEAN bExtentsLocked = FALSE;
9292                         BOOLEAN bCleanExtents = FALSE;
9293
9294                         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9295                                       AFS_TRACE_LEVEL_VERBOSE,
9296                                       "AFSPerformObjectInvalidate Acquiring Fcb lock %p EXCL %08lX\n",
9297                                       &ObjectInfo->Fcb->NPFcb->Resource,
9298                                       PsGetCurrentThread()));
9299
9300                         AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Resource,
9301                                         TRUE);
9302
9303                         bLocked = TRUE;
9304
9305                         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9306                                       AFS_TRACE_LEVEL_VERBOSE,
9307                                       "AFSPerformObjectInvalidate Acquiring Fcb extents lock %p SHARED %08lX\n",
9308                                       &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9309                                       PsGetCurrentThread()));
9310
9311                         AFSAcquireShared( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9312                                           TRUE);
9313
9314                         bExtentsLocked = TRUE;
9315
9316                         //
9317                         // There are several possibilities here:
9318                         //
9319                         // 0. If there are no extents or all of the extents are dirty, do nothing.
9320                         //
9321                         // 1. There could be nothing dirty and an open reference count of zero
9322                         //    in which case we can just tear down all of the extents without
9323                         //    holding any resources.
9324                         //
9325                         // 2. There could be nothing dirty and a non-zero open reference count
9326                         //    in which case we can issue a CcPurge against the entire file
9327                         //    while holding just the Fcb Resource.
9328                         //
9329                         // 3. There can be dirty extents in which case we need to identify
9330                         //    the non-dirty ranges and then perform a CcPurge on just the
9331                         //    non-dirty ranges while holding just the Fcb Resource.
9332                         //
9333
9334                         if ( ObjectInfo->Fcb->Specific.File.ExtentCount != ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount)
9335                         {
9336
9337                             if ( ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount == 0)
9338                             {
9339
9340                                 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9341
9342                                 bExtentsLocked = FALSE;
9343
9344                                 if ( ObjectInfo->Fcb->OpenReferenceCount == 0)
9345                                 {
9346
9347                                     AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9348
9349                                     bLocked = FALSE;
9350
9351                                     AFSTearDownFcbExtents( ObjectInfo->Fcb,
9352                                                            NULL);
9353                                 }
9354                                 else
9355                                 {
9356
9357                                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
9358                                                   AFS_TRACE_LEVEL_VERBOSE,
9359                                                   "AFSPerformObjectInvalidation Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
9360                                                   &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9361                                                   PsGetCurrentThread()));
9362
9363                                     AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9364                                                     TRUE);
9365
9366                                     __try
9367                                     {
9368
9369                                         if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
9370                                             !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9371                                                                   NULL,
9372                                                                   0,
9373                                                                   FALSE))
9374                                         {
9375
9376                                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9377                                                           AFS_TRACE_LEVEL_WARNING,
9378                                                           "AFSPerformObjectInvalidation CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9379                                                           ObjectInfo->FileId.Cell,
9380                                                           ObjectInfo->FileId.Volume,
9381                                                           ObjectInfo->FileId.Vnode,
9382                                                           ObjectInfo->FileId.Unique));
9383
9384                                             SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9385                                         }
9386                                         else
9387                                         {
9388
9389                                             bCleanExtents = TRUE;
9390                                         }
9391                                     }
9392                                     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
9393                                     {
9394
9395                                         ntStatus = GetExceptionCode();
9396
9397                                         AFSDbgTrace(( 0,
9398                                                       0,
9399                                                       "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
9400                                                       ObjectInfo->FileId.Cell,
9401                                                       ObjectInfo->FileId.Volume,
9402                                                       ObjectInfo->FileId.Vnode,
9403                                                       ObjectInfo->FileId.Unique,
9404                                                       ntStatus));
9405
9406                                         SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9407                                     }
9408
9409                                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
9410                                                   AFS_TRACE_LEVEL_VERBOSE,
9411                                                   "AFSPerformObjectInvalidation Releasing Fcb SectionObject lock %p EXCL %08lX\n",
9412                                                   &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9413                                                   PsGetCurrentThread()));
9414
9415                                     AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
9416
9417                                     AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9418
9419                                     bLocked = FALSE;
9420                                 }
9421                             }
9422                             else
9423                             {
9424
9425                                 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9426
9427                                 bExtentsLocked = FALSE;
9428
9429                                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
9430                                               AFS_TRACE_LEVEL_VERBOSE,
9431                                               "AFSPerformObjectInvalidation Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
9432                                               &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9433                                               PsGetCurrentThread()));
9434
9435                                 AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9436                                                 TRUE);
9437
9438                                 //
9439                                 // Must build a list of non-dirty ranges from the beginning of the file
9440                                 // to the end.  There can be at most (Fcb->Specific.File.ExtentsDirtyCount + 1)
9441                                 // ranges.  In all but the most extreme random data write scenario there will
9442                                 // be significantly fewer.
9443                                 //
9444                                 // For each range we need offset and size.
9445                                 //
9446
9447                                 AFSByteRange * ByteRangeList = NULL;
9448                                 ULONG          ulByteRangeCount = 0;
9449                                 ULONG          ulIndex;
9450                                 BOOLEAN        bPurgeOnClose = FALSE;
9451
9452                                 __try
9453                                 {
9454
9455                                     ulByteRangeCount = AFSConstructCleanByteRangeList( ObjectInfo->Fcb,
9456                                                                                        &ByteRangeList);
9457
9458                                     if ( ByteRangeList != NULL ||
9459                                          ulByteRangeCount == 0)
9460                                     {
9461
9462                                         for ( ulIndex = 0; ulIndex < ulByteRangeCount; ulIndex++)
9463                                         {
9464
9465                                             ULONG ulSize;
9466
9467                                             do {
9468
9469                                                 ulSize = ByteRangeList[ulIndex].Length.QuadPart > DWORD_MAX ? DWORD_MAX : ByteRangeList[ulIndex].Length.LowPart;
9470
9471                                                 if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
9472                                                     !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9473                                                                           &ByteRangeList[ulIndex].FileOffset,
9474                                                                           ulSize,
9475                                                                           FALSE))
9476                                                 {
9477
9478                                                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9479                                                                   AFS_TRACE_LEVEL_WARNING,
9480                                                                   "AFSPerformObjectInvalidation [1] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9481                                                                   ObjectInfo->FileId.Cell,
9482                                                                   ObjectInfo->FileId.Volume,
9483                                                                   ObjectInfo->FileId.Vnode,
9484                                                                   ObjectInfo->FileId.Unique));
9485
9486                                                     bPurgeOnClose = TRUE;
9487                                                 }
9488                                                 else
9489                                                 {
9490
9491                                                     bCleanExtents = TRUE;
9492                                                 }
9493
9494                                                 ByteRangeList[ulIndex].Length.QuadPart -= ulSize;
9495
9496                                                 ByteRangeList[ulIndex].FileOffset.QuadPart += ulSize;
9497
9498                                             } while ( ByteRangeList[ulIndex].Length.QuadPart > 0);
9499                                         }
9500                                     }
9501                                     else
9502                                     {
9503
9504                                         //
9505                                         // We couldn't allocate the memory to build the purge list
9506                                         // so just walk the extent list while holding the ExtentsList Resource.
9507                                         // This could deadlock but we do not have much choice.
9508                                         //
9509
9510                                         AFSAcquireExcl(  &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9511                                                         TRUE);
9512                                         bExtentsLocked = TRUE;
9513
9514                                         le = ObjectInfo->Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
9515
9516                                         ulProcessCount = 0;
9517
9518                                         ulCount = (ULONG)ObjectInfo->Fcb->Specific.File.ExtentCount;
9519
9520                                         if( ulCount > 0)
9521                                         {
9522                                             pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
9523
9524                                             while( ulProcessCount < ulCount)
9525                                             {
9526                                                 pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
9527
9528                                                 if( !BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
9529                                                 {
9530                                                     if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9531                                                                               &pEntry->FileOffset,
9532                                                                               pEntry->Size,
9533                                                                               FALSE))
9534                                                     {
9535
9536                                                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9537                                                                       AFS_TRACE_LEVEL_WARNING,
9538                                                                       "AFSPerformObjectInvalidation [2] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9539                                                                       ObjectInfo->FileId.Cell,
9540                                                                       ObjectInfo->FileId.Volume,
9541                                                                       ObjectInfo->FileId.Vnode,
9542                                                                       ObjectInfo->FileId.Unique));
9543
9544                                                         bPurgeOnClose = TRUE;
9545                                                     }
9546                                                     else
9547                                                     {
9548
9549                                                         bCleanExtents = TRUE;
9550                                                     }
9551                                                 }
9552
9553                                                 if( liCurrentOffset.QuadPart < pEntry->FileOffset.QuadPart)
9554                                                 {
9555
9556                                                     liFlushLength.QuadPart = pEntry->FileOffset.QuadPart - liCurrentOffset.QuadPart;
9557
9558                                                     while( liFlushLength.QuadPart > 0)
9559                                                     {
9560
9561                                                         if( liFlushLength.QuadPart > 512 * 1024000)
9562                                                         {
9563                                                             ulFlushLength = 512 * 1024000;
9564                                                         }
9565                                                         else
9566                                                         {
9567                                                             ulFlushLength = liFlushLength.LowPart;
9568                                                         }
9569
9570                                                         if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9571                                                                                   &liCurrentOffset,
9572                                                                                   ulFlushLength,
9573                                                                                   FALSE))
9574                                                         {
9575
9576                                                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9577                                                                           AFS_TRACE_LEVEL_WARNING,
9578                                                                           "AFSPerformObjectInvalidation [3] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9579                                                                           ObjectInfo->FileId.Cell,
9580                                                                           ObjectInfo->FileId.Volume,
9581                                                                           ObjectInfo->FileId.Vnode,
9582                                                                           ObjectInfo->FileId.Unique));
9583
9584                                                             bPurgeOnClose = TRUE;
9585                                                         }
9586                                                         else
9587                                                         {
9588
9589                                                             bCleanExtents = TRUE;
9590                                                         }
9591
9592                                                         liFlushLength.QuadPart -= ulFlushLength;
9593                                                     }
9594                                                 }
9595
9596                                                 liCurrentOffset.QuadPart = pEntry->FileOffset.QuadPart + pEntry->Size;
9597
9598                                                 ulProcessCount++;
9599                                                 le = le->Flink;
9600                                             }
9601                                         }
9602                                         else
9603                                         {
9604                                             if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9605                                                                       NULL,
9606                                                                       0,
9607                                                                       FALSE))
9608                                             {
9609
9610                                                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9611                                                               AFS_TRACE_LEVEL_WARNING,
9612                                                               "AFSPerformObjectInvalidation [4] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9613                                                               ObjectInfo->FileId.Cell,
9614                                                               ObjectInfo->FileId.Volume,
9615                                                               ObjectInfo->FileId.Vnode,
9616                                                               ObjectInfo->FileId.Unique));
9617
9618                                                 bPurgeOnClose = TRUE;
9619                                             }
9620                                             else
9621                                             {
9622
9623                                                 bCleanExtents = TRUE;
9624                                             }
9625                                         }
9626
9627                                         if ( bPurgeOnClose)
9628                                         {
9629
9630                                             SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9631                                         }
9632                                     }
9633                                 }
9634                                 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
9635                                 {
9636
9637                                     ntStatus = GetExceptionCode();
9638
9639                                     AFSDbgTrace(( 0,
9640                                                   0,
9641                                                   "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
9642                                                   ObjectInfo->FileId.Cell,
9643                                                   ObjectInfo->FileId.Volume,
9644                                                   ObjectInfo->FileId.Vnode,
9645                                                   ObjectInfo->FileId.Unique,
9646                                                   ntStatus));
9647                                 }
9648
9649                                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
9650                                               AFS_TRACE_LEVEL_VERBOSE,
9651                                               "AFSPerformObjectInvalidation Releasing Fcb SectionObject lock %p EXCL %08lX\n",
9652                                               &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9653                                               PsGetCurrentThread()));
9654
9655                                 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
9656
9657                                 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9658
9659                                 bLocked = FALSE;
9660                             }
9661                         }
9662
9663                         if ( bExtentsLocked)
9664                         {
9665
9666                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9667                         }
9668
9669                         if ( bLocked)
9670                         {
9671
9672                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9673                         }
9674
9675                         if ( bCleanExtents)
9676                         {
9677
9678                             AFSReleaseCleanExtents( ObjectInfo->Fcb,
9679                                                     NULL);
9680                         }
9681                     }
9682                 }
9683
9684                 break;
9685             }
9686         }
9687
9688         //
9689         // Destroy the reference passed in by the caller to AFSInvalidateObject
9690         // or AFSQueueInvalidateObject
9691         //
9692
9693         AFSAcquireShared( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
9694                           TRUE);
9695
9696         lCount = AFSObjectInfoDecrement( ObjectInfo,
9697                                          AFS_OBJECT_REFERENCE_INVALIDATION);
9698
9699         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
9700                       AFS_TRACE_LEVEL_VERBOSE,
9701                       "AFSPerformObjectInvalidation Decrement count on object %p Cnt %d\n",
9702                       ObjectInfo,
9703                       lCount));
9704
9705         AFSReleaseResource( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
9706     }
9707
9708     return ntStatus;
9709 }
9710
9711 BOOLEAN
9712 AFSIgnoreReparsePointToFile( void)
9713 {
9714     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
9715     BOOLEAN bIgnoreReparsePoint;
9716
9717     {
9718
9719         bIgnoreReparsePoint = BooleanFlagOn( pDeviceExt->Specific.RDR.ReparsePointPolicy,
9720                                              AFS_REPARSE_POINT_TO_FILE_AS_FILE);
9721     }
9722
9723     return bIgnoreReparsePoint;
9724 }