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