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