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