Windows: AFSInitPIOCtlDirectoryCB fixes
[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 %d\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 %d\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 *ParentObjectInfo)
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( ParentObjectInfo,
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             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5892         }
5893
5894         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
5895                       AFS_TRACE_LEVEL_VERBOSE,
5896                       "AFSInitPIOCtlDirectoryCB AFS_DIR_ENTRY_TAG allocated %p\n",
5897                       pDirNode);
5898
5899         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
5900                                                                                 sizeof( AFSNonPagedDirectoryCB),
5901                                                                                 AFS_DIR_ENTRY_NP_TAG);
5902
5903         if( pNonPagedDirEntry == NULL)
5904         {
5905
5906             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5907         }
5908
5909         RtlZeroMemory( pDirNode,
5910                        ulEntryLength);
5911
5912         RtlZeroMemory( pNonPagedDirEntry,
5913                        sizeof( AFSNonPagedDirectoryCB));
5914
5915         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
5916
5917         pDirNode->NonPaged = pNonPagedDirEntry;
5918
5919         pDirNode->ObjectInformation = pObjectInfoCB;
5920
5921         pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_PIOCTL_INDEX;
5922
5923         //
5924         // Set valid entry
5925         //
5926
5927         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_FAKE);
5928
5929         pDirNode->NameInformation.FileName.Length = AFSPIOCtlName.Length;
5930
5931         pDirNode->NameInformation.FileName.MaximumLength = AFSPIOCtlName.Length;
5932
5933         pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
5934
5935         RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
5936                        AFSPIOCtlName.Buffer,
5937                        pDirNode->NameInformation.FileName.Length);
5938
5939         pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
5940                                                                        TRUE);
5941
5942         if ( InterlockedCompareExchangePointer( (PVOID *)&ParentObjectInfo->Specific.Directory.PIOCtlDirectoryCB, pDirNode, NULL) != NULL)
5943         {
5944
5945             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
5946                           AFS_TRACE_LEVEL_WARNING,
5947                           "AFSInitPIOCtlDirectoryCB Raced PIOCtlDirectoryCB %p pFcb %p\n",
5948                           ParentObjectInfo->Specific.Directory.PIOCtlDirectoryCB,
5949                           pDirNode);
5950
5951             try_return( ntStatus = STATUS_REPARSE);
5952         }
5953
5954 try_exit:
5955
5956         if ( ntStatus != STATUS_SUCCESS)
5957         {
5958
5959             if ( pDirNode != NULL)
5960             {
5961
5962                 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
5963                               AFS_TRACE_LEVEL_VERBOSE,
5964                               "AFSInitPIOCtlDirectoryCB AFS_DIR_ENTRY_TAG deallocating %p\n",
5965                               pDirNode);
5966
5967                 AFSExFreePoolWithTag( pDirNode, AFS_DIR_ENTRY_TAG);
5968             }
5969
5970             if( pNonPagedDirEntry != NULL)
5971             {
5972
5973                 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
5974
5975                 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
5976             }
5977
5978             if ( pObjectInfoCB != NULL)
5979             {
5980
5981                 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
5982                                                  AFS_OBJECT_REFERENCE_DIRENTRY);
5983
5984                 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
5985                               AFS_TRACE_LEVEL_VERBOSE,
5986                               "AFSInitPIOCtlDirectoryCB Decrement count on object %p Cnt %d\n",
5987                               pObjectInfoCB,
5988                               lCount);
5989
5990                 AFSDeleteObjectInfo( pObjectInfoCB);
5991             }
5992         }
5993     }
5994
5995     return ntStatus;
5996 }
5997
5998 NTSTATUS
5999 AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB,
6000                            IN AFSDirectoryCB *DirectoryCB,
6001                            IN UNICODE_STRING *ParentPathName,
6002                            IN AFSNameArrayHdr *RelatedNameArray,
6003                            IN GUID           *AuthGroup,
6004                            OUT AFSFileInfoCB *FileInfo)
6005 {
6006
6007     NTSTATUS ntStatus = STATUS_SUCCESS;
6008     AFSDirEnumEntry *pDirEntry = NULL;
6009     UNICODE_STRING uniFullPathName = {0};
6010     AFSNameArrayHdr    *pNameArray = NULL;
6011     AFSVolumeCB *pVolumeCB = NULL;
6012     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
6013     WCHAR *pwchBuffer = NULL;
6014     UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
6015     ULONG ulNameDifference = 0;
6016     LONG lCount;
6017
6018     __Enter
6019     {
6020
6021         //
6022         // Retrieve a target name for the entry
6023         //
6024
6025         AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
6026                           TRUE);
6027
6028         if( DirectoryCB->NameInformation.TargetName.Length == 0)
6029         {
6030
6031             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6032
6033             ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
6034                                               AuthGroup,
6035                                               FALSE,
6036                                               &pDirEntry);
6037
6038             if( !NT_SUCCESS( ntStatus) ||
6039                 pDirEntry->TargetNameLength == 0)
6040             {
6041
6042                 if( pDirEntry != NULL)
6043                 {
6044
6045                     ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
6046                 }
6047
6048                 try_return( ntStatus);
6049             }
6050
6051             AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
6052                             TRUE);
6053
6054             if( DirectoryCB->NameInformation.TargetName.Length == 0)
6055             {
6056
6057                 //
6058                 // Update the target name
6059                 //
6060
6061                 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
6062                                                 &DirectoryCB->Flags,
6063                                                 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
6064                                                 (USHORT)pDirEntry->TargetNameLength);
6065
6066                 if( !NT_SUCCESS( ntStatus))
6067                 {
6068
6069                     AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6070
6071                     try_return( ntStatus);
6072                 }
6073             }
6074
6075             AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
6076         }
6077
6078         //
6079         // Need to pass the full path in for parsing.
6080         //
6081
6082         if( AFSIsRelativeName( &DirectoryCB->NameInformation.TargetName))
6083         {
6084
6085             uniFullPathName.Length = 0;
6086             uniFullPathName.MaximumLength = ParentPathName->Length +
6087                                                     sizeof( WCHAR) +
6088                                                     DirectoryCB->NameInformation.TargetName.Length;
6089
6090             uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6091                                                                         uniFullPathName.MaximumLength,
6092                                                                         AFS_NAME_BUFFER_SIX_TAG);
6093
6094             if( uniFullPathName.Buffer == NULL)
6095             {
6096
6097                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6098
6099                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6100             }
6101
6102             pwchBuffer = uniFullPathName.Buffer;
6103
6104             RtlZeroMemory( uniFullPathName.Buffer,
6105                            uniFullPathName.MaximumLength);
6106
6107             RtlCopyMemory( uniFullPathName.Buffer,
6108                            ParentPathName->Buffer,
6109                            ParentPathName->Length);
6110
6111             uniFullPathName.Length = ParentPathName->Length;
6112
6113             if( uniFullPathName.Buffer[ (uniFullPathName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
6114                 DirectoryCB->NameInformation.TargetName.Buffer[ 0] != L'\\')
6115             {
6116
6117                 uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)] = L'\\';
6118
6119                 uniFullPathName.Length += sizeof( WCHAR);
6120             }
6121
6122             RtlCopyMemory( &uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)],
6123                            DirectoryCB->NameInformation.TargetName.Buffer,
6124                            DirectoryCB->NameInformation.TargetName.Length);
6125
6126             uniFullPathName.Length += DirectoryCB->NameInformation.TargetName.Length;
6127
6128             uniParsedName.Length = uniFullPathName.Length - ParentPathName->Length;
6129             uniParsedName.MaximumLength = uniParsedName.Length;
6130
6131             uniParsedName.Buffer = &uniFullPathName.Buffer[ ParentPathName->Length/sizeof( WCHAR)];
6132
6133             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6134
6135             //
6136             // We populate up to the current parent
6137             //
6138
6139             if( RelatedNameArray != NULL)
6140             {
6141
6142                 pNameArray = AFSInitNameArray( NULL,
6143                                                RelatedNameArray->MaxElementCount);
6144
6145                 if( pNameArray == NULL)
6146                 {
6147
6148                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6149                 }
6150
6151                 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
6152                                                                  RelatedNameArray,
6153                                                                  ParentDirectoryCB);
6154             }
6155             else
6156             {
6157
6158                 pNameArray = AFSInitNameArray( NULL,
6159                                                0);
6160
6161                 if( pNameArray == NULL)
6162                 {
6163
6164                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6165                 }
6166
6167                 ntStatus = AFSPopulateNameArray( pNameArray,
6168                                                  NULL,
6169                                                  ParentDirectoryCB);
6170             }
6171
6172             if( !NT_SUCCESS( ntStatus))
6173             {
6174
6175                 try_return( ntStatus);
6176             }
6177
6178             pVolumeCB = ParentDirectoryCB->ObjectInformation->VolumeCB;
6179
6180             pParentDirEntry = ParentDirectoryCB;
6181         }
6182         else
6183         {
6184
6185             uniFullPathName.Length = 0;
6186             uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
6187
6188             uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6189                                                                         uniFullPathName.MaximumLength,
6190                                                                         AFS_NAME_BUFFER_SEVEN_TAG);
6191
6192             if( uniFullPathName.Buffer == NULL)
6193             {
6194
6195                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6196
6197                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6198             }
6199
6200             pwchBuffer = uniFullPathName.Buffer;
6201
6202             RtlZeroMemory( uniFullPathName.Buffer,
6203                            uniFullPathName.MaximumLength);
6204
6205             RtlCopyMemory( uniFullPathName.Buffer,
6206                            DirectoryCB->NameInformation.TargetName.Buffer,
6207                            DirectoryCB->NameInformation.TargetName.Length);
6208
6209             uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6210
6211             //
6212             // This name should begin with the \afs server so parse it off and check it
6213             //
6214
6215             FsRtlDissectName( uniFullPathName,
6216                               &uniComponentName,
6217                               &uniRemainingPath);
6218
6219             if( RtlCompareUnicodeString( &uniComponentName,
6220                                          &AFSServerName,
6221                                          TRUE) != 0)
6222             {
6223
6224                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6225
6226                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
6227                               AFS_TRACE_LEVEL_ERROR,
6228                               "AFSRetrieveFileAttributes Name %wZ contains invalid server name\n",
6229                               &uniFullPathName);
6230
6231                 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
6232             }
6233
6234             uniFullPathName = uniRemainingPath;
6235
6236             uniParsedName = uniFullPathName;
6237
6238             ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
6239
6240             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6241
6242             //
6243             // Our name array
6244             //
6245
6246             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
6247                                            0);
6248
6249             if( pNameArray == NULL)
6250             {
6251
6252                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6253             }
6254
6255             pVolumeCB = AFSGlobalRoot;
6256
6257             pParentDirEntry = AFSGlobalRoot->DirectoryCB;
6258         }
6259
6260         //
6261         // Increment the ref count on the volume and dir entry for correct processing below
6262         //
6263
6264         lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
6265
6266         AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6267                       AFS_TRACE_LEVEL_VERBOSE,
6268                       "AFSRetrieveFileAttributes Increment count on volume %p Cnt %d\n",
6269                       pVolumeCB,
6270                       lCount);
6271
6272         lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
6273
6274         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6275                       AFS_TRACE_LEVEL_VERBOSE,
6276                       "AFSRetrieveFileAttributes Increment count on %wZ DE %p Ccb %p Cnt %d\n",
6277                       &pParentDirEntry->NameInformation.FileName,
6278                       pParentDirEntry,
6279                       NULL,
6280                       lCount);
6281
6282         ntStatus = AFSLocateNameEntry( NULL,
6283                                        NULL,
6284                                        &uniFullPathName,
6285                                        &uniParsedName,
6286                                        pNameArray,
6287                                        AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL,
6288                                        &pVolumeCB,
6289                                        &pParentDirEntry,
6290                                        &pDirectoryEntry,
6291                                        NULL);
6292
6293         if( !NT_SUCCESS( ntStatus) ||
6294             ntStatus == STATUS_REPARSE)
6295         {
6296
6297             //
6298             // The volume lock was released on failure or reparse above
6299             // Except for STATUS_OBJECT_NAME_NOT_FOUND
6300             //
6301
6302             if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
6303             {
6304
6305                 if( pVolumeCB != NULL)
6306                 {
6307
6308                     lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6309
6310                     AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6311                                   AFS_TRACE_LEVEL_VERBOSE,
6312                                   "AFSRetrieveFileAttributes Decrement count on volume %p Cnt %d\n",
6313                                   pVolumeCB,
6314                                   lCount);
6315                 }
6316
6317                 if( pDirectoryEntry != NULL)
6318                 {
6319
6320                     lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
6321
6322                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6323                                   AFS_TRACE_LEVEL_VERBOSE,
6324                                   "AFSRetrieveFileAttributes Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6325                                   &pDirectoryEntry->NameInformation.FileName,
6326                                   pDirectoryEntry,
6327                                   NULL,
6328                                   lCount);
6329
6330                     ASSERT( lCount >= 0);
6331                 }
6332                 else
6333                 {
6334
6335                     lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
6336
6337                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6338                                   AFS_TRACE_LEVEL_VERBOSE,
6339                                   "AFSRetrieveFileAttributes Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
6340                                   &pParentDirEntry->NameInformation.FileName,
6341                                   pParentDirEntry,
6342                                   NULL,
6343                                   lCount);
6344
6345                     ASSERT( lCount >= 0);
6346                 }
6347             }
6348
6349             pVolumeCB = NULL;
6350
6351             try_return( ntStatus);
6352         }
6353
6354         //
6355         // Store off the information
6356         //
6357
6358         FileInfo->FileAttributes = pDirectoryEntry->ObjectInformation->FileAttributes;
6359
6360         //
6361         // Check for the mount point being returned
6362         //
6363
6364         if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT)
6365         {
6366
6367             FileInfo->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
6368         }
6369         else if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK ||
6370                  pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DFSLINK)
6371         {
6372
6373             if ( FileInfo->FileAttributes == FILE_ATTRIBUTE_NORMAL)
6374             {
6375
6376                 FileInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
6377             }
6378             else
6379             {
6380
6381                 FileInfo->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
6382             }
6383         }
6384
6385         FileInfo->AllocationSize = pDirectoryEntry->ObjectInformation->AllocationSize;
6386
6387         FileInfo->EndOfFile = pDirectoryEntry->ObjectInformation->EndOfFile;
6388
6389         FileInfo->CreationTime = pDirectoryEntry->ObjectInformation->CreationTime;
6390
6391         FileInfo->LastAccessTime = pDirectoryEntry->ObjectInformation->LastAccessTime;
6392
6393         FileInfo->LastWriteTime = pDirectoryEntry->ObjectInformation->LastWriteTime;
6394
6395         FileInfo->ChangeTime = pDirectoryEntry->ObjectInformation->ChangeTime;
6396
6397         //
6398         // Remove the reference made above
6399         //
6400
6401         lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
6402
6403         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6404                       AFS_TRACE_LEVEL_VERBOSE,
6405                       "AFSRetrieveFileAttributes Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
6406                       &pDirectoryEntry->NameInformation.FileName,
6407                       pDirectoryEntry,
6408                       NULL,
6409                       lCount);
6410
6411         ASSERT( lCount >= 0);
6412
6413 try_exit:
6414
6415         if( pDirEntry != NULL)
6416         {
6417
6418             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
6419         }
6420
6421         if( pVolumeCB != NULL)
6422         {
6423
6424             lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6425
6426             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6427                           AFS_TRACE_LEVEL_VERBOSE,
6428                           "AFSRetrieveFileAttributes Decrement2 count on volume %p Cnt %d\n",
6429                           pVolumeCB,
6430                           lCount);
6431         }
6432
6433         if( pNameArray != NULL)
6434         {
6435
6436             AFSFreeNameArray( pNameArray);
6437         }
6438
6439         if( pwchBuffer != NULL)
6440         {
6441
6442             //
6443             // Always free the buffer that we allocated as AFSLocateNameEntry
6444             // will not free it.  If uniFullPathName.Buffer was allocated by
6445             // AFSLocateNameEntry, then we must free that as well.
6446             // Check that the uniFullPathName.Buffer in the string is not the same
6447             // offset by the length of the server name
6448             //
6449
6450             if( uniFullPathName.Length > 0 &&
6451                 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
6452             {
6453
6454                 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
6455             }
6456
6457             AFSExFreePoolWithTag( pwchBuffer, 0);
6458         }
6459     }
6460
6461     return ntStatus;
6462 }
6463
6464 AFSObjectInfoCB *
6465 AFSAllocateObjectInfo( IN AFSObjectInfoCB *ParentObjectInfo,
6466                        IN ULONGLONG HashIndex)
6467 {
6468
6469     NTSTATUS ntStatus = STATUS_SUCCESS;
6470     AFSObjectInfoCB *pObjectInfo = NULL;
6471     LONG lCount;
6472
6473     __Enter
6474     {
6475
6476         pObjectInfo = (AFSObjectInfoCB *)AFSExAllocatePoolWithTag( PagedPool,
6477                                                                    sizeof( AFSObjectInfoCB),
6478                                                                    AFS_OBJECT_INFO_TAG);
6479
6480         if( pObjectInfo == NULL)
6481         {
6482
6483             try_return( pObjectInfo);
6484         }
6485
6486         RtlZeroMemory( pObjectInfo,
6487                        sizeof( AFSObjectInfoCB));
6488
6489         pObjectInfo->NonPagedInfo = (AFSNonPagedObjectInfoCB *)AFSExAllocatePoolWithTag( NonPagedPool,
6490                                                                                          sizeof( AFSNonPagedObjectInfoCB),
6491                                                                                          AFS_NP_OBJECT_INFO_TAG);
6492
6493         if( pObjectInfo->NonPagedInfo == NULL)
6494         {
6495
6496             AFSExFreePoolWithTag( pObjectInfo, AFS_OBJECT_INFO_TAG);
6497
6498             try_return( pObjectInfo = NULL);
6499         }
6500
6501         ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6502
6503         ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
6504
6505         pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock = &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock;
6506
6507         pObjectInfo->VolumeCB = ParentObjectInfo->VolumeCB;
6508
6509         pObjectInfo->ParentObjectInformation = ParentObjectInfo;
6510
6511         if( ParentObjectInfo != NULL)
6512         {
6513
6514             lCount = AFSObjectInfoIncrement( ParentObjectInfo,
6515                                              AFS_OBJECT_REFERENCE_CHILD);
6516
6517             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
6518                           AFS_TRACE_LEVEL_VERBOSE,
6519                           "AFSAllocateObjectInfo Increment count on parent object %p Cnt %d\n",
6520                           ParentObjectInfo,
6521                           lCount);
6522         }
6523
6524         //
6525         // Initialize the access time
6526         //
6527
6528         KeQueryTickCount( &pObjectInfo->LastAccessCount);
6529
6530         if( HashIndex != 0)
6531         {
6532
6533             //
6534             // Insert the entry into the object tree and list
6535             //
6536
6537             pObjectInfo->TreeEntry.HashIndex = HashIndex;
6538
6539             if( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead == NULL)
6540             {
6541
6542                 ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead = &pObjectInfo->TreeEntry;
6543             }
6544             else
6545             {
6546
6547                 ntStatus = AFSInsertHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
6548                                                &pObjectInfo->TreeEntry);
6549
6550                 ASSERT( NT_SUCCESS( ntStatus));
6551             }
6552
6553             //
6554             // And the object list in the volume
6555             //
6556
6557             if( ParentObjectInfo->VolumeCB->ObjectInfoListHead == NULL)
6558             {
6559
6560                 ParentObjectInfo->VolumeCB->ObjectInfoListHead = pObjectInfo;
6561             }
6562             else
6563             {
6564
6565                 ParentObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = (void *)pObjectInfo;
6566
6567                 pObjectInfo->ListEntry.bLink = (void *)ParentObjectInfo->VolumeCB->ObjectInfoListTail;
6568             }
6569
6570             ParentObjectInfo->VolumeCB->ObjectInfoListTail = pObjectInfo;
6571
6572             //
6573             // Indicate the object is in the hash tree and linked list in the volume
6574             //
6575
6576             SetFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE | AFS_OBJECT_INSERTED_VOLUME_LIST);
6577         }
6578
6579 try_exit:
6580
6581         NOTHING;
6582     }
6583
6584     return pObjectInfo;
6585 }
6586
6587 LONG
6588 AFSObjectInfoIncrement( IN AFSObjectInfoCB *ObjectInfo,
6589                         IN LONG Reason)
6590 {
6591
6592     LONG lCount;
6593
6594     if ( ObjectInfo->ObjectReferenceCount == 0)
6595     {
6596
6597         AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6598                         TRUE);
6599
6600         lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6601     }
6602     else
6603     {
6604
6605         AFSAcquireShared( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6606                           TRUE);
6607
6608         lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6609
6610         if ( lCount == 1)
6611         {
6612
6613             AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6614
6615             AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6616                             TRUE);
6617         }
6618     }
6619
6620     InterlockedIncrement( &ObjectInfo->ObjectReferences[ Reason]);
6621
6622     AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6623
6624     return lCount;
6625 }
6626
6627 LONG
6628 AFSObjectInfoDecrement( IN AFSObjectInfoCB *ObjectInfo,
6629                         IN LONG Reason)
6630 {
6631
6632     LONG lCount;
6633
6634     AFSAcquireShared( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6635                       TRUE);
6636
6637     lCount = InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);
6638
6639     if ( lCount == 0)
6640     {
6641
6642         lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6643
6644         AFSReleaseResource(&ObjectInfo->NonPagedInfo->ObjectInfoLock);
6645
6646         AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6647                         TRUE);
6648
6649         lCount = InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);
6650     }
6651
6652     lCount = InterlockedDecrement( &ObjectInfo->ObjectReferences[ Reason]);
6653
6654     ASSERT( lCount >= 0);
6655
6656     AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6657
6658     return lCount;
6659 }
6660
6661
6662
6663 void
6664 AFSDeleteObjectInfo( IN AFSObjectInfoCB *ObjectInfo)
6665 {
6666
6667     BOOLEAN bAcquiredTreeLock = FALSE;
6668     LONG lCount;
6669
6670     if ( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_ROOT_VOLUME))
6671     {
6672
6673         //
6674         // AFSDeleteObjectInfo should never be called on the ObjectInformationCB
6675         // embedded in the VolumeCB.
6676         //
6677
6678         ASSERT( TRUE);
6679
6680         return;
6681     }
6682
6683     ASSERT( ObjectInfo->ObjectReferenceCount == 0);
6684
6685     if( !ExIsResourceAcquiredExclusiveLite( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock))
6686     {
6687
6688         ASSERT( !ExIsResourceAcquiredLite( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock));
6689
6690         AFSAcquireExcl( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
6691                         TRUE);
6692
6693         bAcquiredTreeLock = TRUE;
6694     }
6695
6696     //
6697     // Remove it from the tree and list if it was inserted
6698     //
6699
6700     if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
6701     {
6702
6703         AFSRemoveHashEntry( &ObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
6704                             &ObjectInfo->TreeEntry);
6705     }
6706
6707     if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_INSERTED_VOLUME_LIST))
6708     {
6709
6710         if( ObjectInfo->ListEntry.fLink == NULL)
6711         {
6712
6713             ObjectInfo->VolumeCB->ObjectInfoListTail = (AFSObjectInfoCB *)ObjectInfo->ListEntry.bLink;
6714
6715             if( ObjectInfo->VolumeCB->ObjectInfoListTail != NULL)
6716             {
6717
6718                 ObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = NULL;
6719             }
6720         }
6721         else
6722         {
6723
6724             ((AFSObjectInfoCB *)(ObjectInfo->ListEntry.fLink))->ListEntry.bLink = ObjectInfo->ListEntry.bLink;
6725         }
6726
6727         if( ObjectInfo->ListEntry.bLink == NULL)
6728         {
6729
6730             ObjectInfo->VolumeCB->ObjectInfoListHead = (AFSObjectInfoCB *)ObjectInfo->ListEntry.fLink;
6731
6732             if( ObjectInfo->VolumeCB->ObjectInfoListHead != NULL)
6733             {
6734
6735                 ObjectInfo->VolumeCB->ObjectInfoListHead->ListEntry.bLink = NULL;
6736             }
6737         }
6738         else
6739         {
6740
6741             ((AFSObjectInfoCB *)(ObjectInfo->ListEntry.bLink))->ListEntry.fLink = ObjectInfo->ListEntry.fLink;
6742         }
6743     }
6744
6745     if( ObjectInfo->ParentObjectInformation != NULL)
6746     {
6747
6748         lCount = AFSObjectInfoDecrement( ObjectInfo->ParentObjectInformation,
6749                                          AFS_OBJECT_REFERENCE_CHILD);
6750
6751         AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
6752                       AFS_TRACE_LEVEL_VERBOSE,
6753                       "AFSDeleteObjectInfo Decrement count on parent object %p Cnt %d\n",
6754                       ObjectInfo->ParentObjectInformation,
6755                       lCount);
6756     }
6757
6758     if( bAcquiredTreeLock)
6759     {
6760
6761         AFSReleaseResource( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
6762     }
6763
6764     //
6765     // Release the fid in the service
6766     //
6767
6768     if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_HELD_IN_SERVICE))
6769     {
6770
6771         AFSReleaseFid( &ObjectInfo->FileId);
6772     }
6773
6774     ExDeleteResourceLite( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6775
6776     ExDeleteResourceLite( &ObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6777
6778     AFSExFreePoolWithTag( ObjectInfo->NonPagedInfo, AFS_NP_OBJECT_INFO_TAG);
6779
6780     AFSExFreePoolWithTag( ObjectInfo, AFS_OBJECT_INFO_TAG);
6781
6782     return;
6783 }
6784
6785 NTSTATUS
6786 AFSEvaluateRootEntry( IN AFSDirectoryCB *DirectoryCB,
6787                       OUT AFSDirectoryCB **TargetDirEntry)
6788 {
6789
6790     NTSTATUS ntStatus = STATUS_SUCCESS;
6791     AFSDirEnumEntry *pDirEntry = NULL;
6792     UNICODE_STRING uniFullPathName = {0};
6793     AFSNameArrayHdr    *pNameArray = NULL;
6794     AFSVolumeCB *pVolumeCB = NULL;
6795     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
6796     WCHAR *pwchBuffer = NULL;
6797     UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
6798     ULONG ulNameDifference = 0;
6799     GUID    stAuthGroup;
6800     LONG lCount;
6801
6802     __Enter
6803     {
6804
6805         ntStatus = AFSRetrieveValidAuthGroup( NULL,
6806                                               DirectoryCB->ObjectInformation,
6807                                               FALSE,
6808                                               &stAuthGroup);
6809
6810         if( !NT_SUCCESS( ntStatus))
6811         {
6812             try_return( ntStatus);
6813         }
6814
6815         //
6816         // Retrieve a target name for the entry
6817         //
6818
6819         AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
6820                           TRUE);
6821
6822         if( DirectoryCB->NameInformation.TargetName.Length == 0)
6823         {
6824
6825             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6826
6827             ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
6828                                               &stAuthGroup,
6829                                               FALSE,
6830                                               &pDirEntry);
6831
6832             if( !NT_SUCCESS( ntStatus) ||
6833                 pDirEntry->TargetNameLength == 0)
6834             {
6835
6836                 if( pDirEntry != NULL)
6837                 {
6838
6839                     ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
6840                 }
6841
6842                 try_return( ntStatus);
6843             }
6844
6845             AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
6846                             TRUE);
6847
6848             if( DirectoryCB->NameInformation.TargetName.Length == 0)
6849             {
6850
6851                 //
6852                 // Update the target name
6853                 //
6854
6855                 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
6856                                                 &DirectoryCB->Flags,
6857                                                 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
6858                                                 (USHORT)pDirEntry->TargetNameLength);
6859
6860                 if( !NT_SUCCESS( ntStatus))
6861                 {
6862
6863                     AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6864
6865                     try_return( ntStatus);
6866                 }
6867             }
6868
6869             AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
6870         }
6871
6872         //
6873         // Need to pass the full path in for parsing.
6874         //
6875
6876         uniFullPathName.Length = 0;
6877         uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
6878
6879         uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6880                                                                     uniFullPathName.MaximumLength,
6881                                                                     AFS_NAME_BUFFER_EIGHT_TAG);
6882
6883         if( uniFullPathName.Buffer == NULL)
6884         {
6885
6886             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6887
6888             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6889         }
6890
6891         pwchBuffer = uniFullPathName.Buffer;
6892
6893         RtlZeroMemory( uniFullPathName.Buffer,
6894                        uniFullPathName.MaximumLength);
6895
6896         RtlCopyMemory( uniFullPathName.Buffer,
6897                        DirectoryCB->NameInformation.TargetName.Buffer,
6898                        DirectoryCB->NameInformation.TargetName.Length);
6899
6900         uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6901
6902         //
6903         // This name should begin with the \afs server so parse it off and chech it
6904         //
6905
6906         FsRtlDissectName( uniFullPathName,
6907                           &uniComponentName,
6908                           &uniRemainingPath);
6909
6910         if( RtlCompareUnicodeString( &uniComponentName,
6911                                      &AFSServerName,
6912                                      TRUE) != 0)
6913         {
6914
6915             //
6916             // Try evaluating the full path
6917             //
6918
6919             uniFullPathName.Buffer = pwchBuffer;
6920
6921             uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6922
6923             uniFullPathName.MaximumLength = uniFullPathName.Length;
6924         }
6925         else
6926         {
6927
6928             uniFullPathName = uniRemainingPath;
6929         }
6930
6931         uniParsedName = uniFullPathName;
6932
6933         ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
6934
6935         AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6936
6937         //
6938         // Our name array
6939         //
6940
6941         pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
6942                                        0);
6943
6944         if( pNameArray == NULL)
6945         {
6946
6947             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6948         }
6949
6950         pVolumeCB = AFSGlobalRoot;
6951
6952         pParentDirEntry = AFSGlobalRoot->DirectoryCB;
6953
6954         lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
6955
6956         AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6957                       AFS_TRACE_LEVEL_VERBOSE,
6958                       "AFSEvaluateRootEntry Increment count on volume %p Cnt %d\n",
6959                       pVolumeCB,
6960                       lCount);
6961
6962         lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
6963
6964         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6965                       AFS_TRACE_LEVEL_VERBOSE,
6966                       "AFSEvaluateRootEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
6967                       &pParentDirEntry->NameInformation.FileName,
6968                       pParentDirEntry,
6969                       NULL,
6970                       lCount);
6971
6972         ntStatus = AFSLocateNameEntry( NULL,
6973                                        NULL,
6974                                        &uniFullPathName,
6975                                        &uniParsedName,
6976                                        pNameArray,
6977                                        0,
6978                                        &pVolumeCB,
6979                                        &pParentDirEntry,
6980                                        &pDirectoryEntry,
6981                                        NULL);
6982
6983         if( !NT_SUCCESS( ntStatus) ||
6984             ntStatus == STATUS_REPARSE)
6985         {
6986
6987             //
6988             // The volume lock was released on failure or reparse above
6989             // Except for STATUS_OBJECT_NAME_NOT_FOUND
6990             //
6991
6992             if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
6993             {
6994
6995                 if( pVolumeCB != NULL)
6996                 {
6997
6998                     lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6999
7000                     AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7001                                   AFS_TRACE_LEVEL_VERBOSE,
7002                                   "AFSEvaluateRootEntry Decrement count on volume %p Cnt %d\n",
7003                                   pVolumeCB,
7004                                   lCount);
7005                 }
7006
7007                 if( pDirectoryEntry != NULL)
7008                 {
7009
7010                     lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
7011
7012                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
7013                                   AFS_TRACE_LEVEL_VERBOSE,
7014                                   "AFSEvaluateRootEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
7015                                   &pDirectoryEntry->NameInformation.FileName,
7016                                   pDirectoryEntry,
7017                                   NULL,
7018                                   lCount);
7019
7020                     ASSERT( lCount >= 0);
7021                 }
7022                 else
7023                 {
7024
7025                     lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
7026
7027                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
7028                                   AFS_TRACE_LEVEL_VERBOSE,
7029                                   "AFSEvaluateRootEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
7030                                   &pParentDirEntry->NameInformation.FileName,
7031                                   pParentDirEntry,
7032                                   NULL,
7033                                   lCount);
7034
7035                     ASSERT( lCount >= 0);
7036                 }
7037             }
7038
7039             pVolumeCB = NULL;
7040
7041             try_return( ntStatus);
7042         }
7043
7044         //
7045         // Pass back the target dir entry for this request
7046         // The caller must release the DirOpenReferenceCount
7047         //
7048
7049         *TargetDirEntry = pDirectoryEntry;
7050
7051 try_exit:
7052
7053         if( pDirEntry != NULL)
7054         {
7055
7056             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
7057         }
7058
7059         if( pVolumeCB != NULL)
7060         {
7061
7062             lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
7063
7064             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7065                           AFS_TRACE_LEVEL_VERBOSE,
7066                           "AFSEvaluateRootEntry Decrement2 count on volume %p Cnt %d\n",
7067                           pVolumeCB,
7068                           lCount);
7069         }
7070
7071         if( pNameArray != NULL)
7072         {
7073
7074             AFSFreeNameArray( pNameArray);
7075         }
7076
7077         if( pwchBuffer != NULL)
7078         {
7079
7080             //
7081             // Always free the buffer that we allocated as AFSLocateNameEntry
7082             // will not free it.  If uniFullPathName.Buffer was allocated by
7083             // AFSLocateNameEntry, then we must free that as well.
7084             // Check that the uniFullPathName.Buffer in the string is not the same
7085             // offset by the length of the server name
7086             //
7087
7088             if( uniFullPathName.Length > 0 &&
7089                 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
7090             {
7091
7092                 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
7093             }
7094
7095             AFSExFreePoolWithTag( pwchBuffer, 0);
7096         }
7097     }
7098
7099     return ntStatus;
7100 }
7101
7102 NTSTATUS
7103 AFSCleanupFcb( IN AFSFcb *Fcb,
7104                IN BOOLEAN ForceFlush)
7105 {
7106
7107     NTSTATUS ntStatus = STATUS_SUCCESS;
7108     AFSDeviceExt *pRDRDeviceExt = NULL, *pControlDeviceExt = NULL;
7109     LARGE_INTEGER liTime;
7110     IO_STATUS_BLOCK stIoStatus;
7111
7112     __Enter
7113     {
7114
7115         pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
7116
7117         pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
7118
7119         if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
7120         {
7121
7122             if( !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) &&
7123                 !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
7124             {
7125
7126                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
7127                               AFS_TRACE_LEVEL_VERBOSE,
7128                               "AFSCleanupEntry Acquiring Fcb lock %p SHARED %08lX\n",
7129                               &Fcb->NPFcb->Resource,
7130                               PsGetCurrentThread());
7131
7132                 AFSAcquireShared( &Fcb->NPFcb->Resource,
7133                                   TRUE);
7134
7135                 if( Fcb->OpenReferenceCount > 0)
7136                 {
7137
7138                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
7139                                   AFS_TRACE_LEVEL_VERBOSE,
7140                                   "AFSCleanupEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
7141                                   &Fcb->NPFcb->SectionObjectResource,
7142                                   PsGetCurrentThread());
7143
7144                     AFSAcquireExcl( &Fcb->NPFcb->SectionObjectResource,
7145                                     TRUE);
7146
7147                     __try
7148                     {
7149
7150                         CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
7151                                       NULL,
7152                                       0,
7153                                       &stIoStatus);
7154
7155                         if( !NT_SUCCESS( stIoStatus.Status))
7156                         {
7157
7158                             AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
7159                                           AFS_TRACE_LEVEL_ERROR,
7160                                           "AFSCleanupFcb CcFlushCache [1] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
7161                                           Fcb->ObjectInformation->FileId.Cell,
7162                                           Fcb->ObjectInformation->FileId.Volume,
7163                                           Fcb->ObjectInformation->FileId.Vnode,
7164                                           Fcb->ObjectInformation->FileId.Unique,
7165                                           stIoStatus.Status,
7166                                           stIoStatus.Information);
7167
7168                             ntStatus = stIoStatus.Status;
7169                         }
7170
7171                         if (  Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
7172                         {
7173
7174                             if ( !CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
7175                                                        NULL,
7176                                                        0,
7177                                                        FALSE))
7178                             {
7179
7180                                 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
7181                                               AFS_TRACE_LEVEL_WARNING,
7182                                               "AFSCleanupFcb CcPurgeCacheSection [1] failure FID %08lX-%08lX-%08lX-%08lX\n",
7183                                               Fcb->ObjectInformation->FileId.Cell,
7184                                               Fcb->ObjectInformation->FileId.Volume,
7185                                               Fcb->ObjectInformation->FileId.Vnode,
7186                                               Fcb->ObjectInformation->FileId.Unique);
7187
7188                                 SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
7189                             }
7190                         }
7191                     }
7192                     __except( EXCEPTION_EXECUTE_HANDLER)
7193                     {
7194
7195                         ntStatus = GetExceptionCode();
7196
7197                         AFSDbgLogMsg( 0,
7198                                       0,
7199                                       "EXCEPTION - AFSCleanupFcb Cc [1] FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
7200                                       Fcb->ObjectInformation->FileId.Cell,
7201                                       Fcb->ObjectInformation->FileId.Volume,
7202                                       Fcb->ObjectInformation->FileId.Vnode,
7203                                       Fcb->ObjectInformation->FileId.Unique,
7204                                       ntStatus);
7205
7206                         SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
7207                     }
7208
7209                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
7210                                   AFS_TRACE_LEVEL_VERBOSE,
7211                                   "AFSCleanupFcb Releasing Fcb SectionObject lock %p EXCL %08lX\n",
7212                                   &Fcb->NPFcb->SectionObjectResource,
7213                                   PsGetCurrentThread());
7214
7215                     AFSReleaseResource( &Fcb->NPFcb->SectionObjectResource);
7216                 }
7217
7218                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
7219                               AFS_TRACE_LEVEL_VERBOSE,
7220                               "AFSCleanupEntry Releasing Fcb lock %p SHARED %08lX\n",
7221                               &Fcb->NPFcb->Resource,
7222                               PsGetCurrentThread());
7223
7224                 AFSReleaseResource( &Fcb->NPFcb->Resource);
7225
7226                 //
7227                 // Wait for any currently running flush or release requests to complete
7228                 //
7229
7230                 AFSWaitOnQueuedFlushes( Fcb);
7231
7232                 //
7233                 // Now perform another flush on the file
7234                 //
7235
7236                 if( !NT_SUCCESS( AFSFlushExtents( Fcb,
7237                                                   NULL)))
7238                 {
7239
7240                     AFSReleaseExtentsWithFlush( Fcb,
7241                                                 NULL,
7242                                                 TRUE);
7243                 }
7244             }
7245
7246             if( Fcb->OpenReferenceCount == 0 ||
7247                 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
7248                 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
7249             {
7250
7251                 AFSTearDownFcbExtents( Fcb,
7252                                        NULL);
7253             }
7254
7255             try_return( ntStatus);
7256         }
7257
7258         KeQueryTickCount( &liTime);
7259
7260         //
7261         // First up are there dirty extents in the cache to flush?
7262         //
7263
7264         if( BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
7265             BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
7266         {
7267
7268             //
7269             // The file has been marked as invalid.  Dump it
7270             //
7271
7272             AFSTearDownFcbExtents( Fcb,
7273                                    NULL);
7274         }
7275         else if( ForceFlush ||
7276             ( ( Fcb->Specific.File.ExtentsDirtyCount ||
7277                 Fcb->Specific.File.ExtentCount) &&
7278               (liTime.QuadPart - Fcb->Specific.File.LastServerFlush.QuadPart)
7279                                                     >= pControlDeviceExt->Specific.Control.FcbFlushTimeCount.QuadPart))
7280         {
7281             if( !NT_SUCCESS( AFSFlushExtents( Fcb,
7282                                               NULL)) &&
7283                 Fcb->OpenReferenceCount == 0)
7284             {
7285
7286                 AFSReleaseExtentsWithFlush( Fcb,
7287                                             NULL,
7288                                             TRUE);
7289             }
7290         }
7291
7292         //
7293         // If there are extents and they haven't been used recently *and*
7294         // are not being used
7295         //
7296
7297         if( ( ForceFlush ||
7298               ( 0 != Fcb->Specific.File.ExtentCount &&
7299                 0 != Fcb->Specific.File.LastExtentAccess.QuadPart &&
7300                 (liTime.QuadPart - Fcb->Specific.File.LastExtentAccess.QuadPart) >=
7301                                         (AFS_SERVER_PURGE_SLEEP * pControlDeviceExt->Specific.Control.FcbPurgeTimeCount.QuadPart))))
7302         {
7303
7304             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
7305                           AFS_TRACE_LEVEL_VERBOSE,
7306                           "AFSCleanupFcb Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
7307                           &Fcb->NPFcb->SectionObjectResource,
7308                           PsGetCurrentThread());
7309
7310             if ( AFSAcquireExcl( &Fcb->NPFcb->SectionObjectResource, ForceFlush))
7311             {
7312
7313                 __try
7314                 {
7315
7316                     CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
7317                                   NULL,
7318                                   0,
7319                                   &stIoStatus);
7320
7321                     if( !NT_SUCCESS( stIoStatus.Status))
7322                     {
7323
7324                         AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
7325                                       AFS_TRACE_LEVEL_ERROR,
7326                                       "AFSCleanupFcb CcFlushCache [2] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
7327                                       Fcb->ObjectInformation->FileId.Cell,
7328                                       Fcb->ObjectInformation->FileId.Volume,
7329                                       Fcb->ObjectInformation->FileId.Vnode,
7330                                       Fcb->ObjectInformation->FileId.Unique,
7331                                       stIoStatus.Status,
7332                                       stIoStatus.Information);
7333
7334                         ntStatus = stIoStatus.Status;
7335                     }
7336
7337                     if( ForceFlush &&
7338                         Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
7339                     {
7340
7341                         if ( !CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
7342                                                    NULL,
7343                                                    0,
7344                                                    FALSE))
7345                         {
7346
7347                             AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
7348                                           AFS_TRACE_LEVEL_WARNING,
7349                                           "AFSCleanupFcb CcPurgeCacheSection [2] failure FID %08lX-%08lX-%08lX-%08lX\n",
7350                                           Fcb->ObjectInformation->FileId.Cell,
7351                                           Fcb->ObjectInformation->FileId.Volume,
7352                                           Fcb->ObjectInformation->FileId.Vnode,
7353                                           Fcb->ObjectInformation->FileId.Unique);
7354
7355                             SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
7356                         }
7357                     }
7358                 }
7359                 __except( EXCEPTION_EXECUTE_HANDLER)
7360                 {
7361
7362                     ntStatus = GetExceptionCode();
7363
7364                     AFSDbgLogMsg( 0,
7365                                   0,
7366                                   "EXCEPTION - AFSCleanupFcb Cc [2] FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
7367                                   Fcb->ObjectInformation->FileId.Cell,
7368                                   Fcb->ObjectInformation->FileId.Volume,
7369                                   Fcb->ObjectInformation->FileId.Vnode,
7370                                   Fcb->ObjectInformation->FileId.Unique,
7371                                   ntStatus);
7372                 }
7373
7374                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
7375                               AFS_TRACE_LEVEL_VERBOSE,
7376                               "AFSCleanupFcb Releasing Fcb SectionObject lock %p EXCL %08lX\n",
7377                               &Fcb->NPFcb->SectionObjectResource,
7378                               PsGetCurrentThread());
7379
7380                 AFSReleaseResource( &Fcb->NPFcb->SectionObjectResource);
7381
7382                 if( Fcb->OpenReferenceCount <= 0)
7383                 {
7384
7385                     //
7386                     // Tear em down we'll not be needing them again
7387                     //
7388
7389                     AFSTearDownFcbExtents( Fcb,
7390                                            NULL);
7391                 }
7392             }
7393             else
7394             {
7395
7396                 ntStatus = STATUS_RETRY;
7397             }
7398         }
7399
7400 try_exit:
7401
7402         NOTHING;
7403     }
7404
7405     return ntStatus;
7406 }
7407
7408 NTSTATUS
7409 AFSUpdateDirEntryName( IN AFSDirectoryCB *DirectoryCB,
7410                        IN UNICODE_STRING *NewFileName)
7411 {
7412
7413     NTSTATUS ntStatus = STATUS_SUCCESS;
7414     WCHAR *pTmpBuffer = NULL;
7415
7416     __Enter
7417     {
7418
7419         if( NewFileName->Length > DirectoryCB->NameInformation.FileName.Length)
7420         {
7421
7422             if( BooleanFlagOn( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
7423             {
7424
7425                 AFSExFreePoolWithTag( DirectoryCB->NameInformation.FileName.Buffer, 0);
7426
7427                 ClearFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
7428
7429                 DirectoryCB->NameInformation.FileName.Buffer = NULL;
7430             }
7431
7432             //
7433             // OK, we need to allocate a new name buffer
7434             //
7435
7436             pTmpBuffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
7437                                                             NewFileName->Length,
7438                                                             AFS_NAME_BUFFER_NINE_TAG);
7439
7440             if( pTmpBuffer == NULL)
7441             {
7442
7443                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7444             }
7445
7446             DirectoryCB->NameInformation.FileName.Buffer = pTmpBuffer;
7447
7448             DirectoryCB->NameInformation.FileName.MaximumLength = NewFileName->Length;
7449
7450             SetFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
7451         }
7452
7453         DirectoryCB->NameInformation.FileName.Length = NewFileName->Length;
7454
7455         RtlCopyMemory( DirectoryCB->NameInformation.FileName.Buffer,
7456                        NewFileName->Buffer,
7457                        NewFileName->Length);
7458
7459 try_exit:
7460
7461         NOTHING;
7462     }
7463
7464     return ntStatus;
7465 }
7466
7467 NTSTATUS
7468 AFSReadCacheFile( IN void *ReadBuffer,
7469                   IN LARGE_INTEGER *ReadOffset,
7470                   IN ULONG RequestedDataLength,
7471                   IN OUT PULONG BytesRead)
7472 {
7473
7474     NTSTATUS            ntStatus = STATUS_SUCCESS;
7475     PIRP                pIrp = NULL;
7476     KEVENT              kEvent;
7477     PIO_STACK_LOCATION  pIoStackLocation = NULL;
7478     DEVICE_OBJECT      *pTargetDeviceObject = NULL;
7479     FILE_OBJECT        *pCacheFileObject = NULL;
7480
7481     __Enter
7482     {
7483
7484         pCacheFileObject = AFSReferenceCacheFileObject();
7485
7486         if( pCacheFileObject == NULL)
7487         {
7488             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
7489         }
7490
7491         pTargetDeviceObject = IoGetRelatedDeviceObject( pCacheFileObject);
7492
7493         //
7494         // Initialize the event
7495         //
7496
7497         KeInitializeEvent( &kEvent,
7498                            SynchronizationEvent,
7499                            FALSE);
7500
7501         //
7502         // Allocate an irp for this request.  This could also come from a
7503         // private pool, for instance.
7504         //
7505
7506         pIrp = IoAllocateIrp( pTargetDeviceObject->StackSize,
7507                               FALSE);
7508
7509         if( pIrp == NULL)
7510         {
7511
7512             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7513         }
7514
7515         //
7516         // Build the IRP's main body
7517         //
7518
7519         pIrp->UserBuffer = ReadBuffer;
7520
7521         pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
7522         pIrp->RequestorMode = KernelMode;
7523         pIrp->Flags |= IRP_READ_OPERATION;
7524
7525         //
7526         // Set up the I/O stack location.
7527         //
7528
7529         pIoStackLocation = IoGetNextIrpStackLocation( pIrp);
7530         pIoStackLocation->MajorFunction = IRP_MJ_READ;
7531         pIoStackLocation->DeviceObject = pTargetDeviceObject;
7532         pIoStackLocation->FileObject = pCacheFileObject;
7533         pIoStackLocation->Parameters.Read.Length = RequestedDataLength;
7534
7535         pIoStackLocation->Parameters.Read.ByteOffset.QuadPart = ReadOffset->QuadPart;
7536
7537         //
7538         // Set the completion routine.
7539         //
7540
7541         IoSetCompletionRoutine( pIrp,
7542                                 AFSIrpComplete,
7543                                 &kEvent,
7544                                 TRUE,
7545                                 TRUE,
7546                                 TRUE);
7547
7548         //
7549         // Send it to the FSD
7550         //
7551
7552         ntStatus = IoCallDriver( pTargetDeviceObject,
7553                                  pIrp);
7554
7555         if( NT_SUCCESS( ntStatus))
7556         {
7557
7558             //
7559             // Wait for the I/O
7560             //
7561
7562             ntStatus = KeWaitForSingleObject( &kEvent,
7563                                               Executive,
7564                                               KernelMode,
7565                                               FALSE,
7566                                               0);
7567
7568             if( NT_SUCCESS( ntStatus))
7569             {
7570
7571                 ntStatus = pIrp->IoStatus.Status;
7572
7573                 *BytesRead = (ULONG)pIrp->IoStatus.Information;
7574             }
7575         }
7576
7577 try_exit:
7578
7579         if( pCacheFileObject != NULL)
7580         {
7581             AFSReleaseCacheFileObject( pCacheFileObject);
7582         }
7583
7584         if( pIrp != NULL)
7585         {
7586
7587             if( pIrp->MdlAddress != NULL)
7588             {
7589
7590                 if( FlagOn( pIrp->MdlAddress->MdlFlags, MDL_PAGES_LOCKED))
7591                 {
7592
7593                     MmUnlockPages( pIrp->MdlAddress);
7594                 }
7595
7596                 IoFreeMdl( pIrp->MdlAddress);
7597             }
7598
7599             pIrp->MdlAddress = NULL;
7600
7601             //
7602             // Free the Irp
7603             //
7604
7605             IoFreeIrp( pIrp);
7606         }
7607     }
7608
7609     return ntStatus;
7610 }
7611
7612 NTSTATUS
7613 AFSIrpComplete( IN PDEVICE_OBJECT DeviceObject,
7614                 IN PIRP           Irp,
7615                 IN PVOID          Context)
7616 {
7617
7618     UNREFERENCED_PARAMETER(Irp);
7619     UNREFERENCED_PARAMETER(DeviceObject);
7620     KEVENT *pEvent = (KEVENT *)Context;
7621
7622     KeSetEvent( pEvent,
7623                 0,
7624                 FALSE);
7625
7626     return STATUS_MORE_PROCESSING_REQUIRED;
7627 }
7628
7629 BOOLEAN
7630 AFSIsDirectoryEmptyForDelete( IN AFSFcb *Fcb)
7631 {
7632
7633     BOOLEAN bIsEmpty = FALSE;
7634     AFSDirectoryCB *pDirEntry = NULL;
7635
7636     __Enter
7637     {
7638
7639         AFSAcquireShared( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
7640                           TRUE);
7641
7642         bIsEmpty = TRUE;
7643
7644         if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
7645         {
7646
7647             pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
7648
7649             while( pDirEntry != NULL)
7650             {
7651
7652                 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
7653                     !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
7654                 {
7655
7656                     bIsEmpty = FALSE;
7657
7658                     break;
7659                 }
7660
7661                 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
7662             }
7663
7664         }
7665
7666         AFSReleaseResource( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
7667     }
7668
7669     return bIsEmpty;
7670 }
7671
7672 void
7673 AFSRemoveNameEntry( IN AFSObjectInfoCB *ParentObjectInfo,
7674                     IN AFSDirectoryCB *DirEntry)
7675 {
7676
7677     NTSTATUS ntStatus = STATUS_SUCCESS;
7678
7679     __Enter
7680     {
7681
7682         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7683         {
7684
7685             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7686                           AFS_TRACE_LEVEL_VERBOSE,
7687                           "AFSRemoveNameEntry DE %p for %wZ has NOT_IN flag set\n",
7688                           DirEntry,
7689                           &DirEntry->NameInformation.FileName);
7690
7691             try_return( ntStatus);
7692         }
7693
7694         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
7695
7696         //
7697         // Remove the entry from the parent tree
7698         //
7699
7700         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7701                       AFS_TRACE_LEVEL_VERBOSE,
7702                       "AFSRemoveNameEntry DE %p for %wZ removing from case sensitive tree\n",
7703                       DirEntry,
7704                       &DirEntry->NameInformation.FileName);
7705
7706         AFSRemoveCaseSensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7707                                         DirEntry);
7708
7709         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7710                       AFS_TRACE_LEVEL_VERBOSE,
7711                       "AFSRemoveNameEntry DE %p for %wZ removing from case insensitive tree\n",
7712                       DirEntry,
7713                       &DirEntry->NameInformation.FileName);
7714
7715         AFSRemoveCaseInsensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
7716                                           DirEntry);
7717
7718         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
7719         {
7720
7721             //
7722             // From the short name tree
7723             //
7724
7725             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7726                           AFS_TRACE_LEVEL_VERBOSE,
7727                           "AFSRemoveNameEntry DE %p for %wZ removing from shortname tree\n",
7728                           DirEntry,
7729                           &DirEntry->NameInformation.FileName);
7730
7731             AFSRemoveShortNameDirEntry( &ParentObjectInfo->Specific.Directory.ShortNameTree,
7732                                         DirEntry);
7733
7734             ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
7735         }
7736
7737         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7738                       AFS_TRACE_LEVEL_VERBOSE,
7739                       "AFSRemoveNameEntry DE %p for %wZ setting NOT_IN flag\n",
7740                       DirEntry,
7741                       &DirEntry->NameInformation.FileName);
7742
7743         SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
7744
7745         ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
7746
7747 try_exit:
7748
7749         NOTHING;
7750     }
7751
7752     return;
7753 }
7754
7755 LARGE_INTEGER
7756 AFSGetAuthenticationId()
7757 {
7758
7759     LARGE_INTEGER liAuthId = {0,0};
7760     NTSTATUS ntStatus = STATUS_SUCCESS;
7761     PACCESS_TOKEN hToken = NULL;
7762     PTOKEN_STATISTICS pTokenInfo = NULL;
7763     BOOLEAN bCopyOnOpen = FALSE;
7764     BOOLEAN bEffectiveOnly = FALSE;
7765     BOOLEAN bPrimaryToken = FALSE;
7766     SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
7767
7768     __Enter
7769     {
7770
7771         hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
7772                                                 &bCopyOnOpen,
7773                                                 &bEffectiveOnly,
7774                                                 &stImpersonationLevel);
7775
7776         if( hToken == NULL)
7777         {
7778
7779             hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
7780
7781             if( hToken == NULL)
7782             {
7783
7784                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7785                               AFS_TRACE_LEVEL_ERROR,
7786                               "AFSGetAuthenticationId Failed to retrieve impersonation or primary token\n");
7787
7788                 try_return( ntStatus);
7789             }
7790
7791             bPrimaryToken = TRUE;
7792         }
7793
7794         ntStatus = SeQueryInformationToken( hToken,
7795                                             TokenStatistics,
7796                                             (PVOID *)&pTokenInfo);
7797
7798         if( !NT_SUCCESS( ntStatus))
7799         {
7800
7801             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7802                           AFS_TRACE_LEVEL_ERROR,
7803                           "AFSGetAuthenticationId Failed to retrieve information Status %08lX\n", ntStatus);
7804
7805             try_return( ntStatus);
7806         }
7807
7808         liAuthId.HighPart = pTokenInfo->AuthenticationId.HighPart;
7809         liAuthId.LowPart = pTokenInfo->AuthenticationId.LowPart;
7810
7811         AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7812                       AFS_TRACE_LEVEL_VERBOSE,
7813                       "AFSGetAuthenticationId Successfully retrieved authentication ID %I64X\n",
7814                       liAuthId.QuadPart);
7815
7816 try_exit:
7817
7818         if( hToken != NULL)
7819         {
7820
7821             if( !bPrimaryToken)
7822             {
7823
7824                 PsDereferenceImpersonationToken( hToken);
7825             }
7826             else
7827             {
7828
7829                 PsDereferencePrimaryToken( hToken);
7830             }
7831         }
7832
7833         if( pTokenInfo != NULL)
7834         {
7835
7836             ExFreePool( pTokenInfo);    // Allocated by SeQueryInformationToken
7837         }
7838     }
7839
7840     return liAuthId;
7841 }
7842
7843 void
7844 AFSUnwindFileInfo( IN AFSFcb *Fcb,
7845                    IN AFSCcb *Ccb)
7846 {
7847
7848     UNREFERENCED_PARAMETER(Fcb);
7849     if( Ccb->FileUnwindInfo.FileAttributes != (ULONG)-1)
7850     {
7851         Ccb->DirectoryCB->ObjectInformation->FileAttributes = Ccb->FileUnwindInfo.FileAttributes;
7852     }
7853
7854     if( Ccb->FileUnwindInfo.CreationTime.QuadPart != (ULONGLONG)-1)
7855     {
7856         Ccb->DirectoryCB->ObjectInformation->CreationTime.QuadPart = Ccb->FileUnwindInfo.CreationTime.QuadPart;
7857     }
7858
7859     if( Ccb->FileUnwindInfo.LastAccessTime.QuadPart != (ULONGLONG)-1)
7860     {
7861         Ccb->DirectoryCB->ObjectInformation->LastAccessTime.QuadPart = Ccb->FileUnwindInfo.LastAccessTime.QuadPart;
7862     }
7863
7864     if( Ccb->FileUnwindInfo.LastWriteTime.QuadPart != (ULONGLONG)-1)
7865     {
7866         Ccb->DirectoryCB->ObjectInformation->LastWriteTime.QuadPart = Ccb->FileUnwindInfo.LastWriteTime.QuadPart;
7867     }
7868
7869     if( Ccb->FileUnwindInfo.ChangeTime.QuadPart != (ULONGLONG)-1)
7870     {
7871         Ccb->DirectoryCB->ObjectInformation->ChangeTime.QuadPart = Ccb->FileUnwindInfo.ChangeTime.QuadPart;
7872     }
7873
7874     return;
7875 }
7876
7877 BOOLEAN
7878 AFSValidateDirList( IN AFSObjectInfoCB *ObjectInfo)
7879 {
7880
7881     BOOLEAN bIsValid = TRUE;
7882     ULONG ulCount = 0;
7883     AFSDirectoryCB *pCurrentDirEntry = NULL, *pDirEntry = NULL;
7884
7885     pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
7886
7887     while( pCurrentDirEntry != NULL)
7888     {
7889
7890         if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
7891         {
7892             ulCount++;
7893
7894             if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7895             {
7896
7897                 pDirEntry = NULL;
7898
7899                 AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7900                                                 (ULONG)pCurrentDirEntry->CaseSensitiveTreeEntry.HashIndex,
7901                                                 &pDirEntry);
7902
7903                 if( pDirEntry == NULL)
7904                 {
7905                     DbgBreakPoint();
7906                 }
7907             }
7908         }
7909
7910         pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
7911     }
7912
7913     if( ulCount != (ULONG) ObjectInfo->Specific.Directory.DirectoryNodeCount)
7914     {
7915
7916         AFSPrint("AFSValidateDirList Count off Calc: %d Stored: %d\n",
7917                   ulCount,
7918                   ObjectInfo->Specific.Directory.DirectoryNodeCount);
7919
7920         ObjectInfo->Specific.Directory.DirectoryNodeCount = ulCount;
7921
7922         bIsValid = FALSE;
7923     }
7924
7925     return bIsValid;
7926 }
7927
7928 PFILE_OBJECT
7929 AFSReferenceCacheFileObject()
7930 {
7931
7932     AFSDeviceExt       *pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
7933     FILE_OBJECT        *pCacheFileObject = NULL;
7934
7935     AFSAcquireShared( &pRdrDevExt->Specific.RDR.CacheFileLock,
7936                       TRUE);
7937
7938     pCacheFileObject = pRdrDevExt->Specific.RDR.CacheFileObject;
7939
7940     if( pCacheFileObject != NULL)
7941     {
7942         ObReferenceObject( pCacheFileObject);
7943     }
7944
7945     AFSReleaseResource( &pRdrDevExt->Specific.RDR.CacheFileLock);
7946
7947     return pCacheFileObject;
7948 }
7949
7950 void
7951 AFSReleaseCacheFileObject( IN PFILE_OBJECT CacheFileObject)
7952 {
7953
7954     ASSERT( CacheFileObject != NULL);
7955
7956     ObDereferenceObject( CacheFileObject);
7957
7958     return;
7959 }
7960
7961 NTSTATUS
7962 AFSInitializeLibrary( IN AFSLibraryInitCB *LibraryInit)
7963 {
7964
7965     NTSTATUS ntStatus = STATUS_SUCCESS;
7966     AFSDeviceExt *pControlDevExt = NULL;
7967     ULONG ulTimeIncrement = 0;
7968     LONG lCount;
7969
7970     __Enter
7971     {
7972
7973         AFSControlDeviceObject = LibraryInit->AFSControlDeviceObject;
7974
7975         AFSRDRDeviceObject = LibraryInit->AFSRDRDeviceObject;
7976
7977         AFSServerName = LibraryInit->AFSServerName;
7978
7979         AFSMountRootName = LibraryInit->AFSMountRootName;
7980
7981         AFSDebugFlags = LibraryInit->AFSDebugFlags;
7982
7983         //
7984         // Callbacks in the framework
7985         //
7986
7987         AFSProcessRequest = LibraryInit->AFSProcessRequest;
7988
7989         AFSDbgLogMsg = LibraryInit->AFSDbgLogMsg;
7990
7991         AFSAddConnectionEx = LibraryInit->AFSAddConnectionEx;
7992
7993         AFSExAllocatePoolWithTag = LibraryInit->AFSExAllocatePoolWithTag;
7994
7995         AFSExFreePoolWithTag = LibraryInit->AFSExFreePoolWithTag;
7996
7997         AFSDumpTraceFilesFnc = LibraryInit->AFSDumpTraceFiles;
7998
7999         AFSRetrieveAuthGroupFnc = LibraryInit->AFSRetrieveAuthGroup;
8000
8001         AFSLibCacheManagerCallbacks = LibraryInit->AFSCacheManagerCallbacks;
8002
8003         if( LibraryInit->AFSCacheBaseAddress != NULL)
8004         {
8005
8006             SetFlag( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE);
8007
8008             AFSLibCacheBaseAddress = LibraryInit->AFSCacheBaseAddress;
8009
8010             AFSLibCacheLength = LibraryInit->AFSCacheLength;
8011         }
8012
8013         //
8014         // Initialize some flush parameters
8015         //
8016
8017         pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
8018
8019         ulTimeIncrement = KeQueryTimeIncrement();
8020
8021         pControlDevExt->Specific.Control.ObjectLifeTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_OBJECT_LIFETIME / (ULONGLONG)ulTimeIncrement);
8022         pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart = AFS_SERVER_PURGE_DELAY;
8023         pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart /= ulTimeIncrement;
8024         pControlDevExt->Specific.Control.FcbFlushTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_SERVER_FLUSH_DELAY / (ULONGLONG)ulTimeIncrement);
8025         pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_EXTENT_REQUEST_TIME/(ULONGLONG)ulTimeIncrement);
8026
8027         //
8028         // Initialize the global root entry
8029         //
8030
8031         ntStatus = AFSInitVolume( NULL,
8032                                   &LibraryInit->GlobalRootFid,
8033                                   &AFSGlobalRoot);
8034
8035         if( !NT_SUCCESS( ntStatus))
8036         {
8037
8038             AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
8039                           AFS_TRACE_LEVEL_ERROR,
8040                           "AFSInitializeLibrary AFSInitVolume failure %08lX\n",
8041                           ntStatus);
8042
8043             try_return( ntStatus);
8044         }
8045
8046         ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
8047                                    AFSGlobalRoot);
8048
8049         if( !NT_SUCCESS( ntStatus))
8050         {
8051
8052             AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
8053                           AFS_TRACE_LEVEL_ERROR,
8054                           "AFSInitializeLibrary AFSInitRootFcb failure %08lX\n",
8055                           ntStatus);
8056
8057             lCount = InterlockedDecrement( &AFSGlobalRoot->VolumeReferenceCount);
8058
8059             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8060                           AFS_TRACE_LEVEL_VERBOSE,
8061                           "AFSInitializeLibrary Increment count on volume %p Cnt %d\n",
8062                           AFSGlobalRoot,
8063                           lCount);
8064
8065             AFSReleaseResource( AFSGlobalRoot->VolumeLock);
8066
8067             try_return( ntStatus);
8068         }
8069
8070         //
8071         // Update the node type code to AFS_ROOT_ALL
8072         //
8073
8074         AFSGlobalRoot->ObjectInformation.Fcb->Header.NodeTypeCode = AFS_ROOT_ALL;
8075
8076         SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_ACTIVE_GLOBAL_ROOT);
8077
8078         //
8079         // Invalidate all known volumes since contact with the service and therefore
8080         // the file server was lost.
8081         //
8082
8083         AFSInvalidateAllVolumes();
8084
8085         //
8086         // Drop the locks acquired above
8087         //
8088
8089         AFSInitVolumeWorker( AFSGlobalRoot);
8090
8091         lCount = InterlockedDecrement( &AFSGlobalRoot->VolumeReferenceCount);
8092
8093         AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8094                       AFS_TRACE_LEVEL_VERBOSE,
8095                       "AFSInitializeLibrary Decrement count on volume %p Cnt %d\n",
8096                       AFSGlobalRoot,
8097                       lCount);
8098
8099         AFSReleaseResource( AFSGlobalRoot->VolumeLock);
8100
8101         AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Fcb->Header.Resource);
8102
8103 try_exit:
8104
8105         NOTHING;
8106     }
8107
8108     return ntStatus;
8109 }
8110
8111 NTSTATUS
8112 AFSCloseLibrary()
8113 {
8114
8115     NTSTATUS ntStatus = STATUS_SUCCESS;
8116     AFSDirectoryCB *pDirNode = NULL, *pLastDirNode = NULL;
8117     LONG lCount;
8118
8119     __Enter
8120     {
8121
8122         if( AFSGlobalDotDirEntry != NULL)
8123         {
8124
8125             lCount = AFSObjectInfoDecrement( AFSGlobalDotDirEntry->ObjectInformation,
8126                                              AFS_OBJECT_REFERENCE_GLOBAL);
8127
8128             AFSDeleteObjectInfo( AFSGlobalDotDirEntry->ObjectInformation);
8129
8130             ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
8131
8132             ExFreePool( AFSGlobalDotDirEntry->NonPaged);
8133
8134             ExFreePool( AFSGlobalDotDirEntry);
8135
8136             AFSGlobalDotDirEntry = NULL;
8137         }
8138
8139         if( AFSGlobalDotDotDirEntry != NULL)
8140         {
8141
8142             lCount = AFSObjectInfoDecrement( AFSGlobalDotDotDirEntry->ObjectInformation,
8143                                              AFS_OBJECT_REFERENCE_GLOBAL);
8144
8145             AFSDeleteObjectInfo( AFSGlobalDotDotDirEntry->ObjectInformation);
8146
8147             ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
8148
8149             ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
8150
8151             ExFreePool( AFSGlobalDotDotDirEntry);
8152
8153             AFSGlobalDotDotDirEntry = NULL;
8154         }
8155
8156         if( AFSSpecialShareNames != NULL)
8157         {
8158
8159             pDirNode = AFSSpecialShareNames;
8160
8161             while( pDirNode != NULL)
8162             {
8163
8164                 pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
8165
8166                 lCount = AFSObjectInfoDecrement( pDirNode->ObjectInformation,
8167                                                  AFS_OBJECT_REFERENCE_GLOBAL);
8168
8169                 AFSDeleteObjectInfo( pDirNode->ObjectInformation);
8170
8171                 ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
8172
8173                 ExFreePool( pDirNode->NonPaged);
8174
8175                 ExFreePool( pDirNode);
8176
8177                 pDirNode = pLastDirNode;
8178             }
8179
8180             AFSSpecialShareNames = NULL;
8181         }
8182     }
8183
8184     return ntStatus;
8185 }
8186
8187 NTSTATUS
8188 AFSDefaultLogMsg( IN ULONG Subsystem,
8189                   IN ULONG Level,
8190                   IN PCCH Format,
8191                   ...)
8192 {
8193
8194     UNREFERENCED_PARAMETER(Subsystem);
8195     UNREFERENCED_PARAMETER(Level);
8196     NTSTATUS ntStatus = STATUS_SUCCESS;
8197     va_list va_args;
8198     char chDebugBuffer[ 256];
8199
8200     __Enter
8201     {
8202
8203         va_start( va_args, Format);
8204
8205         ntStatus = RtlStringCbVPrintfA( chDebugBuffer,
8206                                         256,
8207                                         Format,
8208                                         va_args);
8209
8210         if( NT_SUCCESS( ntStatus))
8211         {
8212             DbgPrint( chDebugBuffer);
8213         }
8214
8215         va_end( va_args);
8216     }
8217
8218     return ntStatus;
8219 }
8220
8221 NTSTATUS
8222 AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
8223                     IN ULONG InputBufferLength,
8224                     IN AFSStatusInfoCB *StatusInfo,
8225                     OUT ULONG *ReturnLength)
8226 {
8227
8228     NTSTATUS ntStatus = STATUS_SUCCESS;
8229     AFSVolumeCB *pVolumeCB = NULL;
8230     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
8231     AFSObjectInfoCB *pObjectInfo = NULL;
8232     ULONGLONG   ullIndex = 0;
8233     UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName, uniParsedName;
8234     AFSNameArrayHdr *pNameArray = NULL;
8235     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
8236     LONG lCount;
8237
8238     __Enter
8239     {
8240
8241         //
8242         // If we are given a FID then look up the entry by that, otherwise
8243         // do it by name
8244         //
8245
8246         if( GetStatusInfo->FileID.Cell != 0 &&
8247             GetStatusInfo->FileID.Volume != 0 &&
8248             GetStatusInfo->FileID.Vnode != 0 &&
8249             GetStatusInfo->FileID.Unique != 0)
8250         {
8251
8252             AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
8253
8254             //
8255             // Locate the volume node
8256             //
8257
8258             ullIndex = AFSCreateHighIndex( &GetStatusInfo->FileID);
8259
8260             ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
8261                                            ullIndex,
8262                                            (AFSBTreeEntry **)&pVolumeCB);
8263
8264             if( pVolumeCB != NULL)
8265             {
8266
8267                 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
8268
8269                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8270                               AFS_TRACE_LEVEL_VERBOSE,
8271                               "AFSGetObjectStatus Increment count on volume %p Cnt %d\n",
8272                               pVolumeCB,
8273                               lCount);
8274             }
8275
8276             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
8277
8278             if( !NT_SUCCESS( ntStatus) ||
8279                 pVolumeCB == NULL)
8280             {
8281                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8282             }
8283
8284             if( AFSIsVolumeFID( &GetStatusInfo->FileID))
8285             {
8286
8287                 pObjectInfo = &pVolumeCB->ObjectInformation;
8288
8289                 lCount = AFSObjectInfoIncrement( pObjectInfo,
8290                                                  AFS_OBJECT_REFERENCE_STATUS);
8291
8292                 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8293                               AFS_TRACE_LEVEL_VERBOSE,
8294                               "AFSGetObjectStatus Increment1 count on object %p Cnt %d\n",
8295                               pObjectInfo,
8296                               lCount);
8297
8298                 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
8299
8300                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8301                               AFS_TRACE_LEVEL_VERBOSE,
8302                               "AFSGetObjectStatus Decrement count on volume %p Cnt %d\n",
8303                               pVolumeCB,
8304                               lCount);
8305             }
8306             else
8307             {
8308
8309                 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
8310                                   TRUE);
8311
8312                 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
8313
8314                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8315                               AFS_TRACE_LEVEL_VERBOSE,
8316                               "AFSGetObjectStatus Decrement2 count on volume %p Cnt %d\n",
8317                               pVolumeCB,
8318                               lCount);
8319
8320                 ullIndex = AFSCreateLowIndex( &GetStatusInfo->FileID);
8321
8322                 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
8323                                                ullIndex,
8324                                                (AFSBTreeEntry **)&pObjectInfo);
8325
8326                 if( pObjectInfo != NULL)
8327                 {
8328
8329                     //
8330                     // Reference the node so it won't be torn down
8331                     //
8332
8333                     lCount = AFSObjectInfoIncrement( pObjectInfo,
8334                                                      AFS_OBJECT_REFERENCE_STATUS);
8335
8336                     AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8337                                   AFS_TRACE_LEVEL_VERBOSE,
8338                                   "AFSGetObjectStatus Increment2 count on object %p Cnt %d\n",
8339                                   pObjectInfo,
8340                                   lCount);
8341                 }
8342
8343                 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
8344
8345                 if( !NT_SUCCESS( ntStatus) ||
8346                     pObjectInfo == NULL)
8347                 {
8348                     try_return( ntStatus = STATUS_INVALID_PARAMETER);
8349                 }
8350             }
8351         }
8352         else
8353         {
8354
8355             if( GetStatusInfo->FileNameLength == 0 ||
8356                 InputBufferLength < (ULONG)(FIELD_OFFSET( AFSGetStatusInfoCB, FileName) + GetStatusInfo->FileNameLength))
8357             {
8358                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8359             }
8360
8361             uniFullPathName.Length = GetStatusInfo->FileNameLength;
8362             uniFullPathName.MaximumLength = uniFullPathName.Length;
8363
8364             uniFullPathName.Buffer = (WCHAR *)GetStatusInfo->FileName;
8365
8366             //
8367             // This name should begin with the \afs server so parse it off and check it
8368             //
8369
8370             FsRtlDissectName( uniFullPathName,
8371                               &uniComponentName,
8372                               &uniRemainingPath);
8373
8374             if( RtlCompareUnicodeString( &uniComponentName,
8375                                          &AFSServerName,
8376                                          TRUE) != 0)
8377             {
8378                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8379                               AFS_TRACE_LEVEL_ERROR,
8380                               "AFSGetObjectStatus Name %wZ contains invalid server name\n",
8381                               &uniFullPathName);
8382
8383                 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
8384             }
8385
8386             uniFullPathName = uniRemainingPath;
8387
8388             uniParsedName = uniFullPathName;
8389
8390             //
8391             // Our name array
8392             //
8393
8394             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
8395                                            0);
8396
8397             if( pNameArray == NULL)
8398             {
8399                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8400             }
8401
8402             pVolumeCB = AFSGlobalRoot;
8403
8404             pParentDirEntry = AFSGlobalRoot->DirectoryCB;
8405
8406             //
8407             // Increment the ref count on the volume and dir entry for correct processing below
8408             //
8409
8410             lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
8411
8412             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8413                           AFS_TRACE_LEVEL_VERBOSE,
8414                           "AFSGetObjectStatus Increment2 count on volume %p Cnt %d\n",
8415                           pVolumeCB,
8416                           lCount);
8417
8418             lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
8419
8420             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8421                           AFS_TRACE_LEVEL_VERBOSE,
8422                           "AFSGetObjectStatus Increment count on %wZ DE %p Ccb %p Cnt %d\n",
8423                           &pParentDirEntry->NameInformation.FileName,
8424                           pParentDirEntry,
8425                           NULL,
8426                           lCount);
8427
8428             ntStatus = AFSLocateNameEntry( NULL,
8429                                            NULL,
8430                                            &uniFullPathName,
8431                                            &uniParsedName,
8432                                            pNameArray,
8433                                            AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL |
8434                                                AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL,
8435                                            &pVolumeCB,
8436                                            &pParentDirEntry,
8437                                            &pDirectoryEntry,
8438                                            NULL);
8439
8440             if( !NT_SUCCESS( ntStatus) ||
8441                 ntStatus == STATUS_REPARSE)
8442             {
8443
8444                 //
8445                 // The volume lock was released on failure or reparse above
8446                 // Except for STATUS_OBJECT_NAME_NOT_FOUND
8447                 //
8448
8449                 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
8450                 {
8451
8452                     if( pVolumeCB != NULL)
8453                     {
8454
8455                         lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
8456
8457                         AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8458                                       AFS_TRACE_LEVEL_VERBOSE,
8459                                       "AFSGetObjectStatus Decrement3 count on volume %p Cnt %d\n",
8460                                       pVolumeCB,
8461                                       lCount);
8462                     }
8463
8464                     if( pDirectoryEntry != NULL)
8465                     {
8466
8467                         lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
8468
8469                         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8470                                       AFS_TRACE_LEVEL_VERBOSE,
8471                                       "AFSGetObjectStatus Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
8472                                       &pDirectoryEntry->NameInformation.FileName,
8473                                       pDirectoryEntry,
8474                                       NULL,
8475                                       lCount);
8476
8477                         ASSERT( lCount >= 0);
8478                     }
8479                     else
8480                     {
8481
8482                         lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
8483
8484                         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8485                                       AFS_TRACE_LEVEL_VERBOSE,
8486                                       "AFSGetObjectStatus Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
8487                                       &pParentDirEntry->NameInformation.FileName,
8488                                       pParentDirEntry,
8489                                       NULL,
8490                                       lCount);
8491
8492                         ASSERT( lCount >= 0);
8493                     }
8494                 }
8495
8496                 pVolumeCB = NULL;
8497
8498                 try_return( ntStatus);
8499             }
8500
8501             //
8502             // Remove the reference obtained from AFSLocateNameEntry
8503             //
8504
8505             lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
8506
8507             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8508                           AFS_TRACE_LEVEL_VERBOSE,
8509                           "AFSGetObjectStatus Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
8510                           &pDirectoryEntry->NameInformation.FileName,
8511                           pDirectoryEntry,
8512                           NULL,
8513                           lCount);
8514
8515             ASSERT( lCount >= 0);
8516
8517             pObjectInfo = pDirectoryEntry->ObjectInformation;
8518
8519             lCount = AFSObjectInfoIncrement( pObjectInfo,
8520                                              AFS_OBJECT_REFERENCE_STATUS);
8521
8522             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8523                           AFS_TRACE_LEVEL_VERBOSE,
8524                           "AFSGetObjectStatus Increment3 count on object %p Cnt %d\n",
8525                           pObjectInfo,
8526                           lCount);
8527
8528             if( pVolumeCB != NULL)
8529             {
8530
8531                 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
8532
8533                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8534                               AFS_TRACE_LEVEL_VERBOSE,
8535                               "AFSGetObjectStatus Decrement4 count on volume %p Cnt %d\n",
8536                               pVolumeCB,
8537                               lCount);
8538             }
8539         }
8540
8541         //
8542         // At this point we have an object info block, return the information
8543         //
8544
8545         StatusInfo->FileId = pObjectInfo->FileId;
8546
8547         StatusInfo->TargetFileId = pObjectInfo->TargetFileId;
8548
8549         StatusInfo->Expiration = pObjectInfo->Expiration;
8550
8551         StatusInfo->DataVersion = pObjectInfo->DataVersion;
8552
8553         StatusInfo->FileType = pObjectInfo->FileType;
8554
8555         StatusInfo->ObjectFlags = pObjectInfo->Flags;
8556
8557         StatusInfo->CreationTime = pObjectInfo->CreationTime;
8558
8559         StatusInfo->LastAccessTime = pObjectInfo->LastAccessTime;
8560
8561         StatusInfo->LastWriteTime = pObjectInfo->LastWriteTime;
8562
8563         StatusInfo->ChangeTime = pObjectInfo->ChangeTime;
8564
8565         StatusInfo->FileAttributes = pObjectInfo->FileAttributes;
8566
8567         StatusInfo->EndOfFile = pObjectInfo->EndOfFile;
8568
8569         StatusInfo->AllocationSize = pObjectInfo->AllocationSize;
8570
8571         StatusInfo->EaSize = pObjectInfo->EaSize;
8572
8573         StatusInfo->Links = pObjectInfo->Links;
8574
8575         //
8576         // Return the information length
8577         //
8578
8579         *ReturnLength = sizeof( AFSStatusInfoCB);
8580
8581 try_exit:
8582
8583         if( pObjectInfo != NULL)
8584         {
8585
8586             lCount = AFSObjectInfoDecrement( pObjectInfo,
8587                                              AFS_OBJECT_REFERENCE_STATUS);
8588
8589             AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8590                           AFS_TRACE_LEVEL_VERBOSE,
8591                           "AFSGetObjectStatus Decrement count on object %p Cnt %d\n",
8592                           pObjectInfo,
8593                           lCount);
8594         }
8595
8596         if( pNameArray != NULL)
8597         {
8598
8599             AFSFreeNameArray( pNameArray);
8600         }
8601     }
8602
8603     return ntStatus;
8604 }
8605
8606 NTSTATUS
8607 AFSCheckSymlinkAccess( IN AFSDirectoryCB *ParentDirectoryCB,
8608                        IN UNICODE_STRING *ComponentName)
8609 {
8610
8611     NTSTATUS ntStatus = STATUS_SUCCESS;
8612     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
8613     AFSDirectoryCB *pDirEntry = NULL;
8614     ULONG ulCRC = 0;
8615     LONG lCount;
8616
8617     __Enter
8618     {
8619
8620         //
8621         // Search for the entry in the parent
8622         //
8623
8624         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8625                       AFS_TRACE_LEVEL_VERBOSE_2,
8626                       "AFSCheckSymlinkAccess Searching for entry %wZ case sensitive\n",
8627                       ComponentName);
8628
8629         ulCRC = AFSGenerateCRC( ComponentName,
8630                                 FALSE);
8631
8632         AFSAcquireShared( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
8633                           TRUE);
8634
8635         AFSLocateCaseSensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
8636                                         ulCRC,
8637                                         &pDirEntry);
8638
8639         if( pDirEntry == NULL)
8640         {
8641
8642             //
8643             // Missed so perform a case insensitive lookup
8644             //
8645
8646             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8647                           AFS_TRACE_LEVEL_VERBOSE_2,
8648                           "AFSCheckSymlinkAccess Searching for entry %wZ case insensitive\n",
8649                           ComponentName);
8650
8651             ulCRC = AFSGenerateCRC( ComponentName,
8652                                     TRUE);
8653
8654             AFSLocateCaseInsensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
8655                                               ulCRC,
8656                                               &pDirEntry);
8657
8658             if( pDirEntry == NULL)
8659             {
8660
8661                 //
8662                 // OK, if this component is a valid short name then try
8663                 // a lookup in the short name tree
8664                 //
8665
8666                 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
8667                     RtlIsNameLegalDOS8Dot3( ComponentName,
8668                                             NULL,
8669                                             NULL))
8670                 {
8671
8672                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8673                                   AFS_TRACE_LEVEL_VERBOSE_2,
8674                                   "AFSCheckSymlinkAccess Searching for entry %wZ short name\n",
8675                                   ComponentName);
8676
8677                     AFSLocateShortNameDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.ShortNameTree,
8678                                                 ulCRC,
8679                                                 &pDirEntry);
8680                 }
8681             }
8682         }
8683
8684         if( pDirEntry != NULL)
8685         {
8686             lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
8687
8688             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8689                           AFS_TRACE_LEVEL_VERBOSE,
8690                           "AFSCheckSymlinkAccess Increment count on %wZ DE %p Ccb %p Cnt %d\n",
8691                           &pDirEntry->NameInformation.FileName,
8692                           pDirEntry,
8693                           NULL,
8694                           lCount);
8695
8696             ASSERT( lCount >= 0);
8697         }
8698
8699         AFSReleaseResource( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
8700
8701         if( pDirEntry == NULL)
8702         {
8703
8704             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8705                           AFS_TRACE_LEVEL_VERBOSE_2,
8706                           "AFSCheckSymlinkAccess Failed to locate entry %wZ ntStatus %08X\n",
8707                           ComponentName,
8708                           STATUS_OBJECT_NAME_NOT_FOUND);
8709
8710             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
8711         }
8712
8713         //
8714         // We have the symlink object but previously failed to process it so return access
8715         // denied.
8716         //
8717
8718         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8719                       AFS_TRACE_LEVEL_VERBOSE_2,
8720                       "AFSCheckSymlinkAccess Failing symlink access to entry %wZ REPARSE_POINT_NOT_RESOLVED\n",
8721                       ComponentName);
8722
8723         ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
8724
8725         lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
8726
8727         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8728                       AFS_TRACE_LEVEL_VERBOSE,
8729                       "AFSCheckSymlinkAccess Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
8730                       &pDirEntry->NameInformation.FileName,
8731                       pDirEntry,
8732                       NULL,
8733                       lCount);
8734
8735         ASSERT( lCount >= 0);
8736
8737 try_exit:
8738
8739         NOTHING;
8740     }
8741
8742     return ntStatus;
8743 }
8744
8745 NTSTATUS
8746 AFSRetrieveFinalComponent( IN UNICODE_STRING *FullPathName,
8747                            OUT UNICODE_STRING *ComponentName)
8748 {
8749
8750     NTSTATUS ntStatus = STATUS_SUCCESS;
8751     UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName;
8752
8753     uniFullPathName = *FullPathName;
8754
8755     while( TRUE)
8756     {
8757
8758         FsRtlDissectName( uniFullPathName,
8759                           &uniComponentName,
8760                           &uniRemainingPath);
8761
8762         if( uniRemainingPath.Length == 0)
8763         {
8764             break;
8765         }
8766
8767         uniFullPathName = uniRemainingPath;
8768     }
8769
8770     if( uniComponentName.Length > 0)
8771     {
8772         *ComponentName = uniComponentName;
8773     }
8774
8775     return ntStatus;
8776 }
8777
8778 void
8779 AFSDumpTraceFiles_Default()
8780 {
8781     return;
8782 }
8783
8784 BOOLEAN
8785 AFSValidNameFormat( IN UNICODE_STRING *FileName)
8786 {
8787
8788     BOOLEAN bIsValidName = TRUE;
8789     USHORT usIndex = 0;
8790
8791     __Enter
8792     {
8793
8794         while( usIndex < FileName->Length/sizeof( WCHAR))
8795         {
8796
8797             if( FileName->Buffer[ usIndex] == L':' ||
8798                 FileName->Buffer[ usIndex] == L'*' ||
8799                 FileName->Buffer[ usIndex] == L'?' ||
8800                 FileName->Buffer[ usIndex] == L'"' ||
8801                 FileName->Buffer[ usIndex] == L'<' ||
8802                 FileName->Buffer[ usIndex] == L'>')
8803             {
8804                 bIsValidName = FALSE;
8805                 break;
8806             }
8807
8808             usIndex++;
8809         }
8810     }
8811
8812     return bIsValidName;
8813 }
8814
8815 NTSTATUS
8816 AFSCreateDefaultSecurityDescriptor()
8817 {
8818
8819     NTSTATUS ntStatus = STATUS_SUCCESS;
8820     PACL pSACL = NULL;
8821     ULONG ulSACLSize = 0;
8822     SYSTEM_MANDATORY_LABEL_ACE* pACE = NULL;
8823     ULONG ulACESize = 0;
8824     SECURITY_DESCRIPTOR *pSecurityDescr = NULL;
8825     ULONG ulSDLength = 0;
8826     SECURITY_DESCRIPTOR *pRelativeSecurityDescr = NULL;
8827     PSID pWorldSID = NULL;
8828     ULONG *pulSubAuthority = NULL;
8829     ULONG ulWorldSIDLEngth = 0;
8830
8831     __Enter
8832     {
8833
8834         ulWorldSIDLEngth = RtlLengthRequiredSid( 1);
8835
8836         pWorldSID = (PSID)ExAllocatePoolWithTag( PagedPool,
8837                                                  ulWorldSIDLEngth,
8838                                                  AFS_GENERIC_MEMORY_29_TAG);
8839
8840         if( pWorldSID == NULL)
8841         {
8842             AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate World SID\n");
8843             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8844         }
8845
8846         RtlZeroMemory( pWorldSID,
8847                        ulWorldSIDLEngth);
8848
8849         RtlInitializeSid( pWorldSID,
8850                           &SeWorldSidAuthority,
8851                           1);
8852
8853         pulSubAuthority = RtlSubAuthoritySid(pWorldSID, 0);
8854         *pulSubAuthority = SECURITY_WORLD_RID;
8855
8856         if( AFSRtlSetSaclSecurityDescriptor == NULL)
8857         {
8858
8859             AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor == NULL\n");
8860         }
8861         else
8862         {
8863
8864             ulACESize = sizeof( SYSTEM_MANDATORY_LABEL_ACE) + 128;
8865
8866             pACE = (SYSTEM_MANDATORY_LABEL_ACE *)ExAllocatePoolWithTag( PagedPool,
8867                                                                         ulACESize,
8868                                                                         AFS_GENERIC_MEMORY_29_TAG);
8869
8870             if( pACE == NULL)
8871             {
8872
8873                 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8874
8875                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8876             }
8877
8878             RtlZeroMemory( pACE,
8879                            ulACESize);
8880
8881             pACE->Header.AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
8882             pACE->Header.AceType = SYSTEM_MANDATORY_LABEL_ACE_TYPE;
8883             pACE->Header.AceSize = FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + (USHORT)RtlLengthSid( SeExports->SeLowMandatorySid);
8884             pACE->Mask = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP;
8885
8886             RtlCopySid( RtlLengthSid( SeExports->SeLowMandatorySid),
8887                         &pACE->SidStart,
8888                         SeExports->SeLowMandatorySid);
8889
8890             ulSACLSize = sizeof(ACL) + RtlLengthSid( SeExports->SeLowMandatorySid) +
8891                 FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + ulACESize;
8892
8893             pSACL = (PACL)ExAllocatePoolWithTag( PagedPool,
8894                                                  ulSACLSize,
8895                                                  AFS_GENERIC_MEMORY_29_TAG);
8896
8897             if( pSACL == NULL)
8898             {
8899
8900                 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8901
8902                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8903             }
8904
8905             ntStatus = RtlCreateAcl( pSACL,
8906                                      ulSACLSize,
8907                                      ACL_REVISION);
8908
8909             if( !NT_SUCCESS( ntStatus))
8910             {
8911
8912                 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateAcl ntStatus %08lX\n",
8913                           ntStatus);
8914
8915                 try_return( ntStatus);
8916             }
8917
8918             ntStatus = RtlAddAce( pSACL,
8919                                   ACL_REVISION,
8920                                   0,
8921                                   pACE,
8922                                   pACE->Header.AceSize);
8923
8924             if( !NT_SUCCESS( ntStatus))
8925             {
8926
8927                 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAddAce ntStatus %08lX\n",
8928                           ntStatus);
8929
8930                 try_return( ntStatus);
8931             }
8932         }
8933
8934         pSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
8935                                                                        sizeof( SECURITY_DESCRIPTOR),
8936                                                                        AFS_GENERIC_MEMORY_27_TAG);
8937
8938         if( pSecurityDescr == NULL)
8939         {
8940
8941             AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8942
8943             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8944         }
8945
8946         ntStatus = RtlCreateSecurityDescriptor( pSecurityDescr,
8947                                                 SECURITY_DESCRIPTOR_REVISION);
8948
8949         if( !NT_SUCCESS( ntStatus))
8950         {
8951
8952             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateSecurityDescriptor ntStatus %08lX\n",
8953                       ntStatus);
8954
8955             try_return( ntStatus);
8956         }
8957
8958         if( AFSRtlSetSaclSecurityDescriptor != NULL)
8959         {
8960             ntStatus = AFSRtlSetSaclSecurityDescriptor( pSecurityDescr,
8961                                                         TRUE,
8962                                                         pSACL,
8963                                                         FALSE);
8964
8965             if( !NT_SUCCESS( ntStatus))
8966             {
8967
8968                 AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor ntStatus %08lX\n",
8969                           ntStatus);
8970
8971                 try_return( ntStatus);
8972             }
8973         }
8974
8975         //
8976         // Add in the group and owner to the SD
8977         //
8978
8979         if( AFSRtlSetGroupSecurityDescriptor != NULL)
8980         {
8981             ntStatus = AFSRtlSetGroupSecurityDescriptor( pSecurityDescr,
8982                                                          pWorldSID,
8983                                                          FALSE);
8984
8985             if( !NT_SUCCESS( ntStatus))
8986             {
8987
8988                 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetGroupSecurityDescriptor failed ntStatus %08lX\n",
8989                           ntStatus);
8990
8991                 try_return( ntStatus);
8992             }
8993         }
8994
8995         ntStatus = RtlSetOwnerSecurityDescriptor( pSecurityDescr,
8996                                                   pWorldSID,
8997                                                   FALSE);
8998
8999         if( !NT_SUCCESS( ntStatus))
9000         {
9001
9002             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetOwnerSecurityDescriptor failed ntStatus %08lX\n",
9003                       ntStatus);
9004
9005             try_return( ntStatus);
9006         }
9007
9008         if( !RtlValidSecurityDescriptor( pSecurityDescr))
9009         {
9010
9011             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlValidSecurityDescriptor NOT\n");
9012
9013             try_return( ntStatus = STATUS_INVALID_PARAMETER);
9014         }
9015
9016         pRelativeSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
9017                                                                                PAGE_SIZE,
9018                                                                                AFS_GENERIC_MEMORY_27_TAG);
9019
9020         if( pRelativeSecurityDescr == NULL)
9021         {
9022
9023             AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
9024
9025             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
9026         }
9027
9028         ulSDLength = PAGE_SIZE;
9029
9030         ntStatus = RtlAbsoluteToSelfRelativeSD( pSecurityDescr,
9031                                                 pRelativeSecurityDescr,
9032                                                 &ulSDLength);
9033
9034         if( !NT_SUCCESS( ntStatus))
9035         {
9036
9037             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAbsoluteToSelfRelativeSD ntStatus %08lX\n",
9038                       ntStatus);
9039
9040             try_return( ntStatus);
9041         }
9042
9043         AFSDefaultSD = pRelativeSecurityDescr;
9044
9045 try_exit:
9046
9047         if( !NT_SUCCESS( ntStatus))
9048         {
9049
9050             if( pRelativeSecurityDescr != NULL)
9051             {
9052                 ExFreePool( pRelativeSecurityDescr);
9053             }
9054         }
9055
9056         if( pSecurityDescr != NULL)
9057         {
9058             ExFreePool( pSecurityDescr);
9059         }
9060
9061         if( pSACL != NULL)
9062         {
9063             ExFreePool( pSACL);
9064         }
9065
9066         if( pACE != NULL)
9067         {
9068             ExFreePool( pACE);
9069         }
9070
9071         if( pWorldSID != NULL)
9072         {
9073             ExFreePool( pWorldSID);
9074         }
9075     }
9076
9077     return ntStatus;
9078 }
9079
9080 void
9081 AFSRetrieveParentPath( IN UNICODE_STRING *FullFileName,
9082                        OUT UNICODE_STRING *ParentPath)
9083 {
9084
9085     *ParentPath = *FullFileName;
9086
9087     //
9088     // If the final character is a \, jump over it
9089     //
9090
9091     if( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] == L'\\')
9092     {
9093         ParentPath->Length -= sizeof( WCHAR);
9094     }
9095
9096     while( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] != L'\\')
9097     {
9098         ParentPath->Length -= sizeof( WCHAR);
9099     }
9100
9101     //
9102     // And the separator
9103     //
9104
9105     ParentPath->Length -= sizeof( WCHAR);
9106
9107     return;
9108 }
9109
9110 NTSTATUS
9111 AFSRetrieveValidAuthGroup( IN AFSFcb *Fcb,
9112                            IN AFSObjectInfoCB *ObjectInfo,
9113                            IN BOOLEAN WriteAccess,
9114                            OUT GUID *AuthGroup)
9115 {
9116
9117     NTSTATUS ntStatus = STATUS_SUCCESS;
9118     GUID     stAuthGroup, stZeroAuthGroup;
9119     BOOLEAN  bFoundAuthGroup = FALSE;
9120     AFSCcb  *pCcb = NULL;
9121     AFSFcb *pFcb = Fcb;
9122
9123     __Enter
9124     {
9125
9126         RtlZeroMemory( &stAuthGroup,
9127                        sizeof( GUID));
9128
9129         RtlZeroMemory( &stZeroAuthGroup,
9130                        sizeof( GUID));
9131
9132         if( Fcb == NULL)
9133         {
9134
9135             if( ObjectInfo != NULL &&
9136                 ObjectInfo->Fcb != NULL)
9137             {
9138                 pFcb = ObjectInfo->Fcb;
9139             }
9140         }
9141
9142         if( pFcb != NULL)
9143         {
9144
9145             AFSAcquireShared( &Fcb->NPFcb->CcbListLock,
9146                               TRUE);
9147
9148             pCcb = Fcb->CcbListHead;
9149
9150             while( pCcb != NULL)
9151             {
9152
9153                 if( WriteAccess &&
9154                     pCcb->GrantedAccess & FILE_WRITE_DATA)
9155                 {
9156                     RtlCopyMemory( &stAuthGroup,
9157                                    &pCcb->AuthGroup,
9158                                    sizeof( GUID));
9159
9160                     bFoundAuthGroup = TRUE;
9161
9162                     break;
9163                 }
9164                 else if( pCcb->GrantedAccess & FILE_READ_DATA)
9165                 {
9166                     //
9167                     // At least get the read-only access
9168                     //
9169
9170                     RtlCopyMemory( &stAuthGroup,
9171                                    &pCcb->AuthGroup,
9172                                    sizeof( GUID));
9173
9174                     bFoundAuthGroup = TRUE;
9175                 }
9176
9177                 pCcb = (AFSCcb *)pCcb->ListEntry.fLink;
9178             }
9179
9180             AFSReleaseResource( &Fcb->NPFcb->CcbListLock);
9181         }
9182
9183         if( !bFoundAuthGroup)
9184         {
9185
9186             AFSRetrieveAuthGroupFnc( (ULONGLONG)PsGetCurrentProcessId(),
9187                                      (ULONGLONG)PsGetCurrentThreadId(),
9188                                       &stAuthGroup);
9189
9190             if( RtlCompareMemory( &stZeroAuthGroup,
9191                                   &stAuthGroup,
9192                                   sizeof( GUID)) == sizeof( GUID))
9193             {
9194
9195                 DbgPrint("AFSRetrieveValidAuthGroup Failed to locate PAG\n");
9196
9197                 try_return( ntStatus = STATUS_ACCESS_DENIED);
9198             }
9199         }
9200
9201         RtlCopyMemory( AuthGroup,
9202                        &stAuthGroup,
9203                        sizeof( GUID));
9204
9205 try_exit:
9206
9207         NOTHING;
9208     }
9209
9210     return ntStatus;
9211 }
9212
9213 NTSTATUS
9214 AFSPerformObjectInvalidate( IN AFSObjectInfoCB *ObjectInfo,
9215                             IN ULONG InvalidateReason)
9216 {
9217
9218     NTSTATUS            ntStatus = STATUS_SUCCESS;
9219     LIST_ENTRY         *le;
9220     AFSExtent          *pEntry;
9221     ULONG               ulProcessCount = 0;
9222     ULONG               ulCount = 0;
9223     LONG                lCount;
9224
9225     __Enter
9226     {
9227
9228         switch( InvalidateReason)
9229         {
9230
9231             case AFS_INVALIDATE_DELETED:
9232             {
9233
9234                 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
9235                     ObjectInfo->Fcb != NULL)
9236                 {
9237
9238                     AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9239                                     TRUE);
9240
9241                     ObjectInfo->Links = 0;
9242
9243                     ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
9244
9245                     KeSetEvent( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
9246                                 0,
9247                                 FALSE);
9248
9249                     //
9250                     // Clear out the extents
9251                     // And get rid of them (note this involves waiting
9252                     // for any writes or reads to the cache to complete)
9253                     //
9254
9255                     AFSTearDownFcbExtents( ObjectInfo->Fcb,
9256                                            NULL);
9257
9258                     AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
9259                 }
9260
9261                 break;
9262             }
9263
9264             case AFS_INVALIDATE_DATA_VERSION:
9265             {
9266
9267                 LARGE_INTEGER liCurrentOffset = {0,0};
9268                 LARGE_INTEGER liFlushLength = {0,0};
9269                 ULONG ulFlushLength = 0;
9270                 BOOLEAN bLocked = FALSE;
9271                 BOOLEAN bExtentsLocked = FALSE;
9272                 BOOLEAN bCleanExtents = FALSE;
9273
9274                 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
9275                     ObjectInfo->Fcb != NULL)
9276                 {
9277
9278                     AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Resource,
9279                                     TRUE);
9280
9281                     bLocked = TRUE;
9282
9283                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
9284                                   AFS_TRACE_LEVEL_VERBOSE,
9285                                   "AFSPerformObjectInvalidate Acquiring Fcb extents lock %p SHARED %08lX\n",
9286                                   &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9287                                   PsGetCurrentThread());
9288
9289                     AFSAcquireShared( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9290                                       TRUE);
9291
9292                     bExtentsLocked = TRUE;
9293
9294                     //
9295                     // There are several possibilities here:
9296                     //
9297                     // 0. If there are no extents or all of the extents are dirty, do nothing.
9298                     //
9299                     // 1. There could be nothing dirty and an open reference count of zero
9300                     //    in which case we can just tear down all of the extents without
9301                     //    holding any resources.
9302                     //
9303                     // 2. There could be nothing dirty and a non-zero open reference count
9304                     //    in which case we can issue a CcPurge against the entire file
9305                     //    while holding just the Fcb Resource.
9306                     //
9307                     // 3. There can be dirty extents in which case we need to identify
9308                     //    the non-dirty ranges and then perform a CcPurge on just the
9309                     //    non-dirty ranges while holding just the Fcb Resource.
9310                     //
9311
9312                     if ( ObjectInfo->Fcb->Specific.File.ExtentCount != ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount)
9313                     {
9314
9315                         if ( ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount == 0)
9316                         {
9317
9318                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9319
9320                             bExtentsLocked = FALSE;
9321
9322                             if ( ObjectInfo->Fcb->OpenReferenceCount == 0)
9323                             {
9324
9325                                 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9326
9327                                 bLocked = FALSE;
9328
9329                                 AFSTearDownFcbExtents( ObjectInfo->Fcb,
9330                                                        NULL);
9331                             }
9332                             else
9333                             {
9334
9335                                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
9336                                               AFS_TRACE_LEVEL_VERBOSE,
9337                                               "AFSPerformObjectInvalidation Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
9338                                               &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9339                                               PsGetCurrentThread());
9340
9341                                 AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9342                                                 TRUE);
9343
9344                                 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9345
9346                                 bLocked = FALSE;
9347
9348                                 __try
9349                                 {
9350
9351                                     if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
9352                                         !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9353                                                               NULL,
9354                                                               0,
9355                                                               FALSE))
9356                                     {
9357
9358                                         AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
9359                                                       AFS_TRACE_LEVEL_WARNING,
9360                                                       "AFSPerformObjectInvalidation CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9361                                                       ObjectInfo->FileId.Cell,
9362                                                       ObjectInfo->FileId.Volume,
9363                                                       ObjectInfo->FileId.Vnode,
9364                                                       ObjectInfo->FileId.Unique);
9365
9366                                         SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9367                                     }
9368                                     else
9369                                     {
9370
9371                                         bCleanExtents = TRUE;
9372                                     }
9373                                 }
9374                                 __except( EXCEPTION_EXECUTE_HANDLER)
9375                                 {
9376
9377                                     ntStatus = GetExceptionCode();
9378
9379                                     AFSDbgLogMsg( 0,
9380                                                   0,
9381                                                   "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
9382                                                   ObjectInfo->FileId.Cell,
9383                                                   ObjectInfo->FileId.Volume,
9384                                                   ObjectInfo->FileId.Vnode,
9385                                                   ObjectInfo->FileId.Unique,
9386                                                   ntStatus);
9387
9388                                     SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9389                                 }
9390
9391                                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
9392                                               AFS_TRACE_LEVEL_VERBOSE,
9393                                               "AFSPerformObjectInvalidation Releasing Fcb SectionObject lock %p EXCL %08lX\n",
9394                                               &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9395                                               PsGetCurrentThread());
9396
9397                                 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
9398                             }
9399                         }
9400                         else
9401                         {
9402
9403                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9404
9405                             bExtentsLocked = FALSE;
9406
9407                             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
9408                                           AFS_TRACE_LEVEL_VERBOSE,
9409                                           "AFSPerformObjectInvalidation Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
9410                                           &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9411                                           PsGetCurrentThread());
9412
9413                             AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9414                                             TRUE);
9415
9416                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9417
9418                             bLocked = FALSE;
9419
9420                             //
9421                             // Must build a list of non-dirty ranges from the beginning of the file
9422                             // to the end.  There can be at most (Fcb->Specific.File.ExtentsDirtyCount + 1)
9423                             // ranges.  In all but the most extreme random data write scenario there will
9424                             // be significantly fewer.
9425                             //
9426                             // For each range we need offset and size.
9427                             //
9428
9429                             AFSByteRange * ByteRangeList = NULL;
9430                             ULONG          ulByteRangeCount = 0;
9431                             ULONG          ulIndex;
9432                             BOOLEAN        bPurgeOnClose = FALSE;
9433
9434                             __try
9435                             {
9436
9437                                 ulByteRangeCount = AFSConstructCleanByteRangeList( ObjectInfo->Fcb,
9438                                                                                    &ByteRangeList);
9439
9440                                 if ( ByteRangeList != NULL ||
9441                                      ulByteRangeCount == 0)
9442                                 {
9443
9444                                     for ( ulIndex = 0; ulIndex < ulByteRangeCount; ulIndex++)
9445                                     {
9446
9447                                         ULONG ulSize;
9448
9449                                         do {
9450
9451                                             ulSize = ByteRangeList[ulIndex].Length.QuadPart > DWORD_MAX ? DWORD_MAX : ByteRangeList[ulIndex].Length.LowPart;
9452
9453                                             if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
9454                                                 !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9455                                                                       &ByteRangeList[ulIndex].FileOffset,
9456                                                                       ulSize,
9457                                                                       FALSE))
9458                                             {
9459
9460                                                 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
9461                                                               AFS_TRACE_LEVEL_WARNING,
9462                                                               "AFSPerformObjectInvalidation [1] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9463                                                               ObjectInfo->FileId.Cell,
9464                                                               ObjectInfo->FileId.Volume,
9465                                                               ObjectInfo->FileId.Vnode,
9466                                                               ObjectInfo->FileId.Unique);
9467
9468                                                 bPurgeOnClose = TRUE;
9469                                             }
9470                                             else
9471                                             {
9472
9473                                                 bCleanExtents = TRUE;
9474                                             }
9475
9476                                             ByteRangeList[ulIndex].Length.QuadPart -= ulSize;
9477
9478                                             ByteRangeList[ulIndex].FileOffset.QuadPart += ulSize;
9479
9480                                         } while ( ByteRangeList[ulIndex].Length.QuadPart > 0);
9481                                     }
9482                                 }
9483                                 else
9484                                 {
9485
9486                                     //
9487                                     // We couldn't allocate the memory to build the purge list
9488                                     // so just walk the extent list while holding the ExtentsList Resource.
9489                                     // This could deadlock but we do not have much choice.
9490                                     //
9491
9492                                     AFSAcquireExcl(  &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9493                                                     TRUE);
9494                                     bExtentsLocked = TRUE;
9495
9496                                     le = ObjectInfo->Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
9497
9498                                     ulProcessCount = 0;
9499
9500                                     ulCount = (ULONG)ObjectInfo->Fcb->Specific.File.ExtentCount;
9501
9502                                     if( ulCount > 0)
9503                                     {
9504                                         pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
9505
9506                                         while( ulProcessCount < ulCount)
9507                                         {
9508                                             pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
9509
9510                                             if( !BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
9511                                             {
9512                                                 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9513                                                                           &pEntry->FileOffset,
9514                                                                           pEntry->Size,
9515                                                                           FALSE))
9516                                                 {
9517
9518                                                     AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
9519                                                                   AFS_TRACE_LEVEL_WARNING,
9520                                                                   "AFSPerformObjectInvalidation [2] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9521                                                                   ObjectInfo->FileId.Cell,
9522                                                                   ObjectInfo->FileId.Volume,
9523                                                                   ObjectInfo->FileId.Vnode,
9524                                                                   ObjectInfo->FileId.Unique);
9525
9526                                                     bPurgeOnClose = TRUE;
9527                                                 }
9528                                                 else
9529                                                 {
9530
9531                                                     bCleanExtents = TRUE;
9532                                                 }
9533                                             }
9534
9535                                             if( liCurrentOffset.QuadPart < pEntry->FileOffset.QuadPart)
9536                                             {
9537
9538                                                 liFlushLength.QuadPart = pEntry->FileOffset.QuadPart - liCurrentOffset.QuadPart;
9539
9540                                                 while( liFlushLength.QuadPart > 0)
9541                                                 {
9542
9543                                                     if( liFlushLength.QuadPart > 512 * 1024000)
9544                                                     {
9545                                                         ulFlushLength = 512 * 1024000;
9546                                                     }
9547                                                     else
9548                                                     {
9549                                                         ulFlushLength = liFlushLength.LowPart;
9550                                                     }
9551
9552                                                     if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9553                                                                               &liCurrentOffset,
9554                                                                               ulFlushLength,
9555                                                                               FALSE))
9556                                                     {
9557
9558                                                         AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
9559                                                                       AFS_TRACE_LEVEL_WARNING,
9560                                                                       "AFSPerformObjectInvalidation [3] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9561                                                                       ObjectInfo->FileId.Cell,
9562                                                                       ObjectInfo->FileId.Volume,
9563                                                                       ObjectInfo->FileId.Vnode,
9564                                                                       ObjectInfo->FileId.Unique);
9565
9566                                                         bPurgeOnClose = TRUE;
9567                                                     }
9568                                                     else
9569                                                     {
9570
9571                                                         bCleanExtents = TRUE;
9572                                                     }
9573
9574                                                     liFlushLength.QuadPart -= ulFlushLength;
9575                                                 }
9576                                             }
9577
9578                                             liCurrentOffset.QuadPart = pEntry->FileOffset.QuadPart + pEntry->Size;
9579
9580                                             ulProcessCount++;
9581                                             le = le->Flink;
9582                                         }
9583                                     }
9584                                     else
9585                                     {
9586                                         if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9587                                                                   NULL,
9588                                                                   0,
9589                                                                   FALSE))
9590                                         {
9591
9592                                             AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
9593                                                           AFS_TRACE_LEVEL_WARNING,
9594                                                           "AFSPerformObjectInvalidation [4] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9595                                                           ObjectInfo->FileId.Cell,
9596                                                           ObjectInfo->FileId.Volume,
9597                                                           ObjectInfo->FileId.Vnode,
9598                                                           ObjectInfo->FileId.Unique);
9599
9600                                             bPurgeOnClose = TRUE;
9601                                         }
9602                                         else
9603                                         {
9604
9605                                             bCleanExtents = TRUE;
9606                                         }
9607                                     }
9608
9609                                     if ( bPurgeOnClose)
9610                                     {
9611
9612                                         SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9613                                     }
9614                                 }
9615                             }
9616                             __except( EXCEPTION_EXECUTE_HANDLER)
9617                             {
9618
9619                                 ntStatus = GetExceptionCode();
9620
9621                                 AFSDbgLogMsg( 0,
9622                                               0,
9623                                               "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
9624                                               ObjectInfo->FileId.Cell,
9625                                               ObjectInfo->FileId.Volume,
9626                                               ObjectInfo->FileId.Vnode,
9627                                               ObjectInfo->FileId.Unique,
9628                                               ntStatus);
9629                             }
9630
9631                             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
9632                                           AFS_TRACE_LEVEL_VERBOSE,
9633                                           "AFSPerformObjectInvalidation Releasing Fcb SectionObject lock %p EXCL %08lX\n",
9634                                           &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9635                                           PsGetCurrentThread());
9636
9637                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
9638                         }
9639                     }
9640
9641                     if ( bExtentsLocked)
9642                     {
9643
9644                         AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9645                     }
9646
9647                     if ( bLocked)
9648                     {
9649
9650                         AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9651                     }
9652
9653                     if ( bCleanExtents)
9654                     {
9655
9656                         AFSReleaseCleanExtents( ObjectInfo->Fcb,
9657                                                 NULL);
9658                     }
9659                 }
9660
9661                 break;
9662             }
9663         }
9664
9665         //
9666         // Destroy the reference passed in by the caller to AFSInvalidateObject
9667         // or AFSQueueInvalidateObject
9668         //
9669
9670         lCount = AFSObjectInfoDecrement( ObjectInfo,
9671                                          AFS_OBJECT_REFERENCE_INVALIDATION);
9672
9673         AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
9674                       AFS_TRACE_LEVEL_VERBOSE,
9675                       "AFSPerformObjectInvalidation Decrement count on object %p Cnt %d\n",
9676                       ObjectInfo,
9677                       lCount);
9678     }
9679
9680     return ntStatus;
9681 }