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