ce9fffc3ff2fef227ed36a65332aa8df1d793424
[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 void
5072 AFSSetEnumerationEvent( IN AFSFcb *Fcb)
5073 {
5074     LONG lCount;
5075
5076     //
5077     // Depending on the type of node, set the event
5078     //
5079
5080     switch( Fcb->Header.NodeTypeCode)
5081     {
5082
5083         case AFS_DIRECTORY_FCB:
5084         case AFS_ROOT_FCB:
5085         case AFS_ROOT_ALL:
5086         {
5087
5088             lCount = InterlockedIncrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
5089
5090             break;
5091         }
5092     }
5093
5094     return;
5095 }
5096
5097 void
5098 AFSClearEnumerationEvent( IN AFSFcb *Fcb)
5099 {
5100
5101     LONG lCount;
5102
5103     //
5104     // Depending on the type of node, set the event
5105     //
5106
5107     switch( Fcb->Header.NodeTypeCode)
5108     {
5109
5110         case AFS_DIRECTORY_FCB:
5111         case AFS_ROOT_FCB:
5112         case AFS_ROOT_ALL:
5113         {
5114
5115             ASSERT( Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0);
5116
5117             lCount = InterlockedDecrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
5118
5119             break;
5120         }
5121     }
5122
5123     return;
5124 }
5125
5126 BOOLEAN
5127 AFSIsEnumerationInProcess( IN AFSObjectInfoCB *ObjectInfo)
5128 {
5129
5130     BOOLEAN bIsInProcess = FALSE;
5131
5132     __Enter
5133     {
5134
5135         if( ObjectInfo->Fcb == NULL)
5136         {
5137
5138             try_return( bIsInProcess);
5139         }
5140
5141         switch( ObjectInfo->Fcb->Header.NodeTypeCode)
5142         {
5143
5144             case AFS_DIRECTORY_FCB:
5145             case AFS_ROOT_FCB:
5146             case AFS_ROOT_ALL:
5147             {
5148
5149                 if( ObjectInfo->Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0)
5150                 {
5151
5152                     bIsInProcess = TRUE;
5153                 }
5154
5155                 break;
5156             }
5157         }
5158
5159 try_exit:
5160
5161         NOTHING;
5162     }
5163
5164     return bIsInProcess;
5165 }
5166
5167 NTSTATUS
5168 AFSVerifyVolume( IN ULONGLONG ProcessId,
5169                  IN AFSVolumeCB *VolumeCB)
5170 {
5171
5172     UNREFERENCED_PARAMETER(ProcessId);
5173     UNREFERENCED_PARAMETER(VolumeCB);
5174     NTSTATUS ntStatus = STATUS_SUCCESS;
5175
5176
5177     return ntStatus;
5178 }
5179
5180 NTSTATUS
5181 AFSInitPIOCtlDirectoryCB( IN AFSObjectInfoCB *ParentObjectInfo)
5182 {
5183
5184     NTSTATUS ntStatus = STATUS_SUCCESS;
5185     AFSObjectInfoCB *pObjectInfoCB = NULL;
5186     AFSDirectoryCB *pDirNode = NULL;
5187     ULONG ulEntryLength = 0;
5188     AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
5189     LONG lCount;
5190
5191     __Enter
5192     {
5193
5194         pObjectInfoCB = AFSAllocateObjectInfo( ParentObjectInfo,
5195                                                0);
5196
5197         if( pObjectInfoCB == NULL)
5198         {
5199
5200             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5201         }
5202
5203         lCount = AFSObjectInfoIncrement( pObjectInfoCB,
5204                                          AFS_OBJECT_REFERENCE_DIRENTRY);
5205
5206         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
5207                       AFS_TRACE_LEVEL_VERBOSE,
5208                       "AFSInitPIOCtlDirectoryCB Increment count on object %p Cnt %d\n",
5209                       pObjectInfoCB,
5210                       lCount));
5211
5212         pObjectInfoCB->FileType = (ULONG) AFS_FILE_TYPE_PIOCTL;
5213
5214         pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
5215
5216         ulEntryLength = sizeof( AFSDirectoryCB) + AFSPIOCtlName.Length;
5217
5218         pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
5219                                                                ulEntryLength,
5220                                                                AFS_DIR_ENTRY_TAG);
5221
5222         if( pDirNode == NULL)
5223         {
5224
5225             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5226         }
5227
5228         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
5229                       AFS_TRACE_LEVEL_VERBOSE,
5230                       "AFSInitPIOCtlDirectoryCB AFS_DIR_ENTRY_TAG allocated %p\n",
5231                       pDirNode));
5232
5233         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
5234                                                                                 sizeof( AFSNonPagedDirectoryCB),
5235                                                                                 AFS_DIR_ENTRY_NP_TAG);
5236
5237         if( pNonPagedDirEntry == NULL)
5238         {
5239
5240             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5241         }
5242
5243         RtlZeroMemory( pDirNode,
5244                        ulEntryLength);
5245
5246         RtlZeroMemory( pNonPagedDirEntry,
5247                        sizeof( AFSNonPagedDirectoryCB));
5248
5249         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
5250
5251         pDirNode->NonPaged = pNonPagedDirEntry;
5252
5253         pDirNode->ObjectInformation = pObjectInfoCB;
5254
5255         pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_PIOCTL_INDEX;
5256
5257         //
5258         // Set valid entry
5259         //
5260
5261         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_FAKE);
5262
5263         pDirNode->NameInformation.FileName.Length = AFSPIOCtlName.Length;
5264
5265         pDirNode->NameInformation.FileName.MaximumLength = AFSPIOCtlName.Length;
5266
5267         pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
5268
5269         RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
5270                        AFSPIOCtlName.Buffer,
5271                        pDirNode->NameInformation.FileName.Length);
5272
5273         pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
5274                                                                        TRUE);
5275
5276         if ( InterlockedCompareExchangePointer( (PVOID *)&ParentObjectInfo->Specific.Directory.PIOCtlDirectoryCB, pDirNode, NULL) != NULL)
5277         {
5278
5279             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5280                           AFS_TRACE_LEVEL_WARNING,
5281                           "AFSInitPIOCtlDirectoryCB Raced PIOCtlDirectoryCB %p pFcb %p\n",
5282                           ParentObjectInfo->Specific.Directory.PIOCtlDirectoryCB,
5283                           pDirNode));
5284
5285             try_return( ntStatus = STATUS_REPARSE);
5286         }
5287
5288 try_exit:
5289
5290         if ( ntStatus != STATUS_SUCCESS)
5291         {
5292
5293             if ( pDirNode != NULL)
5294             {
5295
5296                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
5297                               AFS_TRACE_LEVEL_VERBOSE,
5298                               "AFSInitPIOCtlDirectoryCB AFS_DIR_ENTRY_TAG deallocating %p\n",
5299                               pDirNode));
5300
5301                 AFSExFreePoolWithTag( pDirNode, AFS_DIR_ENTRY_TAG);
5302             }
5303
5304             if( pNonPagedDirEntry != NULL)
5305             {
5306
5307                 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
5308
5309                 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
5310             }
5311
5312             if ( pObjectInfoCB != NULL)
5313             {
5314
5315                 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
5316                                                  AFS_OBJECT_REFERENCE_DIRENTRY);
5317
5318                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
5319                               AFS_TRACE_LEVEL_VERBOSE,
5320                               "AFSInitPIOCtlDirectoryCB Decrement count on object %p Cnt %d\n",
5321                               pObjectInfoCB,
5322                               lCount));
5323
5324                 AFSDeleteObjectInfo( &pObjectInfoCB);
5325             }
5326         }
5327     }
5328
5329     return ntStatus;
5330 }
5331
5332 NTSTATUS
5333 AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB,
5334                            IN AFSDirectoryCB *DirectoryCB,
5335                            IN UNICODE_STRING *ParentPathName,
5336                            IN AFSNameArrayHdr *RelatedNameArray,
5337                            IN GUID           *AuthGroup,
5338                            OUT AFSFileInfoCB *FileInfo)
5339 {
5340
5341     NTSTATUS ntStatus = STATUS_SUCCESS;
5342     AFSDirEnumEntry *pDirEntry = NULL;
5343     UNICODE_STRING uniFullPathName = {0};
5344     AFSNameArrayHdr    *pNameArray = NULL;
5345     AFSVolumeCB *pVolumeCB = NULL;
5346     LONG VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
5347     AFSVolumeCB *pNewVolumeCB = NULL;
5348     LONG NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
5349     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
5350     AFSDirectoryCB *pNewParentDirEntry = NULL;
5351     WCHAR *pwchBuffer = NULL;
5352     UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
5353     ULONG ulNameDifference = 0;
5354     LONG lCount;
5355
5356     __Enter
5357     {
5358
5359         //
5360         // Retrieve a target name for the entry
5361         //
5362
5363         AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
5364                           TRUE);
5365
5366         if( DirectoryCB->NameInformation.TargetName.Length == 0)
5367         {
5368
5369             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5370
5371             ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
5372                                               AuthGroup,
5373                                               FALSE,
5374                                               &pDirEntry);
5375
5376             if( !NT_SUCCESS( ntStatus) ||
5377                 pDirEntry->TargetNameLength == 0)
5378             {
5379
5380                 if( pDirEntry != NULL)
5381                 {
5382
5383                     ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
5384                 }
5385
5386                 try_return( ntStatus);
5387             }
5388
5389             AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
5390                             TRUE);
5391
5392             if( DirectoryCB->NameInformation.TargetName.Length == 0)
5393             {
5394
5395                 //
5396                 // Update the target name
5397                 //
5398
5399                 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
5400                                                 &DirectoryCB->Flags,
5401                                                 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
5402                                                 (USHORT)pDirEntry->TargetNameLength);
5403
5404                 if( !NT_SUCCESS( ntStatus))
5405                 {
5406
5407                     AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5408
5409                     try_return( ntStatus);
5410                 }
5411             }
5412
5413             AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
5414         }
5415
5416         //
5417         // Need to pass the full path in for parsing.
5418         //
5419
5420         if( AFSIsRelativeName( &DirectoryCB->NameInformation.TargetName))
5421         {
5422
5423             uniFullPathName.Length = 0;
5424             uniFullPathName.MaximumLength = ParentPathName->Length +
5425                                                     sizeof( WCHAR) +
5426                                                     DirectoryCB->NameInformation.TargetName.Length;
5427
5428             uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5429                                                                         uniFullPathName.MaximumLength,
5430                                                                         AFS_NAME_BUFFER_SIX_TAG);
5431
5432             if( uniFullPathName.Buffer == NULL)
5433             {
5434
5435                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5436
5437                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5438             }
5439
5440             pwchBuffer = uniFullPathName.Buffer;
5441
5442             RtlZeroMemory( uniFullPathName.Buffer,
5443                            uniFullPathName.MaximumLength);
5444
5445             RtlCopyMemory( uniFullPathName.Buffer,
5446                            ParentPathName->Buffer,
5447                            ParentPathName->Length);
5448
5449             uniFullPathName.Length = ParentPathName->Length;
5450
5451             if( uniFullPathName.Buffer[ (uniFullPathName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
5452                 DirectoryCB->NameInformation.TargetName.Buffer[ 0] != L'\\')
5453             {
5454
5455                 uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)] = L'\\';
5456
5457                 uniFullPathName.Length += sizeof( WCHAR);
5458             }
5459
5460             RtlCopyMemory( &uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)],
5461                            DirectoryCB->NameInformation.TargetName.Buffer,
5462                            DirectoryCB->NameInformation.TargetName.Length);
5463
5464             uniFullPathName.Length += DirectoryCB->NameInformation.TargetName.Length;
5465
5466             uniParsedName.Length = uniFullPathName.Length - ParentPathName->Length;
5467             uniParsedName.MaximumLength = uniParsedName.Length;
5468
5469             uniParsedName.Buffer = &uniFullPathName.Buffer[ ParentPathName->Length/sizeof( WCHAR)];
5470
5471             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5472
5473             //
5474             // We populate up to the current parent
5475             //
5476
5477             if( RelatedNameArray != NULL)
5478             {
5479
5480                 pNameArray = AFSInitNameArray( NULL,
5481                                                RelatedNameArray->MaxElementCount);
5482
5483                 if( pNameArray == NULL)
5484                 {
5485
5486                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5487                 }
5488
5489                 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
5490                                                                  RelatedNameArray,
5491                                                                  ParentDirectoryCB);
5492             }
5493             else
5494             {
5495
5496                 pNameArray = AFSInitNameArray( NULL,
5497                                                0);
5498
5499                 if( pNameArray == NULL)
5500                 {
5501
5502                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5503                 }
5504
5505                 ntStatus = AFSPopulateNameArray( pNameArray,
5506                                                  NULL,
5507                                                  ParentDirectoryCB);
5508             }
5509
5510             if( !NT_SUCCESS( ntStatus))
5511             {
5512
5513                 try_return( ntStatus);
5514             }
5515
5516             pVolumeCB = ParentDirectoryCB->ObjectInformation->VolumeCB;
5517
5518             pParentDirEntry = ParentDirectoryCB;
5519         }
5520         else
5521         {
5522
5523             uniFullPathName.Length = 0;
5524             uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
5525
5526             uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5527                                                                         uniFullPathName.MaximumLength,
5528                                                                         AFS_NAME_BUFFER_SEVEN_TAG);
5529
5530             if( uniFullPathName.Buffer == NULL)
5531             {
5532
5533                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5534
5535                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5536             }
5537
5538             pwchBuffer = uniFullPathName.Buffer;
5539
5540             RtlZeroMemory( uniFullPathName.Buffer,
5541                            uniFullPathName.MaximumLength);
5542
5543             RtlCopyMemory( uniFullPathName.Buffer,
5544                            DirectoryCB->NameInformation.TargetName.Buffer,
5545                            DirectoryCB->NameInformation.TargetName.Length);
5546
5547             uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
5548
5549             //
5550             // This name should begin with the \afs server so parse it off and check it
5551             //
5552
5553             FsRtlDissectName( uniFullPathName,
5554                               &uniComponentName,
5555                               &uniRemainingPath);
5556
5557             if( RtlCompareUnicodeString( &uniComponentName,
5558                                          &AFSServerName,
5559                                          TRUE) != 0)
5560             {
5561
5562                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5563
5564                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5565                               AFS_TRACE_LEVEL_ERROR,
5566                               "AFSRetrieveFileAttributes Name %wZ contains invalid server name\n",
5567                               &uniFullPathName));
5568
5569                 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
5570             }
5571
5572             uniFullPathName = uniRemainingPath;
5573
5574             uniParsedName = uniFullPathName;
5575
5576             ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
5577
5578             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5579
5580             //
5581             // Our name array
5582             //
5583
5584             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
5585                                            0);
5586
5587             if( pNameArray == NULL)
5588             {
5589
5590                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5591             }
5592
5593             pVolumeCB = AFSGlobalRoot;
5594
5595             pParentDirEntry = AFSGlobalRoot->DirectoryCB;
5596         }
5597
5598         //
5599         // Increment the ref count on the volume and dir entry for correct processing below
5600         //
5601
5602         VolumeReferenceReason = AFS_VOLUME_REFERENCE_FILE_ATTRS;
5603
5604         lCount = AFSVolumeIncrement( pVolumeCB,
5605                                      VolumeReferenceReason);
5606
5607         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
5608                       AFS_TRACE_LEVEL_VERBOSE,
5609                       "AFSRetrieveFileAttributes Increment count on volume %p Reason %u Cnt %d\n",
5610                       pVolumeCB,
5611                       VolumeReferenceReason,
5612                       lCount));
5613
5614         lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
5615
5616         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5617                       AFS_TRACE_LEVEL_VERBOSE,
5618                       "AFSRetrieveFileAttributes Increment count on %wZ DE %p Ccb %p Cnt %d\n",
5619                       &pParentDirEntry->NameInformation.FileName,
5620                       pParentDirEntry,
5621                       NULL,
5622                       lCount));
5623
5624         ntStatus = AFSLocateNameEntry( NULL,
5625                                        NULL,
5626                                        &uniFullPathName,
5627                                        &uniParsedName,
5628                                        pNameArray,
5629                                        AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL,
5630                                        pVolumeCB,
5631                                        pParentDirEntry,
5632                                        &pNewVolumeCB,
5633                                        &NewVolumeReferenceReason,
5634                                        &pNewParentDirEntry,
5635                                        &pDirectoryEntry,
5636                                        NULL);
5637
5638         if ( pNewVolumeCB != NULL)
5639         {
5640             //
5641             // AFSLocateNameEntry returns pNewVolumeCB with a reference held
5642             // even if pVolumeCB == pNewVolumeCB.  It is always safe to release
5643             // the reference on pVolumeCB that was held prior to the call.
5644             // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
5645             // will be released second.
5646             //
5647
5648             lCount = AFSVolumeDecrement( pVolumeCB,
5649                                          VolumeReferenceReason);
5650
5651             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
5652                           AFS_TRACE_LEVEL_VERBOSE,
5653                           "AFSRetrieveFileAttributes Decrement count on volume %p Reason %u Cnt %d\n",
5654                           pVolumeCB,
5655                           VolumeReferenceReason,
5656                           lCount));
5657
5658             pVolumeCB = pNewVolumeCB;
5659
5660             pNewVolumeCB = NULL;
5661
5662             VolumeReferenceReason = NewVolumeReferenceReason;
5663
5664             NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
5665         }
5666
5667         //
5668         // AFSLocateNameEntry does not alter the reference count of
5669         // pParentDirectoryCB and it returns pNewParentDirectoryCB with
5670         // a reference held.
5671         //
5672
5673         lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
5674
5675         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5676                       AFS_TRACE_LEVEL_VERBOSE,
5677                       "AFSRetrieveFileAttributes DecrementX count on %wZ DE %p Cnt %d\n",
5678                       &pParentDirEntry->NameInformation.FileName,
5679                       pParentDirEntry,
5680                       lCount));
5681
5682         pParentDirEntry = pNewParentDirEntry;
5683
5684         pNewParentDirEntry = NULL;
5685
5686         if( !NT_SUCCESS( ntStatus) ||
5687             ntStatus == STATUS_REPARSE)
5688         {
5689
5690             try_return( ntStatus);
5691         }
5692
5693         //
5694         // Store off the information
5695         //
5696
5697         FileInfo->FileAttributes = pDirectoryEntry->ObjectInformation->FileAttributes;
5698
5699         //
5700         // Check for the mount point being returned
5701         //
5702
5703         if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
5704             pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DFSLINK)
5705         {
5706
5707             FileInfo->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
5708         }
5709         else if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
5710         {
5711
5712             if ( FileInfo->FileAttributes == FILE_ATTRIBUTE_NORMAL)
5713             {
5714
5715                 FileInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
5716             }
5717             else
5718             {
5719
5720                 FileInfo->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
5721             }
5722         }
5723
5724         FileInfo->AllocationSize = pDirectoryEntry->ObjectInformation->AllocationSize;
5725
5726         FileInfo->EndOfFile = pDirectoryEntry->ObjectInformation->EndOfFile;
5727
5728         FileInfo->CreationTime = pDirectoryEntry->ObjectInformation->CreationTime;
5729
5730         FileInfo->LastAccessTime = pDirectoryEntry->ObjectInformation->LastAccessTime;
5731
5732         FileInfo->LastWriteTime = pDirectoryEntry->ObjectInformation->LastWriteTime;
5733
5734         FileInfo->ChangeTime = pDirectoryEntry->ObjectInformation->ChangeTime;
5735
5736 try_exit:
5737
5738         if( pDirEntry != NULL)
5739         {
5740
5741             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
5742         }
5743
5744         if( pDirectoryEntry != NULL)
5745         {
5746
5747             lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
5748
5749             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5750                           AFS_TRACE_LEVEL_VERBOSE,
5751                           "AFSRetrieveFileAttributes Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
5752                           &pDirectoryEntry->NameInformation.FileName,
5753                           pDirectoryEntry,
5754                           NULL,
5755                           lCount));
5756
5757             ASSERT( lCount >= 0);
5758         }
5759
5760         if ( pParentDirEntry != NULL)
5761         {
5762
5763             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
5764
5765             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5766                           AFS_TRACE_LEVEL_VERBOSE,
5767                           "AFSRetrieveFileAttributes Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
5768                           &pParentDirEntry->NameInformation.FileName,
5769                           pParentDirEntry,
5770                           NULL,
5771                           lCount));
5772
5773             ASSERT( lCount >= 0);
5774         }
5775
5776         if( pVolumeCB != NULL)
5777         {
5778
5779             lCount = AFSVolumeDecrement( pVolumeCB,
5780                                          VolumeReferenceReason);
5781
5782             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
5783                           AFS_TRACE_LEVEL_VERBOSE,
5784                           "AFSRetrieveFileAttributes Decrement2 count on volume %p Reason %u Cnt %d\n",
5785                           pVolumeCB,
5786                           VolumeReferenceReason,
5787                           lCount));
5788         }
5789
5790         if( pNameArray != NULL)
5791         {
5792
5793             AFSFreeNameArray( pNameArray);
5794         }
5795
5796         if( pwchBuffer != NULL)
5797         {
5798
5799             //
5800             // Always free the buffer that we allocated as AFSLocateNameEntry
5801             // will not free it.  If uniFullPathName.Buffer was allocated by
5802             // AFSLocateNameEntry, then we must free that as well.
5803             // Check that the uniFullPathName.Buffer in the string is not the same
5804             // offset by the length of the server name
5805             //
5806
5807             if( uniFullPathName.Length > 0 &&
5808                 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
5809             {
5810
5811                 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
5812             }
5813
5814             AFSExFreePoolWithTag( pwchBuffer, 0);
5815         }
5816     }
5817
5818     return ntStatus;
5819 }
5820
5821 AFSObjectInfoCB *
5822 AFSAllocateObjectInfo( IN AFSObjectInfoCB *ParentObjectInfo,
5823                        IN ULONGLONG HashIndex)
5824 {
5825
5826     NTSTATUS ntStatus = STATUS_SUCCESS;
5827     AFSObjectInfoCB *pObjectInfo = NULL;
5828     LONG lCount;
5829
5830     __Enter
5831     {
5832
5833         pObjectInfo = (AFSObjectInfoCB *)AFSExAllocatePoolWithTag( PagedPool,
5834                                                                    sizeof( AFSObjectInfoCB),
5835                                                                    AFS_OBJECT_INFO_TAG);
5836
5837         if( pObjectInfo == NULL)
5838         {
5839
5840             try_return( pObjectInfo);
5841         }
5842
5843         RtlZeroMemory( pObjectInfo,
5844                        sizeof( AFSObjectInfoCB));
5845
5846         pObjectInfo->NonPagedInfo = (AFSNonPagedObjectInfoCB *)AFSExAllocatePoolWithTag( NonPagedPool,
5847                                                                                          sizeof( AFSNonPagedObjectInfoCB),
5848                                                                                          AFS_NP_OBJECT_INFO_TAG);
5849
5850         if( pObjectInfo->NonPagedInfo == NULL)
5851         {
5852
5853             AFSExFreePoolWithTag( pObjectInfo, AFS_OBJECT_INFO_TAG);
5854
5855             try_return( pObjectInfo = NULL);
5856         }
5857
5858         ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
5859
5860         ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
5861
5862         pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock = &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock;
5863
5864         if( ParentObjectInfo != NULL)
5865         {
5866
5867             pObjectInfo->VolumeCB = ParentObjectInfo->VolumeCB;
5868
5869             pObjectInfo->ParentFileId = ParentObjectInfo->FileId;
5870
5871             SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID);
5872
5873             lCount = AFSObjectInfoIncrement( ParentObjectInfo,
5874                                              AFS_OBJECT_REFERENCE_CHILD);
5875
5876             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
5877                           AFS_TRACE_LEVEL_VERBOSE,
5878                           "AFSAllocateObjectInfo Increment count on parent object %p Cnt %d\n",
5879                           ParentObjectInfo,
5880                           lCount));
5881         }
5882
5883         //
5884         // Initialize the access time
5885         //
5886
5887         KeQueryTickCount( &pObjectInfo->LastAccessCount);
5888
5889         if( HashIndex != 0)
5890         {
5891
5892             ASSERT( ParentObjectInfo);
5893
5894             //
5895             // Insert the entry into the object tree and list
5896             //
5897
5898             pObjectInfo->TreeEntry.HashIndex = HashIndex;
5899
5900             if( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead == NULL)
5901             {
5902
5903                 ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead = &pObjectInfo->TreeEntry;
5904             }
5905             else
5906             {
5907
5908                 ntStatus = AFSInsertHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
5909                                                &pObjectInfo->TreeEntry);
5910
5911                 ASSERT( NT_SUCCESS( ntStatus));
5912             }
5913
5914             //
5915             // And the object list in the volume
5916             //
5917
5918             if( ParentObjectInfo->VolumeCB->ObjectInfoListHead == NULL)
5919             {
5920
5921                 ParentObjectInfo->VolumeCB->ObjectInfoListHead = pObjectInfo;
5922             }
5923             else
5924             {
5925
5926                 ParentObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = (void *)pObjectInfo;
5927
5928                 pObjectInfo->ListEntry.bLink = (void *)ParentObjectInfo->VolumeCB->ObjectInfoListTail;
5929             }
5930
5931             ParentObjectInfo->VolumeCB->ObjectInfoListTail = pObjectInfo;
5932
5933             //
5934             // Indicate the object is in the hash tree and linked list in the volume
5935             //
5936
5937             SetFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE | AFS_OBJECT_INSERTED_VOLUME_LIST);
5938         }
5939
5940 try_exit:
5941
5942         NOTHING;
5943     }
5944
5945     return pObjectInfo;
5946 }
5947
5948 LONG
5949 AFSObjectInfoIncrement( IN AFSObjectInfoCB *ObjectInfo,
5950                         IN LONG Reason)
5951 {
5952
5953     LONG lCount;
5954
5955     if ( ObjectInfo->ObjectReferenceCount == 0)
5956     {
5957
5958         AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
5959                         TRUE);
5960
5961         lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
5962     }
5963     else
5964     {
5965
5966         AFSAcquireShared( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
5967                           TRUE);
5968
5969         lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
5970
5971         if ( lCount == 1)
5972         {
5973
5974             AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
5975
5976             AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
5977                             TRUE);
5978         }
5979     }
5980
5981     InterlockedIncrement( &ObjectInfo->ObjectReferences[ Reason]);
5982
5983     AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
5984
5985     return lCount;
5986 }
5987
5988 LONG
5989 AFSObjectInfoDecrement( IN AFSObjectInfoCB *ObjectInfo,
5990                         IN LONG Reason)
5991 {
5992
5993     LONG lCount, lCount2;
5994
5995     AFSAcquireShared( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
5996                       TRUE);
5997
5998     lCount = InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);
5999
6000     if ( lCount == 0)
6001     {
6002
6003         lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6004
6005         AFSReleaseResource(&ObjectInfo->NonPagedInfo->ObjectInfoLock);
6006
6007         AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6008                         TRUE);
6009
6010         lCount = InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);
6011     }
6012
6013     lCount2 = InterlockedDecrement( &ObjectInfo->ObjectReferences[ Reason]);
6014
6015     ASSERT( lCount2 >= 0);
6016
6017     AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6018
6019     return lCount;
6020 }
6021
6022 AFSObjectInfoCB *
6023 AFSFindObjectInfo( IN AFSVolumeCB *VolumeCB,
6024                    IN AFSFileID   *FileId)
6025 {
6026     DWORD            ntStatus = STATUS_SUCCESS;
6027     ULONGLONG        ullIndex;
6028     AFSObjectInfoCB *pObjectInfo = NULL;
6029     LONG             lCount;
6030
6031     if ( AFSIsEqualFID( &VolumeCB->ObjectInformation.FileId, FileId))
6032     {
6033
6034         pObjectInfo = &VolumeCB->ObjectInformation;
6035     }
6036     else
6037     {
6038
6039         AFSAcquireExcl( VolumeCB->ObjectInfoTree.TreeLock,
6040                         TRUE);
6041
6042         ullIndex = AFSCreateLowIndex( FileId);
6043
6044         ntStatus = AFSLocateHashEntry( VolumeCB->ObjectInfoTree.TreeHead,
6045                                        ullIndex,
6046                                        (AFSBTreeEntry **)&pObjectInfo);
6047
6048         AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
6049     }
6050
6051     if ( NT_SUCCESS( ntStatus)) {
6052
6053         lCount = AFSObjectInfoIncrement( pObjectInfo,
6054                                          AFS_OBJECT_REFERENCE_FIND);
6055
6056         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
6057                       AFS_TRACE_LEVEL_VERBOSE,
6058                       "AFSFindObjectInfo Decrement count on object %p Cnt %d\n",
6059                       pObjectInfo,
6060                       lCount));
6061     }
6062
6063     return pObjectInfo;
6064 }
6065
6066 void
6067 AFSReleaseObjectInfo( IN AFSObjectInfoCB **ppObjectInfo)
6068 {
6069     LONG lCount;
6070
6071     lCount = AFSObjectInfoDecrement( *ppObjectInfo,
6072                                      AFS_OBJECT_REFERENCE_FIND);
6073
6074     AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
6075                   AFS_TRACE_LEVEL_VERBOSE,
6076                   "AFSReleaseObjectInfo Decrement count on object %p Cnt %d\n",
6077                   *ppObjectInfo,
6078                   lCount));
6079
6080     *ppObjectInfo = NULL;
6081 }
6082
6083 void
6084 AFSDeleteObjectInfo( IN AFSObjectInfoCB **ppObjectInfo)
6085 {
6086
6087     BOOLEAN bAcquiredTreeLock = FALSE;
6088     AFSObjectInfoCB *pObjectInfo = NULL;
6089     BOOLEAN bHeldInService;
6090     AFSObjectInfoCB * pParentObjectInfo = NULL;
6091     AFSFileID FileId;
6092     LONG lCount;
6093
6094     if ( BooleanFlagOn( (*ppObjectInfo)->Flags, AFS_OBJECT_ROOT_VOLUME))
6095     {
6096
6097         //
6098         // AFSDeleteObjectInfo should never be called on the ObjectInformationCB
6099         // embedded in the VolumeCB.
6100         //
6101
6102         ASSERT( FALSE);
6103
6104         return;
6105     }
6106
6107     pObjectInfo = (AFSObjectInfoCB *) InterlockedCompareExchangePointer( (PVOID *)ppObjectInfo,
6108                                                                          NULL,
6109                                                                          *ppObjectInfo);
6110
6111     if ( pObjectInfo == NULL)
6112     {
6113
6114         return;
6115     }
6116
6117     ASSERT( *ppObjectInfo == NULL);
6118
6119     ASSERT( pObjectInfo->ObjectReferenceCount == 0);
6120
6121     bHeldInService = BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_HELD_IN_SERVICE);
6122
6123     if( !ExIsResourceAcquiredExclusiveLite( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock))
6124     {
6125
6126         ASSERT( !ExIsResourceAcquiredLite( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock));
6127
6128         AFSAcquireExcl( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
6129                         TRUE);
6130
6131         bAcquiredTreeLock = TRUE;
6132     }
6133
6134     if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
6135     {
6136
6137         pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
6138                                                &pObjectInfo->ParentFileId);
6139     }
6140
6141     //
6142     // Remove it from the tree and list if it was inserted
6143     //
6144
6145     if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
6146     {
6147
6148         AFSRemoveHashEntry( &pObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
6149                             &pObjectInfo->TreeEntry);
6150     }
6151
6152     if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_VOLUME_LIST))
6153     {
6154
6155         if( pObjectInfo->ListEntry.fLink == NULL)
6156         {
6157
6158             pObjectInfo->VolumeCB->ObjectInfoListTail = (AFSObjectInfoCB *)pObjectInfo->ListEntry.bLink;
6159
6160             if( pObjectInfo->VolumeCB->ObjectInfoListTail != NULL)
6161             {
6162
6163                 pObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = NULL;
6164             }
6165         }
6166         else
6167         {
6168
6169             ((AFSObjectInfoCB *)(pObjectInfo->ListEntry.fLink))->ListEntry.bLink = pObjectInfo->ListEntry.bLink;
6170         }
6171
6172         if( pObjectInfo->ListEntry.bLink == NULL)
6173         {
6174
6175             pObjectInfo->VolumeCB->ObjectInfoListHead = (AFSObjectInfoCB *)pObjectInfo->ListEntry.fLink;
6176
6177             if( pObjectInfo->VolumeCB->ObjectInfoListHead != NULL)
6178             {
6179
6180                 pObjectInfo->VolumeCB->ObjectInfoListHead->ListEntry.bLink = NULL;
6181             }
6182         }
6183         else
6184         {
6185
6186             ((AFSObjectInfoCB *)(pObjectInfo->ListEntry.bLink))->ListEntry.fLink = pObjectInfo->ListEntry.fLink;
6187         }
6188     }
6189
6190     if( pParentObjectInfo != NULL)
6191     {
6192
6193         ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID);
6194
6195         lCount = AFSObjectInfoDecrement( pParentObjectInfo,
6196                                          AFS_OBJECT_REFERENCE_CHILD);
6197
6198         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
6199                       AFS_TRACE_LEVEL_VERBOSE,
6200                       "AFSDeleteObjectInfo Decrement count on parent object %p Cnt %d\n",
6201                       pParentObjectInfo,
6202                       lCount));
6203
6204         AFSReleaseObjectInfo( &pParentObjectInfo);
6205     }
6206
6207     if( bAcquiredTreeLock)
6208     {
6209
6210         AFSReleaseResource( pObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
6211     }
6212
6213     if( bHeldInService)
6214     {
6215
6216         FileId = pObjectInfo->FileId;
6217     }
6218
6219     ExDeleteResourceLite( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
6220
6221     ExDeleteResourceLite( &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6222
6223     AFSExFreePoolWithTag( pObjectInfo->NonPagedInfo, AFS_NP_OBJECT_INFO_TAG);
6224
6225     AFSExFreePoolWithTag( pObjectInfo, AFS_OBJECT_INFO_TAG);
6226
6227     //
6228     // Release the fid in the service
6229     //
6230
6231     if( bHeldInService)
6232     {
6233
6234         AFSReleaseFid( &FileId);
6235     }
6236
6237     return;
6238 }
6239
6240 NTSTATUS
6241 AFSEvaluateRootEntry( IN AFSDirectoryCB *DirectoryCB,
6242                       OUT AFSDirectoryCB **TargetDirEntry)
6243 {
6244
6245     NTSTATUS ntStatus = STATUS_SUCCESS;
6246     AFSDirEnumEntry *pDirEntry = NULL;
6247     UNICODE_STRING uniFullPathName = {0};
6248     AFSNameArrayHdr    *pNameArray = NULL;
6249     AFSVolumeCB *pVolumeCB = NULL;
6250     LONG VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
6251     AFSVolumeCB *pNewVolumeCB = NULL;
6252     LONG NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
6253     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
6254     AFSDirectoryCB *pNewParentDirEntry = NULL;
6255     WCHAR *pwchBuffer = NULL;
6256     UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
6257     ULONG ulNameDifference = 0;
6258     GUID    stAuthGroup;
6259     LONG lCount;
6260
6261     __Enter
6262     {
6263
6264         ntStatus = AFSRetrieveValidAuthGroup( NULL,
6265                                               DirectoryCB->ObjectInformation,
6266                                               FALSE,
6267                                               &stAuthGroup);
6268
6269         if( !NT_SUCCESS( ntStatus))
6270         {
6271             try_return( ntStatus);
6272         }
6273
6274         //
6275         // Retrieve a target name for the entry
6276         //
6277
6278         AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
6279                           TRUE);
6280
6281         if( DirectoryCB->NameInformation.TargetName.Length == 0)
6282         {
6283
6284             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6285
6286             ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
6287                                               &stAuthGroup,
6288                                               FALSE,
6289                                               &pDirEntry);
6290
6291             if( !NT_SUCCESS( ntStatus) ||
6292                 pDirEntry->TargetNameLength == 0)
6293             {
6294
6295                 if( pDirEntry != NULL)
6296                 {
6297
6298                     ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
6299                 }
6300
6301                 try_return( ntStatus);
6302             }
6303
6304             AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
6305                             TRUE);
6306
6307             if( DirectoryCB->NameInformation.TargetName.Length == 0)
6308             {
6309
6310                 //
6311                 // Update the target name
6312                 //
6313
6314                 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
6315                                                 &DirectoryCB->Flags,
6316                                                 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
6317                                                 (USHORT)pDirEntry->TargetNameLength);
6318
6319                 if( !NT_SUCCESS( ntStatus))
6320                 {
6321
6322                     AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6323
6324                     try_return( ntStatus);
6325                 }
6326             }
6327
6328             AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
6329         }
6330
6331         //
6332         // Need to pass the full path in for parsing.
6333         //
6334
6335         uniFullPathName.Length = 0;
6336         uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
6337
6338         uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6339                                                                     uniFullPathName.MaximumLength,
6340                                                                     AFS_NAME_BUFFER_EIGHT_TAG);
6341
6342         if( uniFullPathName.Buffer == NULL)
6343         {
6344
6345             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6346
6347             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6348         }
6349
6350         pwchBuffer = uniFullPathName.Buffer;
6351
6352         RtlZeroMemory( uniFullPathName.Buffer,
6353                        uniFullPathName.MaximumLength);
6354
6355         RtlCopyMemory( uniFullPathName.Buffer,
6356                        DirectoryCB->NameInformation.TargetName.Buffer,
6357                        DirectoryCB->NameInformation.TargetName.Length);
6358
6359         uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6360
6361         //
6362         // This name should begin with the \afs server so parse it off and chech it
6363         //
6364
6365         FsRtlDissectName( uniFullPathName,
6366                           &uniComponentName,
6367                           &uniRemainingPath);
6368
6369         if( RtlCompareUnicodeString( &uniComponentName,
6370                                      &AFSServerName,
6371                                      TRUE) != 0)
6372         {
6373
6374             //
6375             // Try evaluating the full path
6376             //
6377
6378             uniFullPathName.Buffer = pwchBuffer;
6379
6380             uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6381
6382             uniFullPathName.MaximumLength = uniFullPathName.Length;
6383         }
6384         else
6385         {
6386
6387             uniFullPathName = uniRemainingPath;
6388         }
6389
6390         uniParsedName = uniFullPathName;
6391
6392         ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
6393
6394         AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6395
6396         //
6397         // Our name array
6398         //
6399
6400         pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
6401                                        0);
6402
6403         if( pNameArray == NULL)
6404         {
6405
6406             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6407         }
6408
6409         pVolumeCB = AFSGlobalRoot;
6410
6411         pParentDirEntry = AFSGlobalRoot->DirectoryCB;
6412
6413         VolumeReferenceReason = AFS_VOLUME_REFERENCE_EVAL_ROOT;
6414
6415         lCount = AFSVolumeIncrement( pVolumeCB,
6416                                      VolumeReferenceReason);
6417
6418         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6419                       AFS_TRACE_LEVEL_VERBOSE,
6420                       "AFSEvaluateRootEntry Increment count on volume %p Reason %u Cnt %d\n",
6421                       pVolumeCB,
6422                       VolumeReferenceReason,
6423                       lCount));
6424
6425         lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
6426
6427         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6428                       AFS_TRACE_LEVEL_VERBOSE,
6429                       "AFSEvaluateRootEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
6430                       &pParentDirEntry->NameInformation.FileName,
6431                       pParentDirEntry,
6432                       NULL,
6433                       lCount));
6434
6435         ntStatus = AFSLocateNameEntry( NULL,
6436                                        NULL,
6437                                        &uniFullPathName,
6438                                        &uniParsedName,
6439                                        pNameArray,
6440                                        0,
6441                                        pVolumeCB,
6442                                        pParentDirEntry,
6443                                        &pNewVolumeCB,
6444                                        &VolumeReferenceReason,
6445                                        &pNewParentDirEntry,
6446                                        &pDirectoryEntry,
6447                                        NULL);
6448
6449         if ( pNewVolumeCB != NULL)
6450         {
6451             //
6452             // AFSLocateNameEntry returns pNewVolumeCB with a reference held
6453             // even if pVolumeCB == pNewVolumeCB.  It is always safe to release
6454             // the reference on pVolumeCB that was held prior to the call.
6455             // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
6456             // will be released second.
6457             //
6458
6459             lCount = AFSVolumeDecrement( pVolumeCB,
6460                                          VolumeReferenceReason);
6461
6462             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6463                           AFS_TRACE_LEVEL_VERBOSE,
6464                           "AFSEvaluateRootEntry Decrement count on volume %p Reason %u Cnt %d\n",
6465                           pVolumeCB,
6466                           VolumeReferenceReason,
6467                           lCount));
6468
6469             pVolumeCB = pNewVolumeCB;
6470
6471             pNewVolumeCB = NULL;
6472
6473             VolumeReferenceReason = NewVolumeReferenceReason;
6474
6475             NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
6476         }
6477
6478         //
6479         // AFSLocateNameEntry does not alter the reference count of
6480         // pParentDirectoryCB and it returns pNewParentDirectoryCB with
6481         // a reference held.
6482         //
6483
6484         lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
6485
6486         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6487                       AFS_TRACE_LEVEL_VERBOSE,
6488                       "AFSEvaluateRootEntry DecrementX count on %wZ DE %p Cnt %d\n",
6489                       &pParentDirEntry->NameInformation.FileName,
6490                       pParentDirEntry,
6491                       lCount));
6492
6493         pParentDirEntry = pNewParentDirEntry;
6494
6495         pNewParentDirEntry = NULL;
6496
6497         if( !NT_SUCCESS( ntStatus) ||
6498             ntStatus == STATUS_REPARSE)
6499         {
6500
6501             pVolumeCB = NULL;
6502
6503             try_return( ntStatus);
6504         }
6505
6506         //
6507         // Pass back the target dir entry for this request
6508         // The caller must release the DirOpenReferenceCount
6509         //
6510
6511         *TargetDirEntry = pDirectoryEntry;
6512
6513         pDirectoryEntry = NULL;
6514
6515 try_exit:
6516
6517         if( pDirectoryEntry != NULL)
6518         {
6519
6520             lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
6521
6522             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6523                           AFS_TRACE_LEVEL_VERBOSE,
6524                           "AFSEvaluateRootEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6525                           &pDirectoryEntry->NameInformation.FileName,
6526                           pDirectoryEntry,
6527                           NULL,
6528                           lCount));
6529
6530             ASSERT( lCount >= 0);
6531         }
6532
6533         if ( pParentDirEntry != NULL)
6534         {
6535
6536             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
6537
6538             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6539                           AFS_TRACE_LEVEL_VERBOSE,
6540                           "AFSEvaluateRootEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
6541                           &pParentDirEntry->NameInformation.FileName,
6542                           pParentDirEntry,
6543                           NULL,
6544                           lCount));
6545
6546             ASSERT( lCount >= 0);
6547         }
6548
6549         if( pDirEntry != NULL)
6550         {
6551
6552             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
6553         }
6554
6555         if( pVolumeCB != NULL)
6556         {
6557
6558             lCount = AFSVolumeDecrement( pVolumeCB,
6559                                          VolumeReferenceReason);
6560
6561             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6562                           AFS_TRACE_LEVEL_VERBOSE,
6563                           "AFSEvaluateRootEntry Decrement2 count on volume %p Reason %u Cnt %d\n",
6564                           pVolumeCB,
6565                           VolumeReferenceReason,
6566                           lCount));
6567         }
6568
6569         if( pNameArray != NULL)
6570         {
6571
6572             AFSFreeNameArray( pNameArray);
6573         }
6574
6575         if( pwchBuffer != NULL)
6576         {
6577
6578             //
6579             // Always free the buffer that we allocated as AFSLocateNameEntry
6580             // will not free it.  If uniFullPathName.Buffer was allocated by
6581             // AFSLocateNameEntry, then we must free that as well.
6582             // Check that the uniFullPathName.Buffer in the string is not the same
6583             // offset by the length of the server name
6584             //
6585
6586             if( uniFullPathName.Length > 0 &&
6587                 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
6588             {
6589
6590                 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
6591             }
6592
6593             AFSExFreePoolWithTag( pwchBuffer, 0);
6594         }
6595     }
6596
6597     return ntStatus;
6598 }
6599
6600 NTSTATUS
6601 AFSCleanupFcb( IN AFSFcb *Fcb,
6602                IN BOOLEAN ForceFlush)
6603 {
6604
6605     NTSTATUS ntStatus = STATUS_SUCCESS;
6606     AFSDeviceExt *pRDRDeviceExt = NULL, *pControlDeviceExt = NULL;
6607     LARGE_INTEGER liTime;
6608     IO_STATUS_BLOCK stIoStatus;
6609
6610     __Enter
6611     {
6612
6613         pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
6614
6615         pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
6616
6617         if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
6618         {
6619
6620             if( !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) &&
6621                 !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
6622             {
6623
6624                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
6625                               AFS_TRACE_LEVEL_VERBOSE,
6626                               "AFSCleanupEntry Acquiring Fcb lock %p SHARED %08lX\n",
6627                               &Fcb->NPFcb->Resource,
6628                               PsGetCurrentThread()));
6629
6630                 AFSAcquireShared( &Fcb->NPFcb->Resource,
6631                                   TRUE);
6632
6633                 if( Fcb->OpenReferenceCount > 0)
6634                 {
6635
6636                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
6637                                   AFS_TRACE_LEVEL_VERBOSE,
6638                                   "AFSCleanupEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
6639                                   &Fcb->NPFcb->SectionObjectResource,
6640                                   PsGetCurrentThread()));
6641
6642                     AFSAcquireExcl( &Fcb->NPFcb->SectionObjectResource,
6643                                     TRUE);
6644
6645                     __try
6646                     {
6647
6648                         CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
6649                                       NULL,
6650                                       0,
6651                                       &stIoStatus);
6652
6653                         if( !NT_SUCCESS( stIoStatus.Status))
6654                         {
6655
6656                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
6657                                           AFS_TRACE_LEVEL_ERROR,
6658                                           "AFSCleanupFcb CcFlushCache [1] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
6659                                           Fcb->ObjectInformation->FileId.Cell,
6660                                           Fcb->ObjectInformation->FileId.Volume,
6661                                           Fcb->ObjectInformation->FileId.Vnode,
6662                                           Fcb->ObjectInformation->FileId.Unique,
6663                                           stIoStatus.Status,
6664                                           stIoStatus.Information));
6665
6666                             ntStatus = stIoStatus.Status;
6667                         }
6668
6669                         if (  Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
6670                         {
6671
6672                             if ( !CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
6673                                                        NULL,
6674                                                        0,
6675                                                        FALSE))
6676                             {
6677
6678                                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
6679                                               AFS_TRACE_LEVEL_WARNING,
6680                                               "AFSCleanupFcb CcPurgeCacheSection [1] failure FID %08lX-%08lX-%08lX-%08lX\n",
6681                                               Fcb->ObjectInformation->FileId.Cell,
6682                                               Fcb->ObjectInformation->FileId.Volume,
6683                                               Fcb->ObjectInformation->FileId.Vnode,
6684                                               Fcb->ObjectInformation->FileId.Unique));
6685
6686                                 SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
6687                             }
6688                         }
6689                     }
6690                     __except( EXCEPTION_EXECUTE_HANDLER)
6691                     {
6692
6693                         ntStatus = GetExceptionCode();
6694
6695                         AFSDbgTrace(( 0,
6696                                       0,
6697                                       "EXCEPTION - AFSCleanupFcb Cc [1] FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
6698                                       Fcb->ObjectInformation->FileId.Cell,
6699                                       Fcb->ObjectInformation->FileId.Volume,
6700                                       Fcb->ObjectInformation->FileId.Vnode,
6701                                       Fcb->ObjectInformation->FileId.Unique,
6702                                       ntStatus));
6703
6704                         SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
6705                     }
6706
6707                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
6708                                   AFS_TRACE_LEVEL_VERBOSE,
6709                                   "AFSCleanupFcb Releasing Fcb SectionObject lock %p EXCL %08lX\n",
6710                                   &Fcb->NPFcb->SectionObjectResource,
6711                                   PsGetCurrentThread()));
6712
6713                     AFSReleaseResource( &Fcb->NPFcb->SectionObjectResource);
6714                 }
6715
6716                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
6717                               AFS_TRACE_LEVEL_VERBOSE,
6718                               "AFSCleanupEntry Releasing Fcb lock %p SHARED %08lX\n",
6719                               &Fcb->NPFcb->Resource,
6720                               PsGetCurrentThread()));
6721
6722                 AFSReleaseResource( &Fcb->NPFcb->Resource);
6723
6724                 //
6725                 // Wait for any currently running flush or release requests to complete
6726                 //
6727
6728                 AFSWaitOnQueuedFlushes( Fcb);
6729
6730                 //
6731                 // Now perform another flush on the file
6732                 //
6733
6734                 if( !NT_SUCCESS( AFSFlushExtents( Fcb,
6735                                                   NULL)))
6736                 {
6737
6738                     AFSReleaseExtentsWithFlush( Fcb,
6739                                                 NULL,
6740                                                 TRUE);
6741                 }
6742             }
6743
6744             if( Fcb->OpenReferenceCount == 0 ||
6745                 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
6746                 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
6747             {
6748
6749                 AFSTearDownFcbExtents( Fcb,
6750                                        NULL);
6751             }
6752
6753             try_return( ntStatus);
6754         }
6755
6756         KeQueryTickCount( &liTime);
6757
6758         //
6759         // First up are there dirty extents in the cache to flush?
6760         //
6761
6762         if( BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
6763             BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
6764         {
6765
6766             //
6767             // The file has been marked as invalid.  Dump it
6768             //
6769
6770             AFSTearDownFcbExtents( Fcb,
6771                                    NULL);
6772         }
6773         else if( ForceFlush ||
6774             ( ( Fcb->Specific.File.ExtentsDirtyCount ||
6775                 Fcb->Specific.File.ExtentCount) &&
6776               (liTime.QuadPart - Fcb->Specific.File.LastServerFlush.QuadPart)
6777                                                     >= pControlDeviceExt->Specific.Control.FcbFlushTimeCount.QuadPart))
6778         {
6779             if( !NT_SUCCESS( AFSFlushExtents( Fcb,
6780                                               NULL)) &&
6781                 Fcb->OpenReferenceCount == 0)
6782             {
6783
6784                 AFSReleaseExtentsWithFlush( Fcb,
6785                                             NULL,
6786                                             TRUE);
6787             }
6788         }
6789
6790         //
6791         // If there are extents and they haven't been used recently *and*
6792         // are not being used
6793         //
6794
6795         if( ( ForceFlush ||
6796               ( 0 != Fcb->Specific.File.ExtentCount &&
6797                 0 != Fcb->Specific.File.LastExtentAccess.QuadPart &&
6798                 (liTime.QuadPart - Fcb->Specific.File.LastExtentAccess.QuadPart) >=
6799                                         (AFS_SERVER_PURGE_SLEEP * pControlDeviceExt->Specific.Control.FcbPurgeTimeCount.QuadPart))))
6800         {
6801
6802             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
6803                           AFS_TRACE_LEVEL_VERBOSE,
6804                           "AFSCleanupFcb Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
6805                           &Fcb->NPFcb->SectionObjectResource,
6806                           PsGetCurrentThread()));
6807
6808             if ( AFSAcquireExcl( &Fcb->NPFcb->SectionObjectResource, ForceFlush))
6809             {
6810
6811                 __try
6812                 {
6813
6814                     CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
6815                                   NULL,
6816                                   0,
6817                                   &stIoStatus);
6818
6819                     if( !NT_SUCCESS( stIoStatus.Status))
6820                     {
6821
6822                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
6823                                       AFS_TRACE_LEVEL_ERROR,
6824                                       "AFSCleanupFcb CcFlushCache [2] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
6825                                       Fcb->ObjectInformation->FileId.Cell,
6826                                       Fcb->ObjectInformation->FileId.Volume,
6827                                       Fcb->ObjectInformation->FileId.Vnode,
6828                                       Fcb->ObjectInformation->FileId.Unique,
6829                                       stIoStatus.Status,
6830                                       stIoStatus.Information));
6831
6832                         ntStatus = stIoStatus.Status;
6833                     }
6834
6835                     if( ForceFlush &&
6836                         Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
6837                     {
6838
6839                         if ( !CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
6840                                                    NULL,
6841                                                    0,
6842                                                    FALSE))
6843                         {
6844
6845                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
6846                                           AFS_TRACE_LEVEL_WARNING,
6847                                           "AFSCleanupFcb CcPurgeCacheSection [2] failure FID %08lX-%08lX-%08lX-%08lX\n",
6848                                           Fcb->ObjectInformation->FileId.Cell,
6849                                           Fcb->ObjectInformation->FileId.Volume,
6850                                           Fcb->ObjectInformation->FileId.Vnode,
6851                                           Fcb->ObjectInformation->FileId.Unique));
6852
6853                             SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
6854                         }
6855                     }
6856                 }
6857                 __except( EXCEPTION_EXECUTE_HANDLER)
6858                 {
6859
6860                     ntStatus = GetExceptionCode();
6861
6862                     AFSDbgTrace(( 0,
6863                                   0,
6864                                   "EXCEPTION - AFSCleanupFcb Cc [2] FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
6865                                   Fcb->ObjectInformation->FileId.Cell,
6866                                   Fcb->ObjectInformation->FileId.Volume,
6867                                   Fcb->ObjectInformation->FileId.Vnode,
6868                                   Fcb->ObjectInformation->FileId.Unique,
6869                                   ntStatus));
6870                 }
6871
6872                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
6873                               AFS_TRACE_LEVEL_VERBOSE,
6874                               "AFSCleanupFcb Releasing Fcb SectionObject lock %p EXCL %08lX\n",
6875                               &Fcb->NPFcb->SectionObjectResource,
6876                               PsGetCurrentThread()));
6877
6878                 AFSReleaseResource( &Fcb->NPFcb->SectionObjectResource);
6879
6880                 if( Fcb->OpenReferenceCount <= 0)
6881                 {
6882
6883                     //
6884                     // Tear em down we'll not be needing them again
6885                     //
6886
6887                     AFSTearDownFcbExtents( Fcb,
6888                                            NULL);
6889                 }
6890             }
6891             else
6892             {
6893
6894                 ntStatus = STATUS_RETRY;
6895             }
6896         }
6897
6898 try_exit:
6899
6900         NOTHING;
6901     }
6902
6903     return ntStatus;
6904 }
6905
6906 NTSTATUS
6907 AFSUpdateDirEntryName( IN AFSDirectoryCB *DirectoryCB,
6908                        IN UNICODE_STRING *NewFileName)
6909 {
6910
6911     NTSTATUS ntStatus = STATUS_SUCCESS;
6912     WCHAR *pTmpBuffer = NULL;
6913
6914     __Enter
6915     {
6916
6917         if( NewFileName->Length > DirectoryCB->NameInformation.FileName.Length)
6918         {
6919
6920             if( BooleanFlagOn( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
6921             {
6922
6923                 AFSExFreePoolWithTag( DirectoryCB->NameInformation.FileName.Buffer, 0);
6924
6925                 ClearFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
6926
6927                 DirectoryCB->NameInformation.FileName.Buffer = NULL;
6928             }
6929
6930             //
6931             // OK, we need to allocate a new name buffer
6932             //
6933
6934             pTmpBuffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6935                                                             NewFileName->Length,
6936                                                             AFS_NAME_BUFFER_NINE_TAG);
6937
6938             if( pTmpBuffer == NULL)
6939             {
6940
6941                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6942             }
6943
6944             DirectoryCB->NameInformation.FileName.Buffer = pTmpBuffer;
6945
6946             DirectoryCB->NameInformation.FileName.MaximumLength = NewFileName->Length;
6947
6948             SetFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
6949         }
6950
6951         DirectoryCB->NameInformation.FileName.Length = NewFileName->Length;
6952
6953         RtlCopyMemory( DirectoryCB->NameInformation.FileName.Buffer,
6954                        NewFileName->Buffer,
6955                        NewFileName->Length);
6956
6957 try_exit:
6958
6959         NOTHING;
6960     }
6961
6962     return ntStatus;
6963 }
6964
6965 NTSTATUS
6966 AFSReadCacheFile( IN void *ReadBuffer,
6967                   IN LARGE_INTEGER *ReadOffset,
6968                   IN ULONG RequestedDataLength,
6969                   IN OUT PULONG BytesRead)
6970 {
6971
6972     NTSTATUS            ntStatus = STATUS_SUCCESS;
6973     PIRP                pIrp = NULL;
6974     KEVENT              kEvent;
6975     PIO_STACK_LOCATION  pIoStackLocation = NULL;
6976     DEVICE_OBJECT      *pTargetDeviceObject = NULL;
6977     FILE_OBJECT        *pCacheFileObject = NULL;
6978
6979     __Enter
6980     {
6981
6982         pCacheFileObject = AFSReferenceCacheFileObject();
6983
6984         if( pCacheFileObject == NULL)
6985         {
6986             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
6987         }
6988
6989         pTargetDeviceObject = IoGetRelatedDeviceObject( pCacheFileObject);
6990
6991         //
6992         // Initialize the event
6993         //
6994
6995         KeInitializeEvent( &kEvent,
6996                            SynchronizationEvent,
6997                            FALSE);
6998
6999         //
7000         // Allocate an irp for this request.  This could also come from a
7001         // private pool, for instance.
7002         //
7003
7004         pIrp = IoAllocateIrp( pTargetDeviceObject->StackSize,
7005                               FALSE);
7006
7007         if( pIrp == NULL)
7008         {
7009
7010             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7011         }
7012
7013         //
7014         // Build the IRP's main body
7015         //
7016
7017         pIrp->UserBuffer = ReadBuffer;
7018
7019         pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
7020         pIrp->RequestorMode = KernelMode;
7021         pIrp->Flags |= IRP_READ_OPERATION;
7022
7023         //
7024         // Set up the I/O stack location.
7025         //
7026
7027         pIoStackLocation = IoGetNextIrpStackLocation( pIrp);
7028         pIoStackLocation->MajorFunction = IRP_MJ_READ;
7029         pIoStackLocation->DeviceObject = pTargetDeviceObject;
7030         pIoStackLocation->FileObject = pCacheFileObject;
7031         pIoStackLocation->Parameters.Read.Length = RequestedDataLength;
7032
7033         pIoStackLocation->Parameters.Read.ByteOffset.QuadPart = ReadOffset->QuadPart;
7034
7035         //
7036         // Set the completion routine.
7037         //
7038
7039         IoSetCompletionRoutine( pIrp,
7040                                 AFSIrpComplete,
7041                                 &kEvent,
7042                                 TRUE,
7043                                 TRUE,
7044                                 TRUE);
7045
7046         //
7047         // Send it to the FSD
7048         //
7049
7050         ntStatus = IoCallDriver( pTargetDeviceObject,
7051                                  pIrp);
7052
7053         if( NT_SUCCESS( ntStatus))
7054         {
7055
7056             //
7057             // Wait for the I/O
7058             //
7059
7060             ntStatus = KeWaitForSingleObject( &kEvent,
7061                                               Executive,
7062                                               KernelMode,
7063                                               FALSE,
7064                                               0);
7065
7066             if( NT_SUCCESS( ntStatus))
7067             {
7068
7069                 ntStatus = pIrp->IoStatus.Status;
7070
7071                 *BytesRead = (ULONG)pIrp->IoStatus.Information;
7072             }
7073         }
7074
7075 try_exit:
7076
7077         if( pCacheFileObject != NULL)
7078         {
7079             AFSReleaseCacheFileObject( pCacheFileObject);
7080         }
7081
7082         if( pIrp != NULL)
7083         {
7084
7085             if( pIrp->MdlAddress != NULL)
7086             {
7087
7088                 if( FlagOn( pIrp->MdlAddress->MdlFlags, MDL_PAGES_LOCKED))
7089                 {
7090
7091                     MmUnlockPages( pIrp->MdlAddress);
7092                 }
7093
7094                 IoFreeMdl( pIrp->MdlAddress);
7095             }
7096
7097             pIrp->MdlAddress = NULL;
7098
7099             //
7100             // Free the Irp
7101             //
7102
7103             IoFreeIrp( pIrp);
7104         }
7105     }
7106
7107     return ntStatus;
7108 }
7109
7110 NTSTATUS
7111 AFSIrpComplete( IN PDEVICE_OBJECT DeviceObject,
7112                 IN PIRP           Irp,
7113                 IN PVOID          Context)
7114 {
7115
7116     UNREFERENCED_PARAMETER(Irp);
7117     UNREFERENCED_PARAMETER(DeviceObject);
7118     KEVENT *pEvent = (KEVENT *)Context;
7119
7120     KeSetEvent( pEvent,
7121                 0,
7122                 FALSE);
7123
7124     return STATUS_MORE_PROCESSING_REQUIRED;
7125 }
7126
7127 BOOLEAN
7128 AFSIsDirectoryEmptyForDelete( IN AFSFcb *Fcb)
7129 {
7130
7131     BOOLEAN bIsEmpty = FALSE;
7132     AFSDirectoryCB *pDirEntry = NULL;
7133
7134     __Enter
7135     {
7136
7137         AFSAcquireShared( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
7138                           TRUE);
7139
7140         bIsEmpty = TRUE;
7141
7142         if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
7143         {
7144
7145             pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
7146
7147             while( pDirEntry != NULL)
7148             {
7149
7150                 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
7151                     !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
7152                 {
7153
7154                     bIsEmpty = FALSE;
7155
7156                     break;
7157                 }
7158
7159                 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
7160             }
7161
7162         }
7163
7164         AFSReleaseResource( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
7165     }
7166
7167     return bIsEmpty;
7168 }
7169
7170 void
7171 AFSRemoveNameEntry( IN AFSObjectInfoCB *ParentObjectInfo,
7172                     IN AFSDirectoryCB *DirEntry)
7173 {
7174
7175     NTSTATUS ntStatus = STATUS_SUCCESS;
7176
7177     __Enter
7178     {
7179
7180         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7181         {
7182
7183             AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7184                           AFS_TRACE_LEVEL_VERBOSE,
7185                           "AFSRemoveNameEntry DE %p for %wZ has NOT_IN flag set\n",
7186                           DirEntry,
7187                           &DirEntry->NameInformation.FileName));
7188
7189             try_return( ntStatus);
7190         }
7191
7192         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
7193
7194         //
7195         // Remove the entry from the parent tree
7196         //
7197
7198         AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7199                       AFS_TRACE_LEVEL_VERBOSE,
7200                       "AFSRemoveNameEntry DE %p for %wZ removing from case sensitive tree\n",
7201                       DirEntry,
7202                       &DirEntry->NameInformation.FileName));
7203
7204         AFSRemoveCaseSensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7205                                         DirEntry);
7206
7207         AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7208                       AFS_TRACE_LEVEL_VERBOSE,
7209                       "AFSRemoveNameEntry DE %p for %wZ removing from case insensitive tree\n",
7210                       DirEntry,
7211                       &DirEntry->NameInformation.FileName));
7212
7213         AFSRemoveCaseInsensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
7214                                           DirEntry);
7215
7216         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
7217         {
7218
7219             //
7220             // From the short name tree
7221             //
7222
7223             AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7224                           AFS_TRACE_LEVEL_VERBOSE,
7225                           "AFSRemoveNameEntry DE %p for %wZ removing from shortname tree\n",
7226                           DirEntry,
7227                           &DirEntry->NameInformation.FileName));
7228
7229             AFSRemoveShortNameDirEntry( &ParentObjectInfo->Specific.Directory.ShortNameTree,
7230                                         DirEntry);
7231
7232             ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
7233         }
7234
7235         AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7236                       AFS_TRACE_LEVEL_VERBOSE,
7237                       "AFSRemoveNameEntry DE %p for %wZ setting NOT_IN flag\n",
7238                       DirEntry,
7239                       &DirEntry->NameInformation.FileName));
7240
7241         SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
7242
7243         ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
7244
7245 try_exit:
7246
7247         NOTHING;
7248     }
7249
7250     return;
7251 }
7252
7253 LARGE_INTEGER
7254 AFSGetAuthenticationId()
7255 {
7256
7257     LARGE_INTEGER liAuthId = {0,0};
7258     NTSTATUS ntStatus = STATUS_SUCCESS;
7259     PACCESS_TOKEN hToken = NULL;
7260     PTOKEN_STATISTICS pTokenInfo = NULL;
7261     BOOLEAN bCopyOnOpen = FALSE;
7262     BOOLEAN bEffectiveOnly = FALSE;
7263     BOOLEAN bPrimaryToken = FALSE;
7264     SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
7265
7266     __Enter
7267     {
7268
7269         hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
7270                                                 &bCopyOnOpen,
7271                                                 &bEffectiveOnly,
7272                                                 &stImpersonationLevel);
7273
7274         if( hToken == NULL)
7275         {
7276
7277             hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
7278
7279             if( hToken == NULL)
7280             {
7281
7282                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7283                               AFS_TRACE_LEVEL_ERROR,
7284                               "AFSGetAuthenticationId Failed to retrieve impersonation or primary token\n"));
7285
7286                 try_return( ntStatus);
7287             }
7288
7289             bPrimaryToken = TRUE;
7290         }
7291
7292         ntStatus = SeQueryInformationToken( hToken,
7293                                             TokenStatistics,
7294                                             (PVOID *)&pTokenInfo);
7295
7296         if( !NT_SUCCESS( ntStatus))
7297         {
7298
7299             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7300                           AFS_TRACE_LEVEL_ERROR,
7301                           "AFSGetAuthenticationId Failed to retrieve information Status %08lX\n",
7302                           ntStatus));
7303
7304             try_return( ntStatus);
7305         }
7306
7307         liAuthId.HighPart = pTokenInfo->AuthenticationId.HighPart;
7308         liAuthId.LowPart = pTokenInfo->AuthenticationId.LowPart;
7309
7310         AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7311                       AFS_TRACE_LEVEL_VERBOSE,
7312                       "AFSGetAuthenticationId Successfully retrieved authentication ID %I64X\n",
7313                       liAuthId.QuadPart));
7314
7315 try_exit:
7316
7317         if( hToken != NULL)
7318         {
7319
7320             if( !bPrimaryToken)
7321             {
7322
7323                 PsDereferenceImpersonationToken( hToken);
7324             }
7325             else
7326             {
7327
7328                 PsDereferencePrimaryToken( hToken);
7329             }
7330         }
7331
7332         if( pTokenInfo != NULL)
7333         {
7334
7335             ExFreePool( pTokenInfo);    // Allocated by SeQueryInformationToken
7336         }
7337     }
7338
7339     return liAuthId;
7340 }
7341
7342 void
7343 AFSUnwindFileInfo( IN AFSFcb *Fcb,
7344                    IN AFSCcb *Ccb)
7345 {
7346
7347     UNREFERENCED_PARAMETER(Fcb);
7348     if( Ccb->FileUnwindInfo.FileAttributes != (ULONG)-1)
7349     {
7350         Ccb->DirectoryCB->ObjectInformation->FileAttributes = Ccb->FileUnwindInfo.FileAttributes;
7351     }
7352
7353     if( Ccb->FileUnwindInfo.CreationTime.QuadPart != (ULONGLONG)-1)
7354     {
7355         Ccb->DirectoryCB->ObjectInformation->CreationTime.QuadPart = Ccb->FileUnwindInfo.CreationTime.QuadPart;
7356     }
7357
7358     if( Ccb->FileUnwindInfo.LastAccessTime.QuadPart != (ULONGLONG)-1)
7359     {
7360         Ccb->DirectoryCB->ObjectInformation->LastAccessTime.QuadPart = Ccb->FileUnwindInfo.LastAccessTime.QuadPart;
7361     }
7362
7363     if( Ccb->FileUnwindInfo.LastWriteTime.QuadPart != (ULONGLONG)-1)
7364     {
7365         Ccb->DirectoryCB->ObjectInformation->LastWriteTime.QuadPart = Ccb->FileUnwindInfo.LastWriteTime.QuadPart;
7366     }
7367
7368     if( Ccb->FileUnwindInfo.ChangeTime.QuadPart != (ULONGLONG)-1)
7369     {
7370         Ccb->DirectoryCB->ObjectInformation->ChangeTime.QuadPart = Ccb->FileUnwindInfo.ChangeTime.QuadPart;
7371     }
7372
7373     return;
7374 }
7375
7376 BOOLEAN
7377 AFSValidateDirList( IN AFSObjectInfoCB *ObjectInfo)
7378 {
7379
7380     BOOLEAN bIsValid = TRUE;
7381     ULONG ulCount = 0;
7382     AFSDirectoryCB *pCurrentDirEntry = NULL, *pDirEntry = NULL;
7383
7384     pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
7385
7386     while( pCurrentDirEntry != NULL)
7387     {
7388
7389         if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
7390         {
7391             ulCount++;
7392
7393             if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7394             {
7395
7396                 pDirEntry = NULL;
7397
7398                 AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7399                                                 (ULONG)pCurrentDirEntry->CaseSensitiveTreeEntry.HashIndex,
7400                                                 &pDirEntry);
7401
7402                 if( pDirEntry == NULL)
7403                 {
7404                     DbgBreakPoint();
7405                 }
7406             }
7407         }
7408
7409         pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
7410     }
7411
7412     if( ulCount != (ULONG) ObjectInfo->Specific.Directory.DirectoryNodeCount)
7413     {
7414
7415         AFSPrint("AFSValidateDirList Count off Calc: %d Stored: %d\n",
7416                   ulCount,
7417                   ObjectInfo->Specific.Directory.DirectoryNodeCount);
7418
7419         ObjectInfo->Specific.Directory.DirectoryNodeCount = ulCount;
7420
7421         bIsValid = FALSE;
7422     }
7423
7424     return bIsValid;
7425 }
7426
7427 PFILE_OBJECT
7428 AFSReferenceCacheFileObject()
7429 {
7430
7431     AFSDeviceExt       *pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
7432     FILE_OBJECT        *pCacheFileObject = NULL;
7433
7434     AFSAcquireShared( &pRdrDevExt->Specific.RDR.CacheFileLock,
7435                       TRUE);
7436
7437     pCacheFileObject = pRdrDevExt->Specific.RDR.CacheFileObject;
7438
7439     if( pCacheFileObject != NULL)
7440     {
7441         ObReferenceObject( pCacheFileObject);
7442     }
7443
7444     AFSReleaseResource( &pRdrDevExt->Specific.RDR.CacheFileLock);
7445
7446     return pCacheFileObject;
7447 }
7448
7449 void
7450 AFSReleaseCacheFileObject( IN PFILE_OBJECT CacheFileObject)
7451 {
7452
7453     ASSERT( CacheFileObject != NULL);
7454
7455     ObDereferenceObject( CacheFileObject);
7456
7457     return;
7458 }
7459
7460 NTSTATUS
7461 AFSInitializeLibrary( IN AFSLibraryInitCB *LibraryInit)
7462 {
7463
7464     NTSTATUS ntStatus = STATUS_SUCCESS;
7465     AFSDeviceExt *pControlDevExt = NULL;
7466     ULONG ulTimeIncrement = 0;
7467     LONG lCount;
7468
7469     __Enter
7470     {
7471
7472         AFSControlDeviceObject = LibraryInit->AFSControlDeviceObject;
7473
7474         AFSRDRDeviceObject = LibraryInit->AFSRDRDeviceObject;
7475
7476         AFSServerName = LibraryInit->AFSServerName;
7477
7478         AFSMountRootName = LibraryInit->AFSMountRootName;
7479
7480         AFSDebugFlags = LibraryInit->AFSDebugFlags;
7481
7482         //
7483         // Callbacks in the framework
7484         //
7485
7486         AFSProcessRequest = LibraryInit->AFSProcessRequest;
7487
7488         AFSDbgLogMsg = LibraryInit->AFSDbgLogMsg;
7489
7490         AFSDebugTraceFnc = AFSDbgLogMsg;
7491
7492         AFSAddConnectionEx = LibraryInit->AFSAddConnectionEx;
7493
7494         AFSExAllocatePoolWithTag = LibraryInit->AFSExAllocatePoolWithTag;
7495
7496         AFSExFreePoolWithTag = LibraryInit->AFSExFreePoolWithTag;
7497
7498         AFSDumpTraceFilesFnc = LibraryInit->AFSDumpTraceFiles;
7499
7500         AFSRetrieveAuthGroupFnc = LibraryInit->AFSRetrieveAuthGroup;
7501
7502         AFSLibCacheManagerCallbacks = LibraryInit->AFSCacheManagerCallbacks;
7503
7504         if( LibraryInit->AFSCacheBaseAddress != NULL)
7505         {
7506
7507             SetFlag( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE);
7508
7509             AFSLibCacheBaseAddress = LibraryInit->AFSCacheBaseAddress;
7510
7511             AFSLibCacheLength = LibraryInit->AFSCacheLength;
7512         }
7513
7514         //
7515         // Initialize some flush parameters
7516         //
7517
7518         pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
7519
7520         ulTimeIncrement = KeQueryTimeIncrement();
7521
7522         pControlDevExt->Specific.Control.ObjectLifeTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_OBJECT_LIFETIME / (ULONGLONG)ulTimeIncrement);
7523         pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart = AFS_SERVER_PURGE_DELAY;
7524         pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart /= ulTimeIncrement;
7525         pControlDevExt->Specific.Control.FcbFlushTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_SERVER_FLUSH_DELAY / (ULONGLONG)ulTimeIncrement);
7526         pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_EXTENT_REQUEST_TIME/(ULONGLONG)ulTimeIncrement);
7527
7528         //
7529         // Initialize the global root entry
7530         //
7531
7532         ntStatus = AFSInitVolume( NULL,
7533                                   &LibraryInit->GlobalRootFid,
7534                                   AFS_VOLUME_REFERENCE_GLOBAL_ROOT,
7535                                   &AFSGlobalRoot);
7536
7537         if( !NT_SUCCESS( ntStatus))
7538         {
7539
7540             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
7541                           AFS_TRACE_LEVEL_ERROR,
7542                           "AFSInitializeLibrary AFSInitVolume failure %08lX\n",
7543                           ntStatus));
7544
7545             try_return( ntStatus);
7546         }
7547
7548         ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
7549                                    AFSGlobalRoot);
7550
7551         if( !NT_SUCCESS( ntStatus))
7552         {
7553
7554             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
7555                           AFS_TRACE_LEVEL_ERROR,
7556                           "AFSInitializeLibrary AFSInitRootFcb failure %08lX\n",
7557                           ntStatus));
7558
7559             lCount = AFSVolumeDecrement( AFSGlobalRoot,
7560                                          AFS_VOLUME_REFERENCE_GLOBAL_ROOT);
7561
7562             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7563                           AFS_TRACE_LEVEL_VERBOSE,
7564                           "AFSInitializeLibrary Decrement count on volume %p Cnt %d\n",
7565                           AFSGlobalRoot,
7566                           lCount));
7567
7568             AFSReleaseResource( AFSGlobalRoot->VolumeLock);
7569
7570             try_return( ntStatus);
7571         }
7572
7573         //
7574         // Update the node type code to AFS_ROOT_ALL
7575         //
7576
7577         AFSGlobalRoot->ObjectInformation.Fcb->Header.NodeTypeCode = AFS_ROOT_ALL;
7578
7579         SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_ACTIVE_GLOBAL_ROOT);
7580
7581         //
7582         // Invalidate all known volumes since contact with the service and therefore
7583         // the file server was lost.
7584         //
7585
7586         AFSInvalidateAllVolumes();
7587
7588         //
7589         // Drop the locks acquired above
7590         //
7591
7592         AFSInitVolumeWorker( AFSGlobalRoot);
7593
7594         lCount = AFSVolumeDecrement( AFSGlobalRoot,
7595                                      AFS_VOLUME_REFERENCE_GLOBAL_ROOT);
7596
7597         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7598                       AFS_TRACE_LEVEL_VERBOSE,
7599                       "AFSInitializeLibrary Decrement count on volume %p Cnt %d\n",
7600                       AFSGlobalRoot,
7601                       lCount));
7602
7603         AFSReleaseResource( AFSGlobalRoot->VolumeLock);
7604
7605         AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Fcb->Header.Resource);
7606
7607 try_exit:
7608
7609         NOTHING;
7610     }
7611
7612     return ntStatus;
7613 }
7614
7615 NTSTATUS
7616 AFSCloseLibrary()
7617 {
7618
7619     NTSTATUS ntStatus = STATUS_SUCCESS;
7620     AFSDirectoryCB *pDirNode = NULL, *pLastDirNode = NULL;
7621     LONG lCount;
7622
7623     __Enter
7624     {
7625
7626         if( AFSGlobalDotDirEntry != NULL)
7627         {
7628
7629             lCount = AFSObjectInfoDecrement( AFSGlobalDotDirEntry->ObjectInformation,
7630                                              AFS_OBJECT_REFERENCE_GLOBAL);
7631
7632             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
7633                           AFS_TRACE_LEVEL_VERBOSE,
7634                           "AFSCloseLibrary Decrement count on parent object %p Cnt %d\n",
7635                           AFSGlobalDotDirEntry->ObjectInformation,
7636                           lCount));
7637
7638             AFSDeleteObjectInfo( &AFSGlobalDotDirEntry->ObjectInformation);
7639
7640             ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
7641
7642             ExFreePool( AFSGlobalDotDirEntry->NonPaged);
7643
7644             ExFreePool( AFSGlobalDotDirEntry);
7645
7646             AFSGlobalDotDirEntry = NULL;
7647         }
7648
7649         if( AFSGlobalDotDotDirEntry != NULL)
7650         {
7651
7652             lCount = AFSObjectInfoDecrement( AFSGlobalDotDotDirEntry->ObjectInformation,
7653                                              AFS_OBJECT_REFERENCE_GLOBAL);
7654
7655             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
7656                           AFS_TRACE_LEVEL_VERBOSE,
7657                           "AFSCloseLibrary Decrement count on parent object %p Cnt %d\n",
7658                           AFSGlobalDotDotDirEntry->ObjectInformation,
7659                           lCount));
7660
7661             AFSDeleteObjectInfo( &AFSGlobalDotDotDirEntry->ObjectInformation);
7662
7663             ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
7664
7665             ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
7666
7667             ExFreePool( AFSGlobalDotDotDirEntry);
7668
7669             AFSGlobalDotDotDirEntry = NULL;
7670         }
7671
7672         if( AFSSpecialShareNames != NULL)
7673         {
7674
7675             pDirNode = AFSSpecialShareNames;
7676
7677             while( pDirNode != NULL)
7678             {
7679
7680                 pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
7681
7682                 lCount = AFSObjectInfoDecrement( pDirNode->ObjectInformation,
7683                                                  AFS_OBJECT_REFERENCE_GLOBAL);
7684
7685                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
7686                               AFS_TRACE_LEVEL_VERBOSE,
7687                               "AFSCloseLibrary Decrement count on parent object %p Cnt %d\n",
7688                               pDirNode->ObjectInformation,
7689                               lCount));
7690
7691                 AFSDeleteObjectInfo( &pDirNode->ObjectInformation);
7692
7693                 ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
7694
7695                 ExFreePool( pDirNode->NonPaged);
7696
7697                 ExFreePool( pDirNode);
7698
7699                 pDirNode = pLastDirNode;
7700             }
7701
7702             AFSSpecialShareNames = NULL;
7703         }
7704     }
7705
7706     return ntStatus;
7707 }
7708
7709 NTSTATUS
7710 AFSDefaultLogMsg( IN ULONG Subsystem,
7711                   IN ULONG Level,
7712                   IN PCCH Format,
7713                   ...)
7714 {
7715
7716     UNREFERENCED_PARAMETER(Subsystem);
7717     UNREFERENCED_PARAMETER(Level);
7718     NTSTATUS ntStatus = STATUS_SUCCESS;
7719     va_list va_args;
7720     char chDebugBuffer[ 256];
7721
7722     __Enter
7723     {
7724
7725         va_start( va_args, Format);
7726
7727         ntStatus = RtlStringCbVPrintfA( chDebugBuffer,
7728                                         256,
7729                                         Format,
7730                                         va_args);
7731
7732         if( NT_SUCCESS( ntStatus))
7733         {
7734             DbgPrint( chDebugBuffer);
7735         }
7736
7737         va_end( va_args);
7738     }
7739
7740     return ntStatus;
7741 }
7742
7743 NTSTATUS
7744 AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
7745                     IN ULONG InputBufferLength,
7746                     IN AFSStatusInfoCB *StatusInfo,
7747                     OUT ULONG *ReturnLength)
7748 {
7749
7750     NTSTATUS ntStatus = STATUS_SUCCESS;
7751     AFSVolumeCB *pVolumeCB = NULL;
7752     LONG VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
7753     AFSVolumeCB *pNewVolumeCB = NULL;
7754     LONG NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
7755     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
7756     AFSObjectInfoCB *pObjectInfo = NULL;
7757     ULONGLONG   ullIndex = 0;
7758     UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName, uniParsedName;
7759     AFSNameArrayHdr *pNameArray = NULL;
7760     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
7761     AFSDirectoryCB *pNewParentDirEntry = NULL;
7762     LONG lCount;
7763
7764     __Enter
7765     {
7766
7767         //
7768         // If we are given a FID then look up the entry by that, otherwise
7769         // do it by name
7770         //
7771
7772         if( GetStatusInfo->FileID.Cell != 0 &&
7773             GetStatusInfo->FileID.Volume != 0 &&
7774             GetStatusInfo->FileID.Vnode != 0 &&
7775             GetStatusInfo->FileID.Unique != 0)
7776         {
7777
7778             AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
7779
7780             //
7781             // Locate the volume node
7782             //
7783
7784             ullIndex = AFSCreateHighIndex( &GetStatusInfo->FileID);
7785
7786             ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
7787                                            ullIndex,
7788                                            (AFSBTreeEntry **)&pVolumeCB);
7789
7790             if( pVolumeCB != NULL)
7791             {
7792
7793                 VolumeReferenceReason = AFS_VOLUME_REFERENCE_GET_OBJECT;
7794
7795                 lCount = AFSVolumeIncrement( pVolumeCB,
7796                                              VolumeReferenceReason);
7797
7798                 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7799                               AFS_TRACE_LEVEL_VERBOSE,
7800                               "AFSGetObjectStatus Increment count on volume %p Reason %u Cnt %d\n",
7801                               pVolumeCB,
7802                               VolumeReferenceReason,
7803                               lCount));
7804             }
7805
7806             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
7807
7808             if( !NT_SUCCESS( ntStatus) ||
7809                 pVolumeCB == NULL)
7810             {
7811                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
7812             }
7813
7814             if( AFSIsVolumeFID( &GetStatusInfo->FileID))
7815             {
7816
7817                 pObjectInfo = &pVolumeCB->ObjectInformation;
7818
7819                 lCount = AFSObjectInfoIncrement( pObjectInfo,
7820                                                  AFS_OBJECT_REFERENCE_STATUS);
7821
7822                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
7823                               AFS_TRACE_LEVEL_VERBOSE,
7824                               "AFSGetObjectStatus Increment1 count on object %p Cnt %d\n",
7825                               pObjectInfo,
7826                               lCount));
7827             }
7828             else
7829             {
7830
7831                 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
7832                                   TRUE);
7833
7834                 ullIndex = AFSCreateLowIndex( &GetStatusInfo->FileID);
7835
7836                 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
7837                                                ullIndex,
7838                                                (AFSBTreeEntry **)&pObjectInfo);
7839
7840                 if( pObjectInfo != NULL)
7841                 {
7842
7843                     //
7844                     // Reference the node so it won't be torn down
7845                     //
7846
7847                     lCount = AFSObjectInfoIncrement( pObjectInfo,
7848                                                      AFS_OBJECT_REFERENCE_STATUS);
7849
7850                     AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
7851                                   AFS_TRACE_LEVEL_VERBOSE,
7852                                   "AFSGetObjectStatus Increment2 count on object %p Cnt %d\n",
7853                                   pObjectInfo,
7854                                   lCount));
7855                 }
7856
7857                 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
7858
7859                 if( !NT_SUCCESS( ntStatus) ||
7860                     pObjectInfo == NULL)
7861                 {
7862                     try_return( ntStatus = STATUS_INVALID_PARAMETER);
7863                 }
7864             }
7865         }
7866         else
7867         {
7868
7869             if( GetStatusInfo->FileNameLength == 0 ||
7870                 InputBufferLength < (ULONG)(FIELD_OFFSET( AFSGetStatusInfoCB, FileName) + GetStatusInfo->FileNameLength))
7871             {
7872                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
7873             }
7874
7875             uniFullPathName.Length = GetStatusInfo->FileNameLength;
7876             uniFullPathName.MaximumLength = uniFullPathName.Length;
7877
7878             uniFullPathName.Buffer = (WCHAR *)GetStatusInfo->FileName;
7879
7880             //
7881             // This name should begin with the \afs server so parse it off and check it
7882             //
7883
7884             FsRtlDissectName( uniFullPathName,
7885                               &uniComponentName,
7886                               &uniRemainingPath);
7887
7888             if( RtlCompareUnicodeString( &uniComponentName,
7889                                          &AFSServerName,
7890                                          TRUE) != 0)
7891             {
7892                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
7893                               AFS_TRACE_LEVEL_ERROR,
7894                               "AFSGetObjectStatus Name %wZ contains invalid server name\n",
7895                               &uniFullPathName));
7896
7897                 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
7898             }
7899
7900             uniFullPathName = uniRemainingPath;
7901
7902             uniParsedName = uniFullPathName;
7903
7904             //
7905             // Our name array
7906             //
7907
7908             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
7909                                            0);
7910
7911             if( pNameArray == NULL)
7912             {
7913                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7914             }
7915
7916             pVolumeCB = AFSGlobalRoot;
7917
7918             pParentDirEntry = AFSGlobalRoot->DirectoryCB;
7919
7920             //
7921             // Increment the ref count on the volume and dir entry for correct processing below
7922             //
7923
7924             VolumeReferenceReason = AFS_VOLUME_REFERENCE_GET_OBJECT;
7925
7926             lCount = AFSVolumeIncrement( pVolumeCB,
7927                                          VolumeReferenceReason);
7928
7929             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7930                           AFS_TRACE_LEVEL_VERBOSE,
7931                           "AFSGetObjectStatus Increment2 count on volume %p Reason %u Cnt %d\n",
7932                           pVolumeCB,
7933                           VolumeReferenceReason,
7934                           lCount));
7935
7936             lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
7937
7938             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
7939                           AFS_TRACE_LEVEL_VERBOSE,
7940                           "AFSGetObjectStatus Increment count on %wZ DE %p Ccb %p Cnt %d\n",
7941                           &pParentDirEntry->NameInformation.FileName,
7942                           pParentDirEntry,
7943                           NULL,
7944                           lCount));
7945
7946             ntStatus = AFSLocateNameEntry( NULL,
7947                                            NULL,
7948                                            &uniFullPathName,
7949                                            &uniParsedName,
7950                                            pNameArray,
7951                                            AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL |
7952                                                AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL,
7953                                            pVolumeCB,
7954                                            pParentDirEntry,
7955                                            &pNewVolumeCB,
7956                                            &NewVolumeReferenceReason,
7957                                            &pNewParentDirEntry,
7958                                            &pDirectoryEntry,
7959                                            NULL);
7960
7961             if ( pNewVolumeCB != NULL)
7962             {
7963
7964                 //
7965                 // AFSLocateNameEntry returns pNewVolumeCB with a reference held
7966                 // even if pVolumeCB == pNewVolumeCB.  It is always safe to release
7967                 // the reference on pVolumeCB that was held prior to the call.
7968                 // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
7969                 // will be released second.
7970                 //
7971
7972                 lCount = AFSVolumeDecrement( pVolumeCB,
7973                                              VolumeReferenceReason);
7974
7975                 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7976                               AFS_TRACE_LEVEL_VERBOSE,
7977                               "AFSGetObjectStatus Decrement count on volume %p Reason %u Cnt %d\n",
7978                               pVolumeCB,
7979                               VolumeReferenceReason,
7980                               lCount));
7981
7982                 pVolumeCB = pNewVolumeCB;
7983
7984                 pNewVolumeCB = NULL;
7985
7986                 VolumeReferenceReason = NewVolumeReferenceReason;
7987
7988                 NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
7989             }
7990
7991             //
7992             // AFSLocateNameEntry does not alter the reference count of
7993             // pParentDirectoryCB and it returns pNewParentDirectoryCB with
7994             // a reference held.
7995             //
7996
7997             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
7998
7999             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8000                           AFS_TRACE_LEVEL_VERBOSE,
8001                           "AFSGetObjectStatus DecrementX count on %wZ DE %p Cnt %d\n",
8002                           &pParentDirEntry->NameInformation.FileName,
8003                           pParentDirEntry,
8004                           lCount));
8005
8006             pParentDirEntry = pNewParentDirEntry;
8007
8008             pNewParentDirEntry = NULL;
8009
8010             if( !NT_SUCCESS( ntStatus) ||
8011                 ntStatus == STATUS_REPARSE)
8012             {
8013
8014                 pVolumeCB = NULL;
8015
8016                 try_return( ntStatus);
8017             }
8018
8019             pObjectInfo = pDirectoryEntry->ObjectInformation;
8020
8021             lCount = AFSObjectInfoIncrement( pObjectInfo,
8022                                              AFS_OBJECT_REFERENCE_STATUS);
8023
8024             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8025                           AFS_TRACE_LEVEL_VERBOSE,
8026                           "AFSGetObjectStatus Increment3 count on object %p Cnt %d\n",
8027                           pObjectInfo,
8028                           lCount));
8029         }
8030
8031         //
8032         // At this point we have an object info block, return the information
8033         //
8034
8035         StatusInfo->FileId = pObjectInfo->FileId;
8036
8037         StatusInfo->TargetFileId = pObjectInfo->TargetFileId;
8038
8039         StatusInfo->Expiration = pObjectInfo->Expiration;
8040
8041         StatusInfo->DataVersion = pObjectInfo->DataVersion;
8042
8043         StatusInfo->FileType = pObjectInfo->FileType;
8044
8045         StatusInfo->ObjectFlags = pObjectInfo->Flags;
8046
8047         StatusInfo->CreationTime = pObjectInfo->CreationTime;
8048
8049         StatusInfo->LastAccessTime = pObjectInfo->LastAccessTime;
8050
8051         StatusInfo->LastWriteTime = pObjectInfo->LastWriteTime;
8052
8053         StatusInfo->ChangeTime = pObjectInfo->ChangeTime;
8054
8055         StatusInfo->FileAttributes = pObjectInfo->FileAttributes;
8056
8057         StatusInfo->EndOfFile = pObjectInfo->EndOfFile;
8058
8059         StatusInfo->AllocationSize = pObjectInfo->AllocationSize;
8060
8061         StatusInfo->EaSize = pObjectInfo->EaSize;
8062
8063         StatusInfo->Links = pObjectInfo->Links;
8064
8065         //
8066         // Return the information length
8067         //
8068
8069         *ReturnLength = sizeof( AFSStatusInfoCB);
8070
8071 try_exit:
8072
8073         if( pDirectoryEntry != NULL)
8074         {
8075
8076             lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
8077
8078             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8079                           AFS_TRACE_LEVEL_VERBOSE,
8080                           "AFSGetObjectStatus Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
8081                           &pDirectoryEntry->NameInformation.FileName,
8082                           pDirectoryEntry,
8083                           NULL,
8084                           lCount));
8085
8086             ASSERT( lCount >= 0);
8087         }
8088
8089         if ( pParentDirEntry != NULL)
8090         {
8091
8092             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
8093
8094             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8095                           AFS_TRACE_LEVEL_VERBOSE,
8096                           "AFSGetObjectStatus Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
8097                           &pParentDirEntry->NameInformation.FileName,
8098                           pParentDirEntry,
8099                           NULL,
8100                           lCount));
8101
8102             ASSERT( lCount >= 0);
8103         }
8104
8105         if( pObjectInfo != NULL)
8106         {
8107
8108             lCount = AFSObjectInfoDecrement( pObjectInfo,
8109                                              AFS_OBJECT_REFERENCE_STATUS);
8110
8111             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8112                           AFS_TRACE_LEVEL_VERBOSE,
8113                           "AFSGetObjectStatus Decrement count on object %p Cnt %d\n",
8114                           pObjectInfo,
8115                           lCount));
8116         }
8117
8118         if( pVolumeCB != NULL)
8119         {
8120
8121             lCount = AFSVolumeDecrement( pVolumeCB,
8122                                          VolumeReferenceReason);
8123
8124             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8125                           AFS_TRACE_LEVEL_VERBOSE,
8126                           "AFSGetObjectStatus Decrement4 count on volume %p Reason %u Cnt %d\n",
8127                           pVolumeCB,
8128                           VolumeReferenceReason,
8129                           lCount));
8130         }
8131
8132         if( pNameArray != NULL)
8133         {
8134
8135             AFSFreeNameArray( pNameArray);
8136         }
8137     }
8138
8139     return ntStatus;
8140 }
8141
8142 NTSTATUS
8143 AFSCheckSymlinkAccess( IN AFSDirectoryCB *ParentDirectoryCB,
8144                        IN UNICODE_STRING *ComponentName)
8145 {
8146
8147     NTSTATUS ntStatus = STATUS_SUCCESS;
8148     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
8149     AFSDirectoryCB *pDirEntry = NULL;
8150     ULONG ulCRC = 0;
8151     LONG lCount;
8152
8153     __Enter
8154     {
8155
8156         //
8157         // Search for the entry in the parent
8158         //
8159
8160         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8161                       AFS_TRACE_LEVEL_VERBOSE_2,
8162                       "AFSCheckSymlinkAccess Searching for entry %wZ case sensitive\n",
8163                       ComponentName));
8164
8165         ulCRC = AFSGenerateCRC( ComponentName,
8166                                 FALSE);
8167
8168         AFSAcquireShared( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
8169                           TRUE);
8170
8171         AFSLocateCaseSensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
8172                                         ulCRC,
8173                                         &pDirEntry);
8174
8175         if( pDirEntry == NULL)
8176         {
8177
8178             //
8179             // Missed so perform a case insensitive lookup
8180             //
8181
8182             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8183                           AFS_TRACE_LEVEL_VERBOSE_2,
8184                           "AFSCheckSymlinkAccess Searching for entry %wZ case insensitive\n",
8185                           ComponentName));
8186
8187             ulCRC = AFSGenerateCRC( ComponentName,
8188                                     TRUE);
8189
8190             AFSLocateCaseInsensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
8191                                               ulCRC,
8192                                               &pDirEntry);
8193
8194             if( pDirEntry == NULL)
8195             {
8196
8197                 //
8198                 // OK, if this component is a valid short name then try
8199                 // a lookup in the short name tree
8200                 //
8201
8202                 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
8203                     RtlIsNameLegalDOS8Dot3( ComponentName,
8204                                             NULL,
8205                                             NULL))
8206                 {
8207
8208                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8209                                   AFS_TRACE_LEVEL_VERBOSE_2,
8210                                   "AFSCheckSymlinkAccess Searching for entry %wZ short name\n",
8211                                   ComponentName));
8212
8213                     AFSLocateShortNameDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.ShortNameTree,
8214                                                 ulCRC,
8215                                                 &pDirEntry);
8216                 }
8217             }
8218         }
8219
8220         if( pDirEntry != NULL)
8221         {
8222             lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
8223
8224             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8225                           AFS_TRACE_LEVEL_VERBOSE,
8226                           "AFSCheckSymlinkAccess Increment count on %wZ DE %p Ccb %p Cnt %d\n",
8227                           &pDirEntry->NameInformation.FileName,
8228                           pDirEntry,
8229                           NULL,
8230                           lCount));
8231
8232             ASSERT( lCount >= 0);
8233         }
8234
8235         AFSReleaseResource( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
8236
8237         if( pDirEntry == NULL)
8238         {
8239
8240             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8241                           AFS_TRACE_LEVEL_VERBOSE_2,
8242                           "AFSCheckSymlinkAccess Failed to locate entry %wZ ntStatus %08X\n",
8243                           ComponentName,
8244                           STATUS_OBJECT_NAME_NOT_FOUND));
8245
8246             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
8247         }
8248
8249         //
8250         // We have the symlink object but previously failed to process it so return access
8251         // denied.
8252         //
8253
8254         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8255                       AFS_TRACE_LEVEL_VERBOSE_2,
8256                       "AFSCheckSymlinkAccess Failing symlink access to entry %wZ REPARSE_POINT_NOT_RESOLVED\n",
8257                       ComponentName));
8258
8259         ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
8260
8261         lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
8262
8263         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8264                       AFS_TRACE_LEVEL_VERBOSE,
8265                       "AFSCheckSymlinkAccess Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
8266                       &pDirEntry->NameInformation.FileName,
8267                       pDirEntry,
8268                       NULL,
8269                       lCount));
8270
8271         ASSERT( lCount >= 0);
8272
8273 try_exit:
8274
8275         NOTHING;
8276     }
8277
8278     return ntStatus;
8279 }
8280
8281 NTSTATUS
8282 AFSRetrieveFinalComponent( IN UNICODE_STRING *FullPathName,
8283                            OUT UNICODE_STRING *ComponentName)
8284 {
8285
8286     NTSTATUS ntStatus = STATUS_SUCCESS;
8287     UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName;
8288
8289     uniFullPathName = *FullPathName;
8290
8291     while( TRUE)
8292     {
8293
8294         FsRtlDissectName( uniFullPathName,
8295                           &uniComponentName,
8296                           &uniRemainingPath);
8297
8298         if( uniRemainingPath.Length == 0)
8299         {
8300             break;
8301         }
8302
8303         uniFullPathName = uniRemainingPath;
8304     }
8305
8306     if( uniComponentName.Length > 0)
8307     {
8308         *ComponentName = uniComponentName;
8309     }
8310
8311     return ntStatus;
8312 }
8313
8314 void
8315 AFSDumpTraceFiles_Default()
8316 {
8317     return;
8318 }
8319
8320 BOOLEAN
8321 AFSValidNameFormat( IN UNICODE_STRING *FileName)
8322 {
8323
8324     BOOLEAN bIsValidName = TRUE;
8325     USHORT usIndex = 0;
8326
8327     __Enter
8328     {
8329
8330         while( usIndex < FileName->Length/sizeof( WCHAR))
8331         {
8332
8333             if( FileName->Buffer[ usIndex] == L':' ||
8334                 FileName->Buffer[ usIndex] == L'*' ||
8335                 FileName->Buffer[ usIndex] == L'?' ||
8336                 FileName->Buffer[ usIndex] == L'"' ||
8337                 FileName->Buffer[ usIndex] == L'<' ||
8338                 FileName->Buffer[ usIndex] == L'>')
8339             {
8340                 bIsValidName = FALSE;
8341                 break;
8342             }
8343
8344             usIndex++;
8345         }
8346     }
8347
8348     return bIsValidName;
8349 }
8350
8351 NTSTATUS
8352 AFSCreateDefaultSecurityDescriptor()
8353 {
8354
8355     NTSTATUS ntStatus = STATUS_SUCCESS;
8356     PACL pSACL = NULL;
8357     ULONG ulSACLSize = 0;
8358     SYSTEM_MANDATORY_LABEL_ACE* pACE = NULL;
8359     ULONG ulACESize = 0;
8360     SECURITY_DESCRIPTOR *pSecurityDescr = NULL;
8361     ULONG ulSDLength = 0;
8362     SECURITY_DESCRIPTOR *pRelativeSecurityDescr = NULL;
8363     PSID pWorldSID = NULL;
8364     ULONG *pulSubAuthority = NULL;
8365     ULONG ulWorldSIDLEngth = 0;
8366
8367     __Enter
8368     {
8369
8370         ulWorldSIDLEngth = RtlLengthRequiredSid( 1);
8371
8372         pWorldSID = (PSID)ExAllocatePoolWithTag( PagedPool,
8373                                                  ulWorldSIDLEngth,
8374                                                  AFS_GENERIC_MEMORY_29_TAG);
8375
8376         if( pWorldSID == NULL)
8377         {
8378             AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate World SID\n");
8379
8380             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8381         }
8382
8383         RtlZeroMemory( pWorldSID,
8384                        ulWorldSIDLEngth);
8385
8386         RtlInitializeSid( pWorldSID,
8387                           &SeWorldSidAuthority,
8388                           1);
8389
8390         pulSubAuthority = RtlSubAuthoritySid(pWorldSID, 0);
8391         *pulSubAuthority = SECURITY_WORLD_RID;
8392
8393         if( AFSRtlSetSaclSecurityDescriptor == NULL)
8394         {
8395
8396             AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor == NULL\n");
8397         }
8398         else
8399         {
8400
8401             ulACESize = sizeof( SYSTEM_MANDATORY_LABEL_ACE) + 128;
8402
8403             pACE = (SYSTEM_MANDATORY_LABEL_ACE *)ExAllocatePoolWithTag( PagedPool,
8404                                                                         ulACESize,
8405                                                                         AFS_GENERIC_MEMORY_29_TAG);
8406
8407             if( pACE == NULL)
8408             {
8409
8410                 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8411
8412                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8413             }
8414
8415             RtlZeroMemory( pACE,
8416                            ulACESize);
8417
8418             pACE->Header.AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
8419             pACE->Header.AceType = SYSTEM_MANDATORY_LABEL_ACE_TYPE;
8420             pACE->Header.AceSize = FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + (USHORT)RtlLengthSid( SeExports->SeLowMandatorySid);
8421             pACE->Mask = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP;
8422
8423             RtlCopySid( RtlLengthSid( SeExports->SeLowMandatorySid),
8424                         &pACE->SidStart,
8425                         SeExports->SeLowMandatorySid);
8426
8427             ulSACLSize = sizeof(ACL) + RtlLengthSid( SeExports->SeLowMandatorySid) +
8428                 FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + ulACESize;
8429
8430             pSACL = (PACL)ExAllocatePoolWithTag( PagedPool,
8431                                                  ulSACLSize,
8432                                                  AFS_GENERIC_MEMORY_29_TAG);
8433
8434             if( pSACL == NULL)
8435             {
8436
8437                 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8438
8439                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8440             }
8441
8442             ntStatus = RtlCreateAcl( pSACL,
8443                                      ulSACLSize,
8444                                      ACL_REVISION);
8445
8446             if( !NT_SUCCESS( ntStatus))
8447             {
8448
8449                 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateAcl ntStatus %08lX\n",
8450                           ntStatus);
8451
8452                 try_return( ntStatus);
8453             }
8454
8455             ntStatus = RtlAddAce( pSACL,
8456                                   ACL_REVISION,
8457                                   0,
8458                                   pACE,
8459                                   pACE->Header.AceSize);
8460
8461             if( !NT_SUCCESS( ntStatus))
8462             {
8463
8464                 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAddAce ntStatus %08lX\n",
8465                           ntStatus);
8466
8467                 try_return( ntStatus);
8468             }
8469         }
8470
8471         pSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
8472                                                                        sizeof( SECURITY_DESCRIPTOR),
8473                                                                        AFS_GENERIC_MEMORY_27_TAG);
8474
8475         if( pSecurityDescr == NULL)
8476         {
8477
8478             AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8479
8480             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8481         }
8482
8483         ntStatus = RtlCreateSecurityDescriptor( pSecurityDescr,
8484                                                 SECURITY_DESCRIPTOR_REVISION);
8485
8486         if( !NT_SUCCESS( ntStatus))
8487         {
8488
8489             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateSecurityDescriptor ntStatus %08lX\n",
8490                       ntStatus);
8491
8492             try_return( ntStatus);
8493         }
8494
8495         if( AFSRtlSetSaclSecurityDescriptor != NULL)
8496         {
8497             ntStatus = AFSRtlSetSaclSecurityDescriptor( pSecurityDescr,
8498                                                         TRUE,
8499                                                         pSACL,
8500                                                         FALSE);
8501
8502             if( !NT_SUCCESS( ntStatus))
8503             {
8504
8505                 AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor ntStatus %08lX\n",
8506                           ntStatus);
8507
8508                 try_return( ntStatus);
8509             }
8510         }
8511
8512         //
8513         // Add in the group and owner to the SD
8514         //
8515
8516         if( AFSRtlSetGroupSecurityDescriptor != NULL)
8517         {
8518             ntStatus = AFSRtlSetGroupSecurityDescriptor( pSecurityDescr,
8519                                                          pWorldSID,
8520                                                          FALSE);
8521
8522             if( !NT_SUCCESS( ntStatus))
8523             {
8524
8525                 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetGroupSecurityDescriptor failed ntStatus %08lX\n",
8526                           ntStatus);
8527
8528                 try_return( ntStatus);
8529             }
8530         }
8531
8532         ntStatus = RtlSetOwnerSecurityDescriptor( pSecurityDescr,
8533                                                   pWorldSID,
8534                                                   FALSE);
8535
8536         if( !NT_SUCCESS( ntStatus))
8537         {
8538
8539             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetOwnerSecurityDescriptor failed ntStatus %08lX\n",
8540                       ntStatus);
8541
8542             try_return( ntStatus);
8543         }
8544
8545         if( !RtlValidSecurityDescriptor( pSecurityDescr))
8546         {
8547
8548             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlValidSecurityDescriptor NOT\n");
8549
8550             try_return( ntStatus = STATUS_INVALID_PARAMETER);
8551         }
8552
8553         pRelativeSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
8554                                                                                PAGE_SIZE,
8555                                                                                AFS_GENERIC_MEMORY_27_TAG);
8556
8557         if( pRelativeSecurityDescr == NULL)
8558         {
8559
8560             AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8561
8562             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8563         }
8564
8565         ulSDLength = PAGE_SIZE;
8566
8567         ntStatus = RtlAbsoluteToSelfRelativeSD( pSecurityDescr,
8568                                                 pRelativeSecurityDescr,
8569                                                 &ulSDLength);
8570
8571         if( !NT_SUCCESS( ntStatus))
8572         {
8573
8574             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAbsoluteToSelfRelativeSD ntStatus %08lX\n",
8575                       ntStatus);
8576
8577             try_return( ntStatus);
8578         }
8579
8580         AFSDefaultSD = pRelativeSecurityDescr;
8581
8582 try_exit:
8583
8584         if( !NT_SUCCESS( ntStatus))
8585         {
8586
8587             if( pRelativeSecurityDescr != NULL)
8588             {
8589                 ExFreePool( pRelativeSecurityDescr);
8590             }
8591         }
8592
8593         if( pSecurityDescr != NULL)
8594         {
8595             ExFreePool( pSecurityDescr);
8596         }
8597
8598         if( pSACL != NULL)
8599         {
8600             ExFreePool( pSACL);
8601         }
8602
8603         if( pACE != NULL)
8604         {
8605             ExFreePool( pACE);
8606         }
8607
8608         if( pWorldSID != NULL)
8609         {
8610             ExFreePool( pWorldSID);
8611         }
8612     }
8613
8614     return ntStatus;
8615 }
8616
8617 void
8618 AFSRetrieveParentPath( IN UNICODE_STRING *FullFileName,
8619                        OUT UNICODE_STRING *ParentPath)
8620 {
8621
8622     *ParentPath = *FullFileName;
8623
8624     //
8625     // If the final character is a \, jump over it
8626     //
8627
8628     if( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] == L'\\')
8629     {
8630         ParentPath->Length -= sizeof( WCHAR);
8631     }
8632
8633     while( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] != L'\\')
8634     {
8635         ParentPath->Length -= sizeof( WCHAR);
8636     }
8637
8638     //
8639     // And the separator
8640     //
8641
8642     ParentPath->Length -= sizeof( WCHAR);
8643
8644     return;
8645 }
8646
8647 NTSTATUS
8648 AFSRetrieveValidAuthGroup( IN AFSFcb *Fcb,
8649                            IN AFSObjectInfoCB *ObjectInfo,
8650                            IN BOOLEAN WriteAccess,
8651                            OUT GUID *AuthGroup)
8652 {
8653
8654     NTSTATUS ntStatus = STATUS_SUCCESS;
8655     GUID     stAuthGroup, stZeroAuthGroup;
8656     BOOLEAN  bFoundAuthGroup = FALSE;
8657     AFSCcb  *pCcb = NULL;
8658     AFSFcb *pFcb = Fcb;
8659
8660     __Enter
8661     {
8662
8663         RtlZeroMemory( &stAuthGroup,
8664                        sizeof( GUID));
8665
8666         RtlZeroMemory( &stZeroAuthGroup,
8667                        sizeof( GUID));
8668
8669         if( Fcb == NULL)
8670         {
8671
8672             if( ObjectInfo != NULL &&
8673                 ObjectInfo->Fcb != NULL)
8674             {
8675                 pFcb = ObjectInfo->Fcb;
8676             }
8677         }
8678
8679         if( pFcb != NULL)
8680         {
8681
8682             AFSAcquireShared( &Fcb->NPFcb->CcbListLock,
8683                               TRUE);
8684
8685             pCcb = Fcb->CcbListHead;
8686
8687             while( pCcb != NULL)
8688             {
8689
8690                 if( WriteAccess &&
8691                     pCcb->GrantedAccess & FILE_WRITE_DATA)
8692                 {
8693                     RtlCopyMemory( &stAuthGroup,
8694                                    &pCcb->AuthGroup,
8695                                    sizeof( GUID));
8696
8697                     bFoundAuthGroup = TRUE;
8698
8699                     break;
8700                 }
8701                 else if( pCcb->GrantedAccess & FILE_READ_DATA)
8702                 {
8703                     //
8704                     // At least get the read-only access
8705                     //
8706
8707                     RtlCopyMemory( &stAuthGroup,
8708                                    &pCcb->AuthGroup,
8709                                    sizeof( GUID));
8710
8711                     bFoundAuthGroup = TRUE;
8712                 }
8713
8714                 pCcb = (AFSCcb *)pCcb->ListEntry.fLink;
8715             }
8716
8717             AFSReleaseResource( &Fcb->NPFcb->CcbListLock);
8718         }
8719
8720         if( !bFoundAuthGroup)
8721         {
8722
8723             AFSRetrieveAuthGroupFnc( (ULONGLONG)PsGetCurrentProcessId(),
8724                                      (ULONGLONG)PsGetCurrentThreadId(),
8725                                       &stAuthGroup);
8726
8727             if( RtlCompareMemory( &stZeroAuthGroup,
8728                                   &stAuthGroup,
8729                                   sizeof( GUID)) == sizeof( GUID))
8730             {
8731
8732                 DbgPrint("AFSRetrieveValidAuthGroup Failed to locate PAG\n");
8733
8734                 try_return( ntStatus = STATUS_ACCESS_DENIED);
8735             }
8736         }
8737
8738         RtlCopyMemory( AuthGroup,
8739                        &stAuthGroup,
8740                        sizeof( GUID));
8741
8742 try_exit:
8743
8744         NOTHING;
8745     }
8746
8747     return ntStatus;
8748 }
8749
8750 NTSTATUS
8751 AFSPerformObjectInvalidate( IN AFSObjectInfoCB *ObjectInfo,
8752                             IN ULONG InvalidateReason)
8753 {
8754
8755     NTSTATUS            ntStatus = STATUS_SUCCESS;
8756     LIST_ENTRY         *le;
8757     AFSExtent          *pEntry;
8758     ULONG               ulProcessCount = 0;
8759     ULONG               ulCount = 0;
8760     LONG                lCount;
8761
8762     __Enter
8763     {
8764
8765         switch( InvalidateReason)
8766         {
8767
8768             case AFS_INVALIDATE_DELETED:
8769             {
8770
8771                 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
8772                     ObjectInfo->Fcb != NULL)
8773                 {
8774
8775                     AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
8776                                     TRUE);
8777
8778                     ObjectInfo->Links = 0;
8779
8780                     ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
8781
8782                     KeSetEvent( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
8783                                 0,
8784                                 FALSE);
8785
8786                     //
8787                     // Clear out the extents
8788                     // And get rid of them (note this involves waiting
8789                     // for any writes or reads to the cache to complete)
8790                     //
8791
8792                     AFSTearDownFcbExtents( ObjectInfo->Fcb,
8793                                            NULL);
8794
8795                     AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
8796                 }
8797
8798                 break;
8799             }
8800
8801             case AFS_INVALIDATE_DATA_VERSION:
8802             {
8803
8804                 LARGE_INTEGER liCurrentOffset = {0,0};
8805                 LARGE_INTEGER liFlushLength = {0,0};
8806                 ULONG ulFlushLength = 0;
8807                 BOOLEAN bLocked = FALSE;
8808                 BOOLEAN bExtentsLocked = FALSE;
8809                 BOOLEAN bCleanExtents = FALSE;
8810
8811                 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
8812                     ObjectInfo->Fcb != NULL)
8813                 {
8814
8815                     AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Resource,
8816                                     TRUE);
8817
8818                     bLocked = TRUE;
8819
8820                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
8821                                   AFS_TRACE_LEVEL_VERBOSE,
8822                                   "AFSPerformObjectInvalidate Acquiring Fcb extents lock %p SHARED %08lX\n",
8823                                   &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
8824                                   PsGetCurrentThread()));
8825
8826                     AFSAcquireShared( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
8827                                       TRUE);
8828
8829                     bExtentsLocked = TRUE;
8830
8831                     //
8832                     // There are several possibilities here:
8833                     //
8834                     // 0. If there are no extents or all of the extents are dirty, do nothing.
8835                     //
8836                     // 1. There could be nothing dirty and an open reference count of zero
8837                     //    in which case we can just tear down all of the extents without
8838                     //    holding any resources.
8839                     //
8840                     // 2. There could be nothing dirty and a non-zero open reference count
8841                     //    in which case we can issue a CcPurge against the entire file
8842                     //    while holding just the Fcb Resource.
8843                     //
8844                     // 3. There can be dirty extents in which case we need to identify
8845                     //    the non-dirty ranges and then perform a CcPurge on just the
8846                     //    non-dirty ranges while holding just the Fcb Resource.
8847                     //
8848
8849                     if ( ObjectInfo->Fcb->Specific.File.ExtentCount != ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount)
8850                     {
8851
8852                         if ( ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount == 0)
8853                         {
8854
8855                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
8856
8857                             bExtentsLocked = FALSE;
8858
8859                             if ( ObjectInfo->Fcb->OpenReferenceCount == 0)
8860                             {
8861
8862                                 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
8863
8864                                 bLocked = FALSE;
8865
8866                                 AFSTearDownFcbExtents( ObjectInfo->Fcb,
8867                                                        NULL);
8868                             }
8869                             else
8870                             {
8871
8872                                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
8873                                               AFS_TRACE_LEVEL_VERBOSE,
8874                                               "AFSPerformObjectInvalidation Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
8875                                               &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
8876                                               PsGetCurrentThread()));
8877
8878                                 AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
8879                                                 TRUE);
8880
8881                                 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
8882
8883                                 bLocked = FALSE;
8884
8885                                 __try
8886                                 {
8887
8888                                     if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
8889                                         !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
8890                                                               NULL,
8891                                                               0,
8892                                                               FALSE))
8893                                     {
8894
8895                                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
8896                                                       AFS_TRACE_LEVEL_WARNING,
8897                                                       "AFSPerformObjectInvalidation CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
8898                                                       ObjectInfo->FileId.Cell,
8899                                                       ObjectInfo->FileId.Volume,
8900                                                       ObjectInfo->FileId.Vnode,
8901                                                       ObjectInfo->FileId.Unique));
8902
8903                                         SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
8904                                     }
8905                                     else
8906                                     {
8907
8908                                         bCleanExtents = TRUE;
8909                                     }
8910                                 }
8911                                 __except( EXCEPTION_EXECUTE_HANDLER)
8912                                 {
8913
8914                                     ntStatus = GetExceptionCode();
8915
8916                                     AFSDbgTrace(( 0,
8917                                                   0,
8918                                                   "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
8919                                                   ObjectInfo->FileId.Cell,
8920                                                   ObjectInfo->FileId.Volume,
8921                                                   ObjectInfo->FileId.Vnode,
8922                                                   ObjectInfo->FileId.Unique,
8923                                                   ntStatus));
8924
8925                                     SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
8926                                 }
8927
8928                                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
8929                                               AFS_TRACE_LEVEL_VERBOSE,
8930                                               "AFSPerformObjectInvalidation Releasing Fcb SectionObject lock %p EXCL %08lX\n",
8931                                               &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
8932                                               PsGetCurrentThread()));
8933
8934                                 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
8935                             }
8936                         }
8937                         else
8938                         {
8939
8940                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
8941
8942                             bExtentsLocked = FALSE;
8943
8944                             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
8945                                           AFS_TRACE_LEVEL_VERBOSE,
8946                                           "AFSPerformObjectInvalidation Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
8947                                           &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
8948                                           PsGetCurrentThread()));
8949
8950                             AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
8951                                             TRUE);
8952
8953                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
8954
8955                             bLocked = FALSE;
8956
8957                             //
8958                             // Must build a list of non-dirty ranges from the beginning of the file
8959                             // to the end.  There can be at most (Fcb->Specific.File.ExtentsDirtyCount + 1)
8960                             // ranges.  In all but the most extreme random data write scenario there will
8961                             // be significantly fewer.
8962                             //
8963                             // For each range we need offset and size.
8964                             //
8965
8966                             AFSByteRange * ByteRangeList = NULL;
8967                             ULONG          ulByteRangeCount = 0;
8968                             ULONG          ulIndex;
8969                             BOOLEAN        bPurgeOnClose = FALSE;
8970
8971                             __try
8972                             {
8973
8974                                 ulByteRangeCount = AFSConstructCleanByteRangeList( ObjectInfo->Fcb,
8975                                                                                    &ByteRangeList);
8976
8977                                 if ( ByteRangeList != NULL ||
8978                                      ulByteRangeCount == 0)
8979                                 {
8980
8981                                     for ( ulIndex = 0; ulIndex < ulByteRangeCount; ulIndex++)
8982                                     {
8983
8984                                         ULONG ulSize;
8985
8986                                         do {
8987
8988                                             ulSize = ByteRangeList[ulIndex].Length.QuadPart > DWORD_MAX ? DWORD_MAX : ByteRangeList[ulIndex].Length.LowPart;
8989
8990                                             if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
8991                                                 !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
8992                                                                       &ByteRangeList[ulIndex].FileOffset,
8993                                                                       ulSize,
8994                                                                       FALSE))
8995                                             {
8996
8997                                                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
8998                                                               AFS_TRACE_LEVEL_WARNING,
8999                                                               "AFSPerformObjectInvalidation [1] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9000                                                               ObjectInfo->FileId.Cell,
9001                                                               ObjectInfo->FileId.Volume,
9002                                                               ObjectInfo->FileId.Vnode,
9003                                                               ObjectInfo->FileId.Unique));
9004
9005                                                 bPurgeOnClose = TRUE;
9006                                             }
9007                                             else
9008                                             {
9009
9010                                                 bCleanExtents = TRUE;
9011                                             }
9012
9013                                             ByteRangeList[ulIndex].Length.QuadPart -= ulSize;
9014
9015                                             ByteRangeList[ulIndex].FileOffset.QuadPart += ulSize;
9016
9017                                         } while ( ByteRangeList[ulIndex].Length.QuadPart > 0);
9018                                     }
9019                                 }
9020                                 else
9021                                 {
9022
9023                                     //
9024                                     // We couldn't allocate the memory to build the purge list
9025                                     // so just walk the extent list while holding the ExtentsList Resource.
9026                                     // This could deadlock but we do not have much choice.
9027                                     //
9028
9029                                     AFSAcquireExcl(  &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9030                                                     TRUE);
9031                                     bExtentsLocked = TRUE;
9032
9033                                     le = ObjectInfo->Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
9034
9035                                     ulProcessCount = 0;
9036
9037                                     ulCount = (ULONG)ObjectInfo->Fcb->Specific.File.ExtentCount;
9038
9039                                     if( ulCount > 0)
9040                                     {
9041                                         pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
9042
9043                                         while( ulProcessCount < ulCount)
9044                                         {
9045                                             pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
9046
9047                                             if( !BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
9048                                             {
9049                                                 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9050                                                                           &pEntry->FileOffset,
9051                                                                           pEntry->Size,
9052                                                                           FALSE))
9053                                                 {
9054
9055                                                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9056                                                                   AFS_TRACE_LEVEL_WARNING,
9057                                                                   "AFSPerformObjectInvalidation [2] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9058                                                                   ObjectInfo->FileId.Cell,
9059                                                                   ObjectInfo->FileId.Volume,
9060                                                                   ObjectInfo->FileId.Vnode,
9061                                                                   ObjectInfo->FileId.Unique));
9062
9063                                                     bPurgeOnClose = TRUE;
9064                                                 }
9065                                                 else
9066                                                 {
9067
9068                                                     bCleanExtents = TRUE;
9069                                                 }
9070                                             }
9071
9072                                             if( liCurrentOffset.QuadPart < pEntry->FileOffset.QuadPart)
9073                                             {
9074
9075                                                 liFlushLength.QuadPart = pEntry->FileOffset.QuadPart - liCurrentOffset.QuadPart;
9076
9077                                                 while( liFlushLength.QuadPart > 0)
9078                                                 {
9079
9080                                                     if( liFlushLength.QuadPart > 512 * 1024000)
9081                                                     {
9082                                                         ulFlushLength = 512 * 1024000;
9083                                                     }
9084                                                     else
9085                                                     {
9086                                                         ulFlushLength = liFlushLength.LowPart;
9087                                                     }
9088
9089                                                     if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9090                                                                               &liCurrentOffset,
9091                                                                               ulFlushLength,
9092                                                                               FALSE))
9093                                                     {
9094
9095                                                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9096                                                                       AFS_TRACE_LEVEL_WARNING,
9097                                                                       "AFSPerformObjectInvalidation [3] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9098                                                                       ObjectInfo->FileId.Cell,
9099                                                                       ObjectInfo->FileId.Volume,
9100                                                                       ObjectInfo->FileId.Vnode,
9101                                                                       ObjectInfo->FileId.Unique));
9102
9103                                                         bPurgeOnClose = TRUE;
9104                                                     }
9105                                                     else
9106                                                     {
9107
9108                                                         bCleanExtents = TRUE;
9109                                                     }
9110
9111                                                     liFlushLength.QuadPart -= ulFlushLength;
9112                                                 }
9113                                             }
9114
9115                                             liCurrentOffset.QuadPart = pEntry->FileOffset.QuadPart + pEntry->Size;
9116
9117                                             ulProcessCount++;
9118                                             le = le->Flink;
9119                                         }
9120                                     }
9121                                     else
9122                                     {
9123                                         if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9124                                                                   NULL,
9125                                                                   0,
9126                                                                   FALSE))
9127                                         {
9128
9129                                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9130                                                           AFS_TRACE_LEVEL_WARNING,
9131                                                           "AFSPerformObjectInvalidation [4] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9132                                                           ObjectInfo->FileId.Cell,
9133                                                           ObjectInfo->FileId.Volume,
9134                                                           ObjectInfo->FileId.Vnode,
9135                                                           ObjectInfo->FileId.Unique));
9136
9137                                             bPurgeOnClose = TRUE;
9138                                         }
9139                                         else
9140                                         {
9141
9142                                             bCleanExtents = TRUE;
9143                                         }
9144                                     }
9145
9146                                     if ( bPurgeOnClose)
9147                                     {
9148
9149                                         SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9150                                     }
9151                                 }
9152                             }
9153                             __except( EXCEPTION_EXECUTE_HANDLER)
9154                             {
9155
9156                                 ntStatus = GetExceptionCode();
9157
9158                                 AFSDbgTrace(( 0,
9159                                               0,
9160                                               "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
9161                                               ObjectInfo->FileId.Cell,
9162                                               ObjectInfo->FileId.Volume,
9163                                               ObjectInfo->FileId.Vnode,
9164                                               ObjectInfo->FileId.Unique,
9165                                               ntStatus));
9166                             }
9167
9168                             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9169                                           AFS_TRACE_LEVEL_VERBOSE,
9170                                           "AFSPerformObjectInvalidation Releasing Fcb SectionObject lock %p EXCL %08lX\n",
9171                                           &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9172                                           PsGetCurrentThread()));
9173
9174                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
9175                         }
9176                     }
9177
9178                     if ( bExtentsLocked)
9179                     {
9180
9181                         AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9182                     }
9183
9184                     if ( bLocked)
9185                     {
9186
9187                         AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9188                     }
9189
9190                     if ( bCleanExtents)
9191                     {
9192
9193                         AFSReleaseCleanExtents( ObjectInfo->Fcb,
9194                                                 NULL);
9195                     }
9196                 }
9197
9198                 break;
9199             }
9200         }
9201
9202         //
9203         // Destroy the reference passed in by the caller to AFSInvalidateObject
9204         // or AFSQueueInvalidateObject
9205         //
9206
9207         lCount = AFSObjectInfoDecrement( ObjectInfo,
9208                                          AFS_OBJECT_REFERENCE_INVALIDATION);
9209
9210         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
9211                       AFS_TRACE_LEVEL_VERBOSE,
9212                       "AFSPerformObjectInvalidation Decrement count on object %p Cnt %d\n",
9213                       ObjectInfo,
9214                       lCount));
9215     }
9216
9217     return ntStatus;
9218 }