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