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