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