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