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