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