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