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