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