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