Windows: Use %p for ptrs in redirector trace messages
[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 Increment count on %wZ DE %p Cnt %d\n",
4997                           &DirectoryCB->NameInformation.FileName,
4998                           DirectoryCB,
4999                           lCount);
5000
5001             pCurrentElement->DirectoryCB = DirectoryCB;
5002
5003             pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
5004
5005             pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
5006
5007             if( pCurrentElement->FileId.Vnode == 1)
5008             {
5009
5010                 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5011             }
5012
5013             AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5014                           AFS_TRACE_LEVEL_VERBOSE,
5015                           "AFSInitNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5016                           pNameArray,
5017                           pCurrentElement->DirectoryCB,
5018                           pCurrentElement->FileId.Cell,
5019                           pCurrentElement->FileId.Volume,
5020                           pCurrentElement->FileId.Vnode,
5021                           pCurrentElement->FileId.Unique,
5022                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
5023                           pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5024         }
5025
5026 try_exit:
5027
5028         NOTHING;
5029     }
5030
5031     return pNameArray;
5032 }
5033
5034 NTSTATUS
5035 AFSPopulateNameArray( IN AFSNameArrayHdr *NameArray,
5036                       IN UNICODE_STRING *Path,
5037                       IN AFSDirectoryCB *DirectoryCB)
5038 {
5039
5040     NTSTATUS ntStatus = STATUS_SUCCESS;
5041     AFSNameArrayCB *pCurrentElement = NULL;
5042     LONG lCount;
5043
5044     __Enter
5045     {
5046
5047         AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5048                       AFS_TRACE_LEVEL_VERBOSE,
5049                       "AFSPopulateNameArray [NA:%p] passed Path %wZ DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5050                       NameArray,
5051                       &Path,
5052                       DirectoryCB,
5053                       DirectoryCB->ObjectInformation->FileId.Cell,
5054                       DirectoryCB->ObjectInformation->FileId.Volume,
5055                       DirectoryCB->ObjectInformation->FileId.Vnode,
5056                       DirectoryCB->ObjectInformation->FileId.Unique,
5057                       &DirectoryCB->NameInformation.FileName,
5058                       DirectoryCB->ObjectInformation->FileType);
5059
5060         //
5061         // Init some info in the header
5062         //
5063
5064         pCurrentElement = &NameArray->ElementArray[ 0];
5065
5066         NameArray->CurrentEntry = pCurrentElement;
5067
5068         //
5069         // The first entry points at the root
5070         //
5071
5072         pCurrentElement->DirectoryCB = DirectoryCB->ObjectInformation->VolumeCB->DirectoryCB;
5073
5074         lCount = InterlockedIncrement( &pCurrentElement->DirectoryCB->DirOpenReferenceCount);
5075
5076         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5077                       AFS_TRACE_LEVEL_VERBOSE,
5078                       "AFSPopulateNameArray Increment count on volume %wZ DE %p Cnt %d\n",
5079                       &pCurrentElement->DirectoryCB->NameInformation.FileName,
5080                       pCurrentElement->DirectoryCB,
5081                       lCount);
5082
5083         pCurrentElement->Component = DirectoryCB->ObjectInformation->VolumeCB->DirectoryCB->NameInformation.FileName;
5084
5085         pCurrentElement->FileId = DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation.FileId;
5086
5087         pCurrentElement->Flags = 0;
5088
5089         if( pCurrentElement->FileId.Vnode == 1)
5090         {
5091
5092             SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5093         }
5094
5095         NameArray->Count = 1;
5096
5097         NameArray->LinkCount = 0;
5098
5099         AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5100                       AFS_TRACE_LEVEL_VERBOSE,
5101                       "AFSPopulateNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5102                       NameArray,
5103                       pCurrentElement->DirectoryCB,
5104                       pCurrentElement->FileId.Cell,
5105                       pCurrentElement->FileId.Volume,
5106                       pCurrentElement->FileId.Vnode,
5107                       pCurrentElement->FileId.Unique,
5108                       &pCurrentElement->DirectoryCB->NameInformation.FileName,
5109                       pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5110
5111         //
5112         // If the root is the parent then we are done ...
5113         //
5114
5115         if( &DirectoryCB->ObjectInformation->VolumeCB->ObjectInformation == DirectoryCB->ObjectInformation)
5116         {
5117             try_return( ntStatus);
5118         }
5119
5120 try_exit:
5121
5122         NOTHING;
5123     }
5124
5125     return ntStatus;
5126 }
5127
5128 NTSTATUS
5129 AFSPopulateNameArrayFromRelatedArray( IN AFSNameArrayHdr *NameArray,
5130                                       IN AFSNameArrayHdr *RelatedNameArray,
5131                                       IN AFSDirectoryCB *DirectoryCB)
5132 {
5133
5134     NTSTATUS ntStatus = STATUS_SUCCESS;
5135     AFSNameArrayCB *pCurrentElement = NULL, *pCurrentRelatedElement = NULL;
5136     LONG lCount;
5137
5138     __Enter
5139     {
5140
5141         AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5142                       AFS_TRACE_LEVEL_VERBOSE,
5143                       "AFSPopulateNameArray [NA:%p] passed RelatedNameArray %p DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5144                       NameArray,
5145                       RelatedNameArray,
5146                       DirectoryCB,
5147                       DirectoryCB->ObjectInformation->FileId.Cell,
5148                       DirectoryCB->ObjectInformation->FileId.Volume,
5149                       DirectoryCB->ObjectInformation->FileId.Vnode,
5150                       DirectoryCB->ObjectInformation->FileId.Unique,
5151                       &DirectoryCB->NameInformation.FileName,
5152                       DirectoryCB->ObjectInformation->FileType);
5153
5154         //
5155         // Init some info in the header
5156         //
5157
5158         pCurrentElement = &NameArray->ElementArray[ 0];
5159
5160         pCurrentRelatedElement = &RelatedNameArray->ElementArray[ 0];
5161
5162         NameArray->Count = 0;
5163
5164         NameArray->LinkCount = RelatedNameArray->LinkCount;
5165
5166         //
5167         // Populate the name array with the data from the related array
5168         //
5169
5170         while( TRUE)
5171         {
5172
5173             pCurrentElement->DirectoryCB = pCurrentRelatedElement->DirectoryCB;
5174
5175             pCurrentElement->Component = pCurrentRelatedElement->DirectoryCB->NameInformation.FileName;
5176
5177             pCurrentElement->FileId    = pCurrentElement->DirectoryCB->ObjectInformation->FileId;
5178
5179             pCurrentElement->Flags = 0;
5180
5181             if( pCurrentElement->FileId.Vnode == 1)
5182             {
5183
5184                 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5185             }
5186
5187             lCount = InterlockedIncrement( &pCurrentElement->DirectoryCB->DirOpenReferenceCount);
5188
5189             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5190                           AFS_TRACE_LEVEL_VERBOSE,
5191                           "AFSPopulateNameArrayFromRelatedArray Increment count on %wZ DE %p Cnt %d\n",
5192                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
5193                           pCurrentElement->DirectoryCB,
5194                           lCount);
5195
5196             lCount = InterlockedIncrement( &NameArray->Count);
5197
5198             AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5199                           AFS_TRACE_LEVEL_VERBOSE,
5200                           "AFSPopulateNameArrayFromRelatedArray [NA:%p] Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5201                           NameArray,
5202                           lCount - 1,
5203                           pCurrentElement->DirectoryCB,
5204                           pCurrentElement->FileId.Cell,
5205                           pCurrentElement->FileId.Volume,
5206                           pCurrentElement->FileId.Vnode,
5207                           pCurrentElement->FileId.Unique,
5208                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
5209                           pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5210
5211             if( pCurrentElement->DirectoryCB == DirectoryCB ||
5212                 NameArray->Count == RelatedNameArray->Count)
5213             {
5214
5215                 //
5216                 // Done ...
5217                 //
5218
5219                 break;
5220             }
5221
5222             pCurrentElement++;
5223
5224             pCurrentRelatedElement++;
5225         }
5226
5227         NameArray->CurrentEntry = NameArray->Count > 0 ? pCurrentElement : NULL;
5228     }
5229
5230     return ntStatus;
5231 }
5232
5233 NTSTATUS
5234 AFSFreeNameArray( IN AFSNameArrayHdr *NameArray)
5235 {
5236
5237     NTSTATUS ntStatus = STATUS_SUCCESS;
5238     AFSNameArrayCB *pCurrentElement = NULL;
5239     LONG lCount, lElement;
5240
5241     __Enter
5242     {
5243
5244         AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5245                       AFS_TRACE_LEVEL_VERBOSE,
5246                       "AFSFreeNameArray [NA:%p]\n",
5247                       NameArray);
5248
5249         for ( lElement = 0; lElement < NameArray->Count; lElement++)
5250         {
5251
5252             pCurrentElement = &NameArray->ElementArray[ lElement];
5253
5254             lCount = InterlockedDecrement( &pCurrentElement->DirectoryCB->DirOpenReferenceCount);
5255
5256             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5257                           AFS_TRACE_LEVEL_VERBOSE,
5258                           "AFSFreeNameArray Decrement count on %wZ DE %p Cnt %d\n",
5259                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
5260                           pCurrentElement->DirectoryCB,
5261                           lCount);
5262
5263             ASSERT( lCount >= 0);
5264         }
5265
5266         AFSExFreePoolWithTag( NameArray, AFS_NAME_ARRAY_TAG);
5267     }
5268
5269     return ntStatus;
5270 }
5271
5272 NTSTATUS
5273 AFSInsertNextElement( IN AFSNameArrayHdr *NameArray,
5274                       IN AFSDirectoryCB *DirectoryCB)
5275 {
5276
5277     NTSTATUS ntStatus = STATUS_SUCCESS;
5278     AFSNameArrayCB *pCurrentElement = NULL;
5279     LONG lCount;
5280
5281     __Enter
5282     {
5283
5284         AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5285                       AFS_TRACE_LEVEL_VERBOSE,
5286                       "AFSInsertNextElement [NA:%p] passed DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5287                       NameArray,
5288                       DirectoryCB,
5289                       DirectoryCB->ObjectInformation->FileId.Cell,
5290                       DirectoryCB->ObjectInformation->FileId.Volume,
5291                       DirectoryCB->ObjectInformation->FileId.Vnode,
5292                       DirectoryCB->ObjectInformation->FileId.Unique,
5293                       &DirectoryCB->NameInformation.FileName,
5294                       DirectoryCB->ObjectInformation->FileType);
5295
5296         if( NameArray->Count == (LONG) NameArray->MaxElementCount)
5297         {
5298
5299             AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5300                           AFS_TRACE_LEVEL_ERROR,
5301                           "AFSInsertNextElement [NA:%p] Name has reached Maximum Size\n",
5302                           NameArray);
5303
5304             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5305         }
5306
5307         for ( lCount = 0; lCount < NameArray->Count; lCount++)
5308         {
5309
5310             if ( AFSIsEqualFID( &NameArray->ElementArray[ lCount].FileId,
5311                                 &DirectoryCB->ObjectInformation->FileId) )
5312             {
5313
5314                 AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5315                               AFS_TRACE_LEVEL_WARNING,
5316                               "AFSInsertNextElement [NA:%p] DE %p recursion Status %08X\n",
5317                               NameArray,
5318                               DirectoryCB,
5319                               STATUS_ACCESS_DENIED);
5320
5321                 try_return( ntStatus = STATUS_ACCESS_DENIED);
5322             }
5323         }
5324
5325         if( NameArray->Count > 0)
5326         {
5327
5328             NameArray->CurrentEntry++;
5329         }
5330         else
5331         {
5332             NameArray->CurrentEntry = &NameArray->ElementArray[ 0];
5333         }
5334
5335         pCurrentElement = NameArray->CurrentEntry;
5336
5337         lCount = InterlockedIncrement( &NameArray->Count);
5338
5339         lCount = InterlockedIncrement( &DirectoryCB->DirOpenReferenceCount);
5340
5341         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5342                       AFS_TRACE_LEVEL_VERBOSE,
5343                       "AFSInsertNextElement Increment count on %wZ DE %p Cnt %d\n",
5344                       &DirectoryCB->NameInformation.FileName,
5345                       DirectoryCB,
5346                       lCount);
5347
5348         ASSERT( lCount >= 2);
5349
5350         pCurrentElement->DirectoryCB = DirectoryCB;
5351
5352         pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
5353
5354         pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
5355
5356         pCurrentElement->Flags = 0;
5357
5358         if( pCurrentElement->FileId.Vnode == 1)
5359         {
5360
5361             SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5362         }
5363
5364         AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5365                       AFS_TRACE_LEVEL_VERBOSE,
5366                       "AFSInsertNextElement [NA:%p] Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5367                       NameArray,
5368                       NameArray->Count - 1,
5369                       pCurrentElement->DirectoryCB,
5370                       pCurrentElement->FileId.Cell,
5371                       pCurrentElement->FileId.Volume,
5372                       pCurrentElement->FileId.Vnode,
5373                       pCurrentElement->FileId.Unique,
5374                       &pCurrentElement->DirectoryCB->NameInformation.FileName,
5375                       pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5376
5377 try_exit:
5378
5379         NOTHING;
5380     }
5381
5382     return ntStatus;
5383 }
5384
5385 AFSDirectoryCB *
5386 AFSBackupEntry( IN AFSNameArrayHdr *NameArray)
5387 {
5388
5389     AFSDirectoryCB *pDirectoryCB = NULL;
5390     AFSNameArrayCB *pCurrentElement = NULL;
5391     BOOLEAN         bVolumeRoot = FALSE;
5392     LONG lCount;
5393
5394     __Enter
5395     {
5396
5397         AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5398                       AFS_TRACE_LEVEL_VERBOSE,
5399                       "AFSBackupEntry [NA:%p]\n",
5400                       NameArray);
5401
5402         if( NameArray->Count == 0)
5403         {
5404
5405             AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5406                           AFS_TRACE_LEVEL_ERROR,
5407                           "AFSBackupEntry [NA:%p] No more entries\n",
5408                           NameArray);
5409
5410             try_return( pCurrentElement);
5411         }
5412
5413         lCount = InterlockedDecrement( &NameArray->CurrentEntry->DirectoryCB->DirOpenReferenceCount);
5414
5415         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5416                       AFS_TRACE_LEVEL_VERBOSE,
5417                       "AFSBackupEntry Decrement count on %wZ DE %p Cnt %d\n",
5418                       &NameArray->CurrentEntry->DirectoryCB->NameInformation.FileName,
5419                       NameArray->CurrentEntry->DirectoryCB,
5420                       lCount);
5421
5422         ASSERT( lCount >= 0);
5423
5424         NameArray->CurrentEntry->DirectoryCB = NULL;
5425
5426         lCount = InterlockedDecrement( &NameArray->Count);
5427
5428         if( lCount == 0)
5429         {
5430             NameArray->CurrentEntry = NULL;
5431
5432             AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5433                           AFS_TRACE_LEVEL_ERROR,
5434                           "AFSBackupEntry [NA:%p] No more entries\n",
5435                           NameArray);
5436         }
5437         else
5438         {
5439
5440             bVolumeRoot = BooleanFlagOn( NameArray->CurrentEntry->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5441
5442             NameArray->CurrentEntry--;
5443
5444             pCurrentElement = NameArray->CurrentEntry;
5445
5446             pDirectoryCB = pCurrentElement->DirectoryCB;
5447
5448             AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5449                           AFS_TRACE_LEVEL_VERBOSE,
5450                           "AFSBackupEntry [NA:%p] Returning Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5451                           NameArray,
5452                           NameArray->Count - 1,
5453                           pCurrentElement->DirectoryCB,
5454                           pCurrentElement->FileId.Cell,
5455                           pCurrentElement->FileId.Volume,
5456                           pCurrentElement->FileId.Vnode,
5457                           pCurrentElement->FileId.Unique,
5458                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
5459                           pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5460
5461             //
5462             // If the entry we are removing is a volume root,
5463             // we must remove the mount point entry as well.
5464             // If the NameArray was constructed by checking the
5465             // share name via the service, the name array can
5466             // contain two volume roots in sequence without a
5467             // mount point separating them.
5468             //
5469
5470             if ( bVolumeRoot &&
5471                  !BooleanFlagOn( NameArray->CurrentEntry->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT))
5472             {
5473
5474                 pDirectoryCB = AFSBackupEntry( NameArray);
5475             }
5476         }
5477
5478
5479 try_exit:
5480
5481         NOTHING;
5482     }
5483
5484     return pDirectoryCB;
5485 }
5486
5487 AFSDirectoryCB *
5488 AFSGetParentEntry( IN AFSNameArrayHdr *NameArray)
5489 {
5490
5491     AFSDirectoryCB *pDirEntry = NULL;
5492     AFSNameArrayCB *pElement = NULL;
5493
5494     __Enter
5495     {
5496
5497         AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5498                       AFS_TRACE_LEVEL_VERBOSE,
5499                       "AFSGetParentEntry [NA:%p]\n",
5500                       NameArray);
5501
5502         if( NameArray->Count == 0 ||
5503             NameArray->Count == 1)
5504         {
5505
5506             AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5507                           AFS_TRACE_LEVEL_ERROR,
5508                           "AFSGetParentEntry [NA:%p] No more entries\n",
5509                           NameArray);
5510
5511             try_return( pDirEntry = NULL);
5512         }
5513
5514         pElement = &NameArray->ElementArray[ NameArray->Count - 2];
5515
5516         pDirEntry = pElement->DirectoryCB;
5517
5518         AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5519                       AFS_TRACE_LEVEL_VERBOSE,
5520                       "AFSGetParentEntry [NA:%p] Returning Element[%d] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5521                       NameArray,
5522                       NameArray->Count - 2,
5523                       pElement->DirectoryCB,
5524                       pElement->FileId.Cell,
5525                       pElement->FileId.Volume,
5526                       pElement->FileId.Vnode,
5527                       pElement->FileId.Unique,
5528                       &pElement->DirectoryCB->NameInformation.FileName,
5529                       pElement->DirectoryCB->ObjectInformation->FileType);
5530
5531 try_exit:
5532
5533         NOTHING;
5534     }
5535
5536     return pDirEntry;
5537 }
5538
5539 void
5540 AFSResetNameArray( IN AFSNameArrayHdr *NameArray,
5541                    IN AFSDirectoryCB *DirectoryCB)
5542 {
5543
5544     AFSNameArrayCB *pCurrentElement = NULL;
5545     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
5546     LONG lCount, lElement;
5547
5548     __Enter
5549     {
5550
5551         AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5552                       AFS_TRACE_LEVEL_VERBOSE,
5553                       "AFSResetNameArray [NA:%p] passed DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5554                       NameArray,
5555                       DirectoryCB,
5556                       DirectoryCB->ObjectInformation->FileId.Cell,
5557                       DirectoryCB->ObjectInformation->FileId.Volume,
5558                       DirectoryCB->ObjectInformation->FileId.Vnode,
5559                       DirectoryCB->ObjectInformation->FileId.Unique,
5560                       &DirectoryCB->NameInformation.FileName,
5561                       DirectoryCB->ObjectInformation->FileType);
5562         //
5563         // Dereference previous name array contents
5564         //
5565
5566         for ( lElement = 0; lElement < NameArray->Count; lElement++)
5567         {
5568
5569             pCurrentElement = &NameArray->ElementArray[ lElement];
5570
5571             lCount = InterlockedDecrement( &pCurrentElement->DirectoryCB->DirOpenReferenceCount);
5572
5573             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5574                           AFS_TRACE_LEVEL_VERBOSE,
5575                           "AFSResetNameArray Decrement count on %wZ DE %p Cnt %d\n",
5576                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
5577                           pCurrentElement->DirectoryCB,
5578                           lCount);
5579
5580             ASSERT( lCount >= 0);
5581         }
5582
5583         RtlZeroMemory( NameArray,
5584                        sizeof( AFSNameArrayHdr) +
5585                           ((pDevExt->Specific.RDR.NameArrayLength - 1) * sizeof( AFSNameArrayCB)));
5586
5587         NameArray->MaxElementCount = pDevExt->Specific.RDR.NameArrayLength;
5588
5589         if( DirectoryCB != NULL)
5590         {
5591
5592             pCurrentElement = &NameArray->ElementArray[ 0];
5593
5594             NameArray->CurrentEntry = pCurrentElement;
5595
5596             NameArray->Count = 1;
5597
5598             NameArray->LinkCount = 0;
5599
5600             lCount = InterlockedIncrement( &DirectoryCB->DirOpenReferenceCount);
5601
5602             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5603                           AFS_TRACE_LEVEL_VERBOSE,
5604                           "AFSResetNameArray Increment count on %wZ DE %p Cnt %d\n",
5605                           &DirectoryCB->NameInformation.FileName,
5606                           DirectoryCB,
5607                           lCount);
5608
5609             pCurrentElement->DirectoryCB = DirectoryCB;
5610
5611             pCurrentElement->Component = DirectoryCB->NameInformation.FileName;
5612
5613             pCurrentElement->FileId = DirectoryCB->ObjectInformation->FileId;
5614
5615             pCurrentElement->Flags  = 0;
5616
5617             if( pCurrentElement->FileId.Vnode == 1)
5618             {
5619
5620                 SetFlag( pCurrentElement->Flags, AFS_NAME_ARRAY_FLAG_ROOT_ELEMENT);
5621             }
5622
5623             AFSDbgLogMsg( AFS_SUBSYSTEM_NAME_ARRAY_PROCESSING,
5624                           AFS_TRACE_LEVEL_VERBOSE,
5625                           "AFSResetNameArray [NA:%p] Element[0] DE %p FID %08lX-%08lX-%08lX-%08lX %wZ Type %d\n",
5626                           NameArray,
5627                           pCurrentElement->DirectoryCB,
5628                           pCurrentElement->FileId.Cell,
5629                           pCurrentElement->FileId.Volume,
5630                           pCurrentElement->FileId.Vnode,
5631                           pCurrentElement->FileId.Unique,
5632                           &pCurrentElement->DirectoryCB->NameInformation.FileName,
5633                           pCurrentElement->DirectoryCB->ObjectInformation->FileType);
5634         }
5635     }
5636
5637     return;
5638 }
5639
5640 void
5641 AFSDumpNameArray( IN AFSNameArrayHdr *NameArray)
5642 {
5643
5644     AFSNameArrayCB *pCurrentElement = NULL;
5645
5646     pCurrentElement = &NameArray->ElementArray[ 0];
5647
5648     AFSPrint("AFSDumpNameArray Start (%d)\n", NameArray->Count);
5649
5650     while( pCurrentElement->DirectoryCB != NULL)
5651     {
5652
5653         AFSPrint("FID %08lX-%08lX-%08lX-%08lX %wZ\n",
5654                   pCurrentElement->FileId.Cell,
5655                   pCurrentElement->FileId.Volume,
5656                   pCurrentElement->FileId.Vnode,
5657                   pCurrentElement->FileId.Unique,
5658                   &pCurrentElement->DirectoryCB->NameInformation.FileName);
5659
5660         pCurrentElement++;
5661     }
5662
5663     AFSPrint("AFSDumpNameArray End\n\n");
5664
5665     return;
5666 }
5667
5668 void
5669 AFSSetEnumerationEvent( IN AFSFcb *Fcb)
5670 {
5671     LONG lCount;
5672
5673     //
5674     // Depending on the type of node, set the event
5675     //
5676
5677     switch( Fcb->Header.NodeTypeCode)
5678     {
5679
5680         case AFS_DIRECTORY_FCB:
5681         case AFS_ROOT_FCB:
5682         case AFS_ROOT_ALL:
5683         {
5684
5685             lCount = InterlockedIncrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
5686
5687             break;
5688         }
5689     }
5690
5691     return;
5692 }
5693
5694 void
5695 AFSClearEnumerationEvent( IN AFSFcb *Fcb)
5696 {
5697
5698     LONG lCount;
5699
5700     //
5701     // Depending on the type of node, set the event
5702     //
5703
5704     switch( Fcb->Header.NodeTypeCode)
5705     {
5706
5707         case AFS_DIRECTORY_FCB:
5708         case AFS_ROOT_FCB:
5709         case AFS_ROOT_ALL:
5710         {
5711
5712             ASSERT( Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0);
5713
5714             lCount = InterlockedDecrement( &Fcb->NPFcb->Specific.Directory.DirectoryEnumCount);
5715
5716             break;
5717         }
5718     }
5719
5720     return;
5721 }
5722
5723 BOOLEAN
5724 AFSIsEnumerationInProcess( IN AFSObjectInfoCB *ObjectInfo)
5725 {
5726
5727     BOOLEAN bIsInProcess = FALSE;
5728
5729     __Enter
5730     {
5731
5732         if( ObjectInfo->Fcb == NULL)
5733         {
5734
5735             try_return( bIsInProcess);
5736         }
5737
5738         switch( ObjectInfo->Fcb->Header.NodeTypeCode)
5739         {
5740
5741             case AFS_DIRECTORY_FCB:
5742             case AFS_ROOT_FCB:
5743             case AFS_ROOT_ALL:
5744             {
5745
5746                 if( ObjectInfo->Fcb->NPFcb->Specific.Directory.DirectoryEnumCount > 0)
5747                 {
5748
5749                     bIsInProcess = TRUE;
5750                 }
5751
5752                 break;
5753             }
5754         }
5755
5756 try_exit:
5757
5758         NOTHING;
5759     }
5760
5761     return bIsInProcess;
5762 }
5763
5764 NTSTATUS
5765 AFSVerifyVolume( IN ULONGLONG ProcessId,
5766                  IN AFSVolumeCB *VolumeCB)
5767 {
5768
5769     UNREFERENCED_PARAMETER(ProcessId);
5770     UNREFERENCED_PARAMETER(VolumeCB);
5771     NTSTATUS ntStatus = STATUS_SUCCESS;
5772
5773
5774     return ntStatus;
5775 }
5776
5777 NTSTATUS
5778 AFSInitPIOCtlDirectoryCB( IN AFSObjectInfoCB *ObjectInfo)
5779 {
5780
5781     NTSTATUS ntStatus = STATUS_SUCCESS;
5782     AFSObjectInfoCB *pObjectInfoCB = NULL;
5783     AFSDirectoryCB *pDirNode = NULL;
5784     ULONG ulEntryLength = 0;
5785     AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
5786     LONG lCount;
5787
5788     __Enter
5789     {
5790
5791         pObjectInfoCB = AFSAllocateObjectInfo( ObjectInfo,
5792                                                0);
5793
5794         if( pObjectInfoCB == NULL)
5795         {
5796
5797             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5798         }
5799
5800         AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
5801                       AFS_TRACE_LEVEL_VERBOSE,
5802                       "AFSInitPIOCtlDirectoryCB Initializing count (1) on object %p\n",
5803                       pObjectInfoCB);
5804
5805         pObjectInfoCB->ObjectReferenceCount = 1;
5806
5807         pObjectInfoCB->FileType = (ULONG) AFS_FILE_TYPE_PIOCTL;
5808
5809         pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
5810
5811         ulEntryLength = sizeof( AFSDirectoryCB) + AFSPIOCtlName.Length;
5812
5813         pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
5814                                                                ulEntryLength,
5815                                                                AFS_DIR_ENTRY_TAG);
5816
5817         if( pDirNode == NULL)
5818         {
5819
5820             AFSDeleteObjectInfo( pObjectInfoCB);
5821
5822             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5823         }
5824
5825         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
5826                                                                                 sizeof( AFSNonPagedDirectoryCB),
5827                                                                                 AFS_DIR_ENTRY_NP_TAG);
5828
5829         if( pNonPagedDirEntry == NULL)
5830         {
5831
5832             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5833         }
5834
5835         RtlZeroMemory( pDirNode,
5836                        ulEntryLength);
5837
5838         RtlZeroMemory( pNonPagedDirEntry,
5839                        sizeof( AFSNonPagedDirectoryCB));
5840
5841         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
5842
5843         pDirNode->NonPaged = pNonPagedDirEntry;
5844
5845         pDirNode->ObjectInformation = pObjectInfoCB;
5846
5847         pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_PIOCTL_INDEX;
5848
5849         //
5850         // Set valid entry
5851         //
5852
5853         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_FAKE);
5854
5855         pDirNode->NameInformation.FileName.Length = AFSPIOCtlName.Length;
5856
5857         pDirNode->NameInformation.FileName.MaximumLength = AFSPIOCtlName.Length;
5858
5859         pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
5860
5861         RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
5862                        AFSPIOCtlName.Buffer,
5863                        pDirNode->NameInformation.FileName.Length);
5864
5865         pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
5866                                                                        TRUE);
5867
5868         if ( InterlockedCompareExchangePointer( (PVOID *)&ObjectInfo->Specific.Directory.PIOCtlDirectoryCB, pDirNode, NULL) != NULL)
5869         {
5870
5871             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
5872                           AFS_TRACE_LEVEL_WARNING,
5873                           "AFSInitPIOCtlDirectoryCB Raced PIOCtlDirectoryCB %p pFcb %p\n",
5874                           ObjectInfo->Specific.Directory.PIOCtlDirectoryCB,
5875                           pDirNode);
5876
5877             //
5878             // Increment the open reference and handle on the node
5879             //
5880
5881             lCount = AFSObjectInfoIncrement( pDirNode->ObjectInformation);
5882
5883             AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
5884                           AFS_TRACE_LEVEL_VERBOSE,
5885                           "AFSInitPIOCtlDirectoryCB Increment count on Object %p Cnt %d\n",
5886                           pDirNode->ObjectInformation,
5887                           lCount);
5888
5889             try_return( ntStatus = STATUS_REPARSE);
5890         }
5891
5892 try_exit:
5893
5894         if ( ntStatus != STATUS_SUCCESS)
5895         {
5896
5897             if ( pDirNode != NULL)
5898             {
5899
5900                 AFSExFreePoolWithTag( pDirNode, AFS_DIR_ENTRY_TAG);
5901             }
5902
5903             if( pNonPagedDirEntry != NULL)
5904             {
5905
5906                 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
5907
5908                 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
5909             }
5910
5911             if ( pObjectInfoCB != NULL)
5912             {
5913
5914                 AFSDeleteObjectInfo( pObjectInfoCB);
5915             }
5916         }
5917     }
5918
5919     return ntStatus;
5920 }
5921
5922 NTSTATUS
5923 AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB,
5924                            IN AFSDirectoryCB *DirectoryCB,
5925                            IN UNICODE_STRING *ParentPathName,
5926                            IN AFSNameArrayHdr *RelatedNameArray,
5927                            IN GUID           *AuthGroup,
5928                            OUT AFSFileInfoCB *FileInfo)
5929 {
5930
5931     NTSTATUS ntStatus = STATUS_SUCCESS;
5932     AFSDirEnumEntry *pDirEntry = NULL;
5933     UNICODE_STRING uniFullPathName = {0};
5934     AFSNameArrayHdr    *pNameArray = NULL;
5935     AFSVolumeCB *pVolumeCB = NULL;
5936     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
5937     WCHAR *pwchBuffer = NULL;
5938     UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
5939     ULONG ulNameDifference = 0;
5940     LONG lCount;
5941
5942     __Enter
5943     {
5944
5945         //
5946         // Retrieve a target name for the entry
5947         //
5948
5949         AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
5950                           TRUE);
5951
5952         if( DirectoryCB->NameInformation.TargetName.Length == 0)
5953         {
5954
5955             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5956
5957             ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
5958                                               AuthGroup,
5959                                               FALSE,
5960                                               &pDirEntry);
5961
5962             if( !NT_SUCCESS( ntStatus) ||
5963                 pDirEntry->TargetNameLength == 0)
5964             {
5965
5966                 if( pDirEntry != NULL)
5967                 {
5968
5969                     ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
5970                 }
5971
5972                 try_return( ntStatus);
5973             }
5974
5975             AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
5976                             TRUE);
5977
5978             if( DirectoryCB->NameInformation.TargetName.Length == 0)
5979             {
5980
5981                 //
5982                 // Update the target name
5983                 //
5984
5985                 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
5986                                                 &DirectoryCB->Flags,
5987                                                 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
5988                                                 (USHORT)pDirEntry->TargetNameLength);
5989
5990                 if( !NT_SUCCESS( ntStatus))
5991                 {
5992
5993                     AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5994
5995                     try_return( ntStatus);
5996                 }
5997             }
5998
5999             AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
6000         }
6001
6002         //
6003         // Need to pass the full path in for parsing.
6004         //
6005
6006         if( AFSIsRelativeName( &DirectoryCB->NameInformation.TargetName))
6007         {
6008
6009             uniFullPathName.Length = 0;
6010             uniFullPathName.MaximumLength = ParentPathName->Length +
6011                                                     sizeof( WCHAR) +
6012                                                     DirectoryCB->NameInformation.TargetName.Length;
6013
6014             uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6015                                                                         uniFullPathName.MaximumLength,
6016                                                                         AFS_NAME_BUFFER_SIX_TAG);
6017
6018             if( uniFullPathName.Buffer == NULL)
6019             {
6020
6021                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6022
6023                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6024             }
6025
6026             pwchBuffer = uniFullPathName.Buffer;
6027
6028             RtlZeroMemory( uniFullPathName.Buffer,
6029                            uniFullPathName.MaximumLength);
6030
6031             RtlCopyMemory( uniFullPathName.Buffer,
6032                            ParentPathName->Buffer,
6033                            ParentPathName->Length);
6034
6035             uniFullPathName.Length = ParentPathName->Length;
6036
6037             if( uniFullPathName.Buffer[ (uniFullPathName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
6038                 DirectoryCB->NameInformation.TargetName.Buffer[ 0] != L'\\')
6039             {
6040
6041                 uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)] = L'\\';
6042
6043                 uniFullPathName.Length += sizeof( WCHAR);
6044             }
6045
6046             RtlCopyMemory( &uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)],
6047                            DirectoryCB->NameInformation.TargetName.Buffer,
6048                            DirectoryCB->NameInformation.TargetName.Length);
6049
6050             uniFullPathName.Length += DirectoryCB->NameInformation.TargetName.Length;
6051
6052             uniParsedName.Length = uniFullPathName.Length - ParentPathName->Length;
6053             uniParsedName.MaximumLength = uniParsedName.Length;
6054
6055             uniParsedName.Buffer = &uniFullPathName.Buffer[ ParentPathName->Length/sizeof( WCHAR)];
6056
6057             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6058
6059             //
6060             // We populate up to the current parent
6061             //
6062
6063             if( RelatedNameArray != NULL)
6064             {
6065
6066                 pNameArray = AFSInitNameArray( NULL,
6067                                                RelatedNameArray->MaxElementCount);
6068
6069                 if( pNameArray == NULL)
6070                 {
6071
6072                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6073                 }
6074
6075                 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
6076                                                                  RelatedNameArray,
6077                                                                  ParentDirectoryCB);
6078             }
6079             else
6080             {
6081
6082                 pNameArray = AFSInitNameArray( NULL,
6083                                                0);
6084
6085                 if( pNameArray == NULL)
6086                 {
6087
6088                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6089                 }
6090
6091                 ntStatus = AFSPopulateNameArray( pNameArray,
6092                                                  NULL,
6093                                                  ParentDirectoryCB);
6094             }
6095
6096             if( !NT_SUCCESS( ntStatus))
6097             {
6098
6099                 try_return( ntStatus);
6100             }
6101
6102             pVolumeCB = ParentDirectoryCB->ObjectInformation->VolumeCB;
6103
6104             pParentDirEntry = ParentDirectoryCB;
6105         }
6106         else
6107         {
6108
6109             uniFullPathName.Length = 0;
6110             uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
6111
6112             uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6113                                                                         uniFullPathName.MaximumLength,
6114                                                                         AFS_NAME_BUFFER_SEVEN_TAG);
6115
6116             if( uniFullPathName.Buffer == NULL)
6117             {
6118
6119                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6120
6121                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6122             }
6123
6124             pwchBuffer = uniFullPathName.Buffer;
6125
6126             RtlZeroMemory( uniFullPathName.Buffer,
6127                            uniFullPathName.MaximumLength);
6128
6129             RtlCopyMemory( uniFullPathName.Buffer,
6130                            DirectoryCB->NameInformation.TargetName.Buffer,
6131                            DirectoryCB->NameInformation.TargetName.Length);
6132
6133             uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6134
6135             //
6136             // This name should begin with the \afs server so parse it off and check it
6137             //
6138
6139             FsRtlDissectName( uniFullPathName,
6140                               &uniComponentName,
6141                               &uniRemainingPath);
6142
6143             if( RtlCompareUnicodeString( &uniComponentName,
6144                                          &AFSServerName,
6145                                          TRUE) != 0)
6146             {
6147
6148                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6149
6150                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
6151                               AFS_TRACE_LEVEL_ERROR,
6152                               "AFSRetrieveFileAttributes Name %wZ contains invalid server name\n",
6153                               &uniFullPathName);
6154
6155                 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
6156             }
6157
6158             uniFullPathName = uniRemainingPath;
6159
6160             uniParsedName = uniFullPathName;
6161
6162             ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
6163
6164             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6165
6166             //
6167             // Our name array
6168             //
6169
6170             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
6171                                            0);
6172
6173             if( pNameArray == NULL)
6174             {
6175
6176                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6177             }
6178
6179             pVolumeCB = AFSGlobalRoot;
6180
6181             pParentDirEntry = AFSGlobalRoot->DirectoryCB;
6182         }
6183
6184         //
6185         // Increment the ref count on the volume and dir entry for correct processing below
6186         //
6187
6188         lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
6189
6190         AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6191                       AFS_TRACE_LEVEL_VERBOSE,
6192                       "AFSRetrieveFileAttributes Increment count on volume %p Cnt %d\n",
6193                       pVolumeCB,
6194                       lCount);
6195
6196         lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
6197
6198         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6199                       AFS_TRACE_LEVEL_VERBOSE,
6200                       "AFSRetrieveFileAttributes Increment count on %wZ DE %p Ccb %p Cnt %d\n",
6201                       &pParentDirEntry->NameInformation.FileName,
6202                       pParentDirEntry,
6203                       NULL,
6204                       lCount);
6205
6206         ntStatus = AFSLocateNameEntry( NULL,
6207                                        NULL,
6208                                        &uniFullPathName,
6209                                        &uniParsedName,
6210                                        pNameArray,
6211                                        AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL,
6212                                        &pVolumeCB,
6213                                        &pParentDirEntry,
6214                                        &pDirectoryEntry,
6215                                        NULL);
6216
6217         if( !NT_SUCCESS( ntStatus) ||
6218             ntStatus == STATUS_REPARSE)
6219         {
6220
6221             //
6222             // The volume lock was released on failure or reparse above
6223             // Except for STATUS_OBJECT_NAME_NOT_FOUND
6224             //
6225
6226             if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
6227             {
6228
6229                 if( pVolumeCB != NULL)
6230                 {
6231
6232                     lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6233
6234                     AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6235                                   AFS_TRACE_LEVEL_VERBOSE,
6236                                   "AFSRetrieveFileAttributes Decrement count on volume %p Cnt %d\n",
6237                                   pVolumeCB,
6238                                   lCount);
6239                 }
6240
6241                 if( pDirectoryEntry != NULL)
6242                 {
6243
6244                     lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
6245
6246                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6247                                   AFS_TRACE_LEVEL_VERBOSE,
6248                                   "AFSRetrieveFileAttributes Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6249                                   &pDirectoryEntry->NameInformation.FileName,
6250                                   pDirectoryEntry,
6251                                   NULL,
6252                                   lCount);
6253
6254                     ASSERT( lCount >= 0);
6255                 }
6256                 else
6257                 {
6258
6259                     lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
6260
6261                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6262                                   AFS_TRACE_LEVEL_VERBOSE,
6263                                   "AFSRetrieveFileAttributes Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
6264                                   &pParentDirEntry->NameInformation.FileName,
6265                                   pParentDirEntry,
6266                                   NULL,
6267                                   lCount);
6268
6269                     ASSERT( lCount >= 0);
6270                 }
6271             }
6272
6273             pVolumeCB = NULL;
6274
6275             try_return( ntStatus);
6276         }
6277
6278         //
6279         // Store off the information
6280         //
6281
6282         FileInfo->FileAttributes = pDirectoryEntry->ObjectInformation->FileAttributes;
6283
6284         //
6285         // Check for the mount point being returned
6286         //
6287
6288         if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT)
6289         {
6290
6291             FileInfo->FileAttributes = (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
6292         }
6293         else if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK ||
6294                  pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DFSLINK)
6295         {
6296
6297             if ( FileInfo->FileAttributes == FILE_ATTRIBUTE_NORMAL)
6298             {
6299
6300                 FileInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
6301             }
6302             else
6303             {
6304
6305                 FileInfo->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
6306             }
6307         }
6308
6309         FileInfo->AllocationSize = pDirectoryEntry->ObjectInformation->AllocationSize;
6310
6311         FileInfo->EndOfFile = pDirectoryEntry->ObjectInformation->EndOfFile;
6312
6313         FileInfo->CreationTime = pDirectoryEntry->ObjectInformation->CreationTime;
6314
6315         FileInfo->LastAccessTime = pDirectoryEntry->ObjectInformation->LastAccessTime;
6316
6317         FileInfo->LastWriteTime = pDirectoryEntry->ObjectInformation->LastWriteTime;
6318
6319         FileInfo->ChangeTime = pDirectoryEntry->ObjectInformation->ChangeTime;
6320
6321         //
6322         // Remove the reference made above
6323         //
6324
6325         lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
6326
6327         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6328                       AFS_TRACE_LEVEL_VERBOSE,
6329                       "AFSRetrieveFileAttributes Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
6330                       &pDirectoryEntry->NameInformation.FileName,
6331                       pDirectoryEntry,
6332                       NULL,
6333                       lCount);
6334
6335         ASSERT( lCount >= 0);
6336
6337 try_exit:
6338
6339         if( pDirEntry != NULL)
6340         {
6341
6342             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
6343         }
6344
6345         if( pVolumeCB != NULL)
6346         {
6347
6348             lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6349
6350             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6351                           AFS_TRACE_LEVEL_VERBOSE,
6352                           "AFSRetrieveFileAttributes Decrement2 count on volume %p Cnt %d\n",
6353                           pVolumeCB,
6354                           lCount);
6355         }
6356
6357         if( pNameArray != NULL)
6358         {
6359
6360             AFSFreeNameArray( pNameArray);
6361         }
6362
6363         if( pwchBuffer != NULL)
6364         {
6365
6366             //
6367             // Always free the buffer that we allocated as AFSLocateNameEntry
6368             // will not free it.  If uniFullPathName.Buffer was allocated by
6369             // AFSLocateNameEntry, then we must free that as well.
6370             // Check that the uniFullPathName.Buffer in the string is not the same
6371             // offset by the length of the server name
6372             //
6373
6374             if( uniFullPathName.Length > 0 &&
6375                 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
6376             {
6377
6378                 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
6379             }
6380
6381             AFSExFreePoolWithTag( pwchBuffer, 0);
6382         }
6383     }
6384
6385     return ntStatus;
6386 }
6387
6388 AFSObjectInfoCB *
6389 AFSAllocateObjectInfo( IN AFSObjectInfoCB *ParentObjectInfo,
6390                        IN ULONGLONG HashIndex)
6391 {
6392
6393     NTSTATUS ntStatus = STATUS_SUCCESS;
6394     AFSObjectInfoCB *pObjectInfo = NULL;
6395     LONG lCount;
6396
6397     __Enter
6398     {
6399
6400         pObjectInfo = (AFSObjectInfoCB *)AFSExAllocatePoolWithTag( PagedPool,
6401                                                                    sizeof( AFSObjectInfoCB),
6402                                                                    AFS_OBJECT_INFO_TAG);
6403
6404         if( pObjectInfo == NULL)
6405         {
6406
6407             try_return( pObjectInfo);
6408         }
6409
6410         RtlZeroMemory( pObjectInfo,
6411                        sizeof( AFSObjectInfoCB));
6412
6413         pObjectInfo->NonPagedInfo = (AFSNonPagedObjectInfoCB *)AFSExAllocatePoolWithTag( NonPagedPool,
6414                                                                                          sizeof( AFSNonPagedObjectInfoCB),
6415                                                                                          AFS_NP_OBJECT_INFO_TAG);
6416
6417         if( pObjectInfo->NonPagedInfo == NULL)
6418         {
6419
6420             AFSExFreePoolWithTag( pObjectInfo, AFS_OBJECT_INFO_TAG);
6421
6422             try_return( pObjectInfo = NULL);
6423         }
6424
6425         ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6426
6427         ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
6428
6429         pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock = &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock;
6430
6431         pObjectInfo->VolumeCB = ParentObjectInfo->VolumeCB;
6432
6433         pObjectInfo->ParentObjectInformation = ParentObjectInfo;
6434
6435         if( ParentObjectInfo != NULL)
6436         {
6437             lCount = AFSObjectInfoIncrement( ParentObjectInfo);
6438         }
6439
6440         //
6441         // Initialize the access time
6442         //
6443
6444         KeQueryTickCount( &pObjectInfo->LastAccessCount);
6445
6446         if( HashIndex != 0)
6447         {
6448
6449             //
6450             // Insert the entry into the object tree and list
6451             //
6452
6453             pObjectInfo->TreeEntry.HashIndex = HashIndex;
6454
6455             if( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead == NULL)
6456             {
6457
6458                 ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead = &pObjectInfo->TreeEntry;
6459             }
6460             else
6461             {
6462
6463                 ntStatus = AFSInsertHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
6464                                                &pObjectInfo->TreeEntry);
6465
6466                 ASSERT( NT_SUCCESS( ntStatus));
6467             }
6468
6469             //
6470             // And the object list in the volume
6471             //
6472
6473             if( ParentObjectInfo->VolumeCB->ObjectInfoListHead == NULL)
6474             {
6475
6476                 ParentObjectInfo->VolumeCB->ObjectInfoListHead = pObjectInfo;
6477             }
6478             else
6479             {
6480
6481                 ParentObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = (void *)pObjectInfo;
6482
6483                 pObjectInfo->ListEntry.bLink = (void *)ParentObjectInfo->VolumeCB->ObjectInfoListTail;
6484             }
6485
6486             ParentObjectInfo->VolumeCB->ObjectInfoListTail = pObjectInfo;
6487
6488             //
6489             // Indicate the object is in the hash tree and linked list in the volume
6490             //
6491
6492             SetFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE | AFS_OBJECT_INSERTED_VOLUME_LIST);
6493         }
6494
6495 try_exit:
6496
6497         NOTHING;
6498     }
6499
6500     return pObjectInfo;
6501 }
6502
6503 LONG
6504 AFSObjectInfoIncrement( IN AFSObjectInfoCB *ObjectInfo)
6505 {
6506
6507     LONG lCount;
6508
6509     if ( ObjectInfo->ObjectReferenceCount == 0)
6510     {
6511
6512         AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6513                         TRUE);
6514
6515         lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6516     }
6517     else
6518     {
6519
6520         AFSAcquireShared( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6521                           TRUE);
6522
6523         lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6524
6525         if ( lCount == 1)
6526         {
6527
6528             AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6529
6530             AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6531                             TRUE);
6532         }
6533     }
6534
6535     AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6536
6537     return lCount;
6538 }
6539
6540 LONG
6541 AFSObjectInfoDecrement( IN AFSObjectInfoCB *ObjectInfo)
6542 {
6543
6544     LONG lCount;
6545
6546     AFSAcquireShared( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6547                       TRUE);
6548
6549     lCount = InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);
6550
6551     if ( lCount == 0)
6552     {
6553
6554         lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6555
6556         AFSReleaseResource(&ObjectInfo->NonPagedInfo->ObjectInfoLock);
6557
6558         AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6559                         TRUE);
6560
6561         lCount = InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);
6562     }
6563
6564     AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6565
6566     return lCount;
6567 }
6568
6569
6570
6571 void
6572 AFSDeleteObjectInfo( IN AFSObjectInfoCB *ObjectInfo)
6573 {
6574
6575     BOOLEAN bAcquiredTreeLock = FALSE;
6576     LONG lCount;
6577
6578     if ( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_ROOT_VOLUME))
6579     {
6580
6581         //
6582         // AFSDeleteObjectInfo should never be called on the ObjectInformationCB
6583         // embedded in the VolumeCB.
6584         //
6585
6586         ASSERT( TRUE);
6587
6588         return;
6589     }
6590
6591     if( !ExIsResourceAcquiredExclusiveLite( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock))
6592     {
6593
6594         ASSERT( !ExIsResourceAcquiredLite( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock));
6595
6596         AFSAcquireExcl( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
6597                         TRUE);
6598
6599         bAcquiredTreeLock = TRUE;
6600     }
6601
6602     //
6603     // Remove it from the tree and list if it was inserted
6604     //
6605
6606     if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
6607     {
6608
6609         AFSRemoveHashEntry( &ObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
6610                             &ObjectInfo->TreeEntry);
6611     }
6612
6613     if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_INSERTED_VOLUME_LIST))
6614     {
6615
6616         if( ObjectInfo->ListEntry.fLink == NULL)
6617         {
6618
6619             ObjectInfo->VolumeCB->ObjectInfoListTail = (AFSObjectInfoCB *)ObjectInfo->ListEntry.bLink;
6620
6621             if( ObjectInfo->VolumeCB->ObjectInfoListTail != NULL)
6622             {
6623
6624                 ObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = NULL;
6625             }
6626         }
6627         else
6628         {
6629
6630             ((AFSObjectInfoCB *)(ObjectInfo->ListEntry.fLink))->ListEntry.bLink = ObjectInfo->ListEntry.bLink;
6631         }
6632
6633         if( ObjectInfo->ListEntry.bLink == NULL)
6634         {
6635
6636             ObjectInfo->VolumeCB->ObjectInfoListHead = (AFSObjectInfoCB *)ObjectInfo->ListEntry.fLink;
6637
6638             if( ObjectInfo->VolumeCB->ObjectInfoListHead != NULL)
6639             {
6640
6641                 ObjectInfo->VolumeCB->ObjectInfoListHead->ListEntry.bLink = NULL;
6642             }
6643         }
6644         else
6645         {
6646
6647             ((AFSObjectInfoCB *)(ObjectInfo->ListEntry.bLink))->ListEntry.fLink = ObjectInfo->ListEntry.fLink;
6648         }
6649     }
6650
6651     if( ObjectInfo->ParentObjectInformation != NULL)
6652     {
6653
6654         lCount = AFSObjectInfoDecrement( ObjectInfo->ParentObjectInformation);
6655     }
6656
6657     if( bAcquiredTreeLock)
6658     {
6659
6660         AFSReleaseResource( ObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
6661     }
6662
6663     //
6664     // Release the fid in the service
6665     //
6666
6667     if( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_HELD_IN_SERVICE))
6668     {
6669
6670         AFSReleaseFid( &ObjectInfo->FileId);
6671     }
6672
6673     ExDeleteResourceLite( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6674
6675     ExDeleteResourceLite( &ObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6676
6677     AFSExFreePoolWithTag( ObjectInfo->NonPagedInfo, AFS_NP_OBJECT_INFO_TAG);
6678
6679     AFSExFreePoolWithTag( ObjectInfo, AFS_OBJECT_INFO_TAG);
6680
6681     return;
6682 }
6683
6684 NTSTATUS
6685 AFSEvaluateRootEntry( IN AFSDirectoryCB *DirectoryCB,
6686                       OUT AFSDirectoryCB **TargetDirEntry)
6687 {
6688
6689     NTSTATUS ntStatus = STATUS_SUCCESS;
6690     AFSDirEnumEntry *pDirEntry = NULL;
6691     UNICODE_STRING uniFullPathName = {0};
6692     AFSNameArrayHdr    *pNameArray = NULL;
6693     AFSVolumeCB *pVolumeCB = NULL;
6694     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
6695     WCHAR *pwchBuffer = NULL;
6696     UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
6697     ULONG ulNameDifference = 0;
6698     GUID    stAuthGroup;
6699     LONG lCount;
6700
6701     __Enter
6702     {
6703
6704         ntStatus = AFSRetrieveValidAuthGroup( NULL,
6705                                               DirectoryCB->ObjectInformation,
6706                                               FALSE,
6707                                               &stAuthGroup);
6708
6709         if( !NT_SUCCESS( ntStatus))
6710         {
6711             try_return( ntStatus);
6712         }
6713
6714         //
6715         // Retrieve a target name for the entry
6716         //
6717
6718         AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
6719                           TRUE);
6720
6721         if( DirectoryCB->NameInformation.TargetName.Length == 0)
6722         {
6723
6724             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6725
6726             ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
6727                                               &stAuthGroup,
6728                                               FALSE,
6729                                               &pDirEntry);
6730
6731             if( !NT_SUCCESS( ntStatus) ||
6732                 pDirEntry->TargetNameLength == 0)
6733             {
6734
6735                 if( pDirEntry != NULL)
6736                 {
6737
6738                     ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
6739                 }
6740
6741                 try_return( ntStatus);
6742             }
6743
6744             AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
6745                             TRUE);
6746
6747             if( DirectoryCB->NameInformation.TargetName.Length == 0)
6748             {
6749
6750                 //
6751                 // Update the target name
6752                 //
6753
6754                 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
6755                                                 &DirectoryCB->Flags,
6756                                                 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
6757                                                 (USHORT)pDirEntry->TargetNameLength);
6758
6759                 if( !NT_SUCCESS( ntStatus))
6760                 {
6761
6762                     AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6763
6764                     try_return( ntStatus);
6765                 }
6766             }
6767
6768             AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
6769         }
6770
6771         //
6772         // Need to pass the full path in for parsing.
6773         //
6774
6775         uniFullPathName.Length = 0;
6776         uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
6777
6778         uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6779                                                                     uniFullPathName.MaximumLength,
6780                                                                     AFS_NAME_BUFFER_EIGHT_TAG);
6781
6782         if( uniFullPathName.Buffer == NULL)
6783         {
6784
6785             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6786
6787             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6788         }
6789
6790         pwchBuffer = uniFullPathName.Buffer;
6791
6792         RtlZeroMemory( uniFullPathName.Buffer,
6793                        uniFullPathName.MaximumLength);
6794
6795         RtlCopyMemory( uniFullPathName.Buffer,
6796                        DirectoryCB->NameInformation.TargetName.Buffer,
6797                        DirectoryCB->NameInformation.TargetName.Length);
6798
6799         uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6800
6801         //
6802         // This name should begin with the \afs server so parse it off and chech it
6803         //
6804
6805         FsRtlDissectName( uniFullPathName,
6806                           &uniComponentName,
6807                           &uniRemainingPath);
6808
6809         if( RtlCompareUnicodeString( &uniComponentName,
6810                                      &AFSServerName,
6811                                      TRUE) != 0)
6812         {
6813
6814             //
6815             // Try evaluating the full path
6816             //
6817
6818             uniFullPathName.Buffer = pwchBuffer;
6819
6820             uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6821
6822             uniFullPathName.MaximumLength = uniFullPathName.Length;
6823         }
6824         else
6825         {
6826
6827             uniFullPathName = uniRemainingPath;
6828         }
6829
6830         uniParsedName = uniFullPathName;
6831
6832         ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
6833
6834         AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6835
6836         //
6837         // Our name array
6838         //
6839
6840         pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
6841                                        0);
6842
6843         if( pNameArray == NULL)
6844         {
6845
6846             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6847         }
6848
6849         pVolumeCB = AFSGlobalRoot;
6850
6851         pParentDirEntry = AFSGlobalRoot->DirectoryCB;
6852
6853         lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
6854
6855         AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6856                       AFS_TRACE_LEVEL_VERBOSE,
6857                       "AFSEvaluateRootEntry Increment count on volume %p Cnt %d\n",
6858                       pVolumeCB,
6859                       lCount);
6860
6861         lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
6862
6863         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6864                       AFS_TRACE_LEVEL_VERBOSE,
6865                       "AFSEvaluateRootEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
6866                       &pParentDirEntry->NameInformation.FileName,
6867                       pParentDirEntry,
6868                       NULL,
6869                       lCount);
6870
6871         ntStatus = AFSLocateNameEntry( NULL,
6872                                        NULL,
6873                                        &uniFullPathName,
6874                                        &uniParsedName,
6875                                        pNameArray,
6876                                        0,
6877                                        &pVolumeCB,
6878                                        &pParentDirEntry,
6879                                        &pDirectoryEntry,
6880                                        NULL);
6881
6882         if( !NT_SUCCESS( ntStatus) ||
6883             ntStatus == STATUS_REPARSE)
6884         {
6885
6886             //
6887             // The volume lock was released on failure or reparse above
6888             // Except for STATUS_OBJECT_NAME_NOT_FOUND
6889             //
6890
6891             if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
6892             {
6893
6894                 if( pVolumeCB != NULL)
6895                 {
6896
6897                     lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6898
6899                     AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6900                                   AFS_TRACE_LEVEL_VERBOSE,
6901                                   "AFSEvaluateRootEntry Decrement count on volume %p Cnt %d\n",
6902                                   pVolumeCB,
6903                                   lCount);
6904                 }
6905
6906                 if( pDirectoryEntry != NULL)
6907                 {
6908
6909                     lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
6910
6911                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6912                                   AFS_TRACE_LEVEL_VERBOSE,
6913                                   "AFSEvaluateRootEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6914                                   &pDirectoryEntry->NameInformation.FileName,
6915                                   pDirectoryEntry,
6916                                   NULL,
6917                                   lCount);
6918
6919                     ASSERT( lCount >= 0);
6920                 }
6921                 else
6922                 {
6923
6924                     lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
6925
6926                     AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6927                                   AFS_TRACE_LEVEL_VERBOSE,
6928                                   "AFSEvaluateRootEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
6929                                   &pParentDirEntry->NameInformation.FileName,
6930                                   pParentDirEntry,
6931                                   NULL,
6932                                   lCount);
6933
6934                     ASSERT( lCount >= 0);
6935                 }
6936             }
6937
6938             pVolumeCB = NULL;
6939
6940             try_return( ntStatus);
6941         }
6942
6943         //
6944         // Pass back the target dir entry for this request
6945         //
6946
6947         *TargetDirEntry = pDirectoryEntry;
6948
6949 try_exit:
6950
6951         if( pDirEntry != NULL)
6952         {
6953
6954             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
6955         }
6956
6957         if( pVolumeCB != NULL)
6958         {
6959
6960             lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
6961
6962             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6963                           AFS_TRACE_LEVEL_VERBOSE,
6964                           "AFSEvaluateRootEntry Decrement2 count on volume %p Cnt %d\n",
6965                           pVolumeCB,
6966                           lCount);
6967         }
6968
6969         if( pNameArray != NULL)
6970         {
6971
6972             AFSFreeNameArray( pNameArray);
6973         }
6974
6975         if( pwchBuffer != NULL)
6976         {
6977
6978             //
6979             // Always free the buffer that we allocated as AFSLocateNameEntry
6980             // will not free it.  If uniFullPathName.Buffer was allocated by
6981             // AFSLocateNameEntry, then we must free that as well.
6982             // Check that the uniFullPathName.Buffer in the string is not the same
6983             // offset by the length of the server name
6984             //
6985
6986             if( uniFullPathName.Length > 0 &&
6987                 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
6988             {
6989
6990                 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
6991             }
6992
6993             AFSExFreePoolWithTag( pwchBuffer, 0);
6994         }
6995     }
6996
6997     return ntStatus;
6998 }
6999
7000 NTSTATUS
7001 AFSCleanupFcb( IN AFSFcb *Fcb,
7002                IN BOOLEAN ForceFlush)
7003 {
7004
7005     NTSTATUS ntStatus = STATUS_SUCCESS;
7006     AFSDeviceExt *pRDRDeviceExt = NULL, *pControlDeviceExt = NULL;
7007     LARGE_INTEGER liTime;
7008     IO_STATUS_BLOCK stIoStatus;
7009
7010     __Enter
7011     {
7012
7013         pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
7014
7015         pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
7016
7017         if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
7018         {
7019
7020             if( !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) &&
7021                 !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
7022             {
7023
7024                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
7025                               AFS_TRACE_LEVEL_VERBOSE,
7026                               "AFSCleanupEntry Acquiring Fcb lock %p SHARED %08lX\n",
7027                               &Fcb->NPFcb->Resource,
7028                               PsGetCurrentThread());
7029
7030                 AFSAcquireShared( &Fcb->NPFcb->Resource,
7031                                   TRUE);
7032
7033                 if( Fcb->OpenReferenceCount > 0)
7034                 {
7035
7036                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
7037                                   AFS_TRACE_LEVEL_VERBOSE,
7038                                   "AFSCleanupEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
7039                                   &Fcb->NPFcb->SectionObjectResource,
7040                                   PsGetCurrentThread());
7041
7042                     AFSAcquireExcl( &Fcb->NPFcb->SectionObjectResource,
7043                                     TRUE);
7044
7045                     __try
7046                     {
7047
7048                         CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
7049                                       NULL,
7050                                       0,
7051                                       &stIoStatus);
7052
7053                         if( !NT_SUCCESS( stIoStatus.Status))
7054                         {
7055
7056                             AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
7057                                           AFS_TRACE_LEVEL_ERROR,
7058                                           "AFSCleanupFcb CcFlushCache [1] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
7059                                           Fcb->ObjectInformation->FileId.Cell,
7060                                           Fcb->ObjectInformation->FileId.Volume,
7061                                           Fcb->ObjectInformation->FileId.Vnode,
7062                                           Fcb->ObjectInformation->FileId.Unique,
7063                                           stIoStatus.Status,
7064                                           stIoStatus.Information);
7065
7066                             ntStatus = stIoStatus.Status;
7067                         }
7068
7069                         if (  Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
7070                         {
7071
7072                             if ( !CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
7073                                                        NULL,
7074                                                        0,
7075                                                        FALSE))
7076                             {
7077
7078                                 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
7079                                               AFS_TRACE_LEVEL_WARNING,
7080                                               "AFSCleanupFcb CcPurgeCacheSection [1] failure FID %08lX-%08lX-%08lX-%08lX\n",
7081                                               Fcb->ObjectInformation->FileId.Cell,
7082                                               Fcb->ObjectInformation->FileId.Volume,
7083                                               Fcb->ObjectInformation->FileId.Vnode,
7084                                               Fcb->ObjectInformation->FileId.Unique);
7085
7086                                 SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
7087                             }
7088                         }
7089                     }
7090                     __except( EXCEPTION_EXECUTE_HANDLER)
7091                     {
7092
7093                         ntStatus = GetExceptionCode();
7094
7095                         AFSDbgLogMsg( 0,
7096                                       0,
7097                                       "EXCEPTION - AFSCleanupFcb Cc [1] FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
7098                                       Fcb->ObjectInformation->FileId.Cell,
7099                                       Fcb->ObjectInformation->FileId.Volume,
7100                                       Fcb->ObjectInformation->FileId.Vnode,
7101                                       Fcb->ObjectInformation->FileId.Unique,
7102                                       ntStatus);
7103
7104                         SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
7105                     }
7106
7107                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
7108                                   AFS_TRACE_LEVEL_VERBOSE,
7109                                   "AFSCleanupFcb Releasing Fcb SectionObject lock %p EXCL %08lX\n",
7110                                   &Fcb->NPFcb->SectionObjectResource,
7111                                   PsGetCurrentThread());
7112
7113                     AFSReleaseResource( &Fcb->NPFcb->SectionObjectResource);
7114                 }
7115
7116                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
7117                               AFS_TRACE_LEVEL_VERBOSE,
7118                               "AFSCleanupEntry Releasing Fcb lock %p SHARED %08lX\n",
7119                               &Fcb->NPFcb->Resource,
7120                               PsGetCurrentThread());
7121
7122                 AFSReleaseResource( &Fcb->NPFcb->Resource);
7123
7124                 //
7125                 // Wait for any currently running flush or release requests to complete
7126                 //
7127
7128                 AFSWaitOnQueuedFlushes( Fcb);
7129
7130                 //
7131                 // Now perform another flush on the file
7132                 //
7133
7134                 if( !NT_SUCCESS( AFSFlushExtents( Fcb,
7135                                                   NULL)))
7136                 {
7137
7138                     AFSReleaseExtentsWithFlush( Fcb,
7139                                                 NULL,
7140                                                 TRUE);
7141                 }
7142             }
7143
7144             if( Fcb->OpenReferenceCount == 0 ||
7145                 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
7146                 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
7147             {
7148
7149                 AFSTearDownFcbExtents( Fcb,
7150                                        NULL);
7151             }
7152
7153             try_return( ntStatus);
7154         }
7155
7156         KeQueryTickCount( &liTime);
7157
7158         //
7159         // First up are there dirty extents in the cache to flush?
7160         //
7161
7162         if( BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
7163             BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
7164         {
7165
7166             //
7167             // The file has been marked as invalid.  Dump it
7168             //
7169
7170             AFSTearDownFcbExtents( Fcb,
7171                                    NULL);
7172         }
7173         else if( ForceFlush ||
7174             ( ( Fcb->Specific.File.ExtentsDirtyCount ||
7175                 Fcb->Specific.File.ExtentCount) &&
7176               (liTime.QuadPart - Fcb->Specific.File.LastServerFlush.QuadPart)
7177                                                     >= pControlDeviceExt->Specific.Control.FcbFlushTimeCount.QuadPart))
7178         {
7179             if( !NT_SUCCESS( AFSFlushExtents( Fcb,
7180                                               NULL)) &&
7181                 Fcb->OpenReferenceCount == 0)
7182             {
7183
7184                 AFSReleaseExtentsWithFlush( Fcb,
7185                                             NULL,
7186                                             TRUE);
7187             }
7188         }
7189
7190         //
7191         // If there are extents and they haven't been used recently *and*
7192         // are not being used
7193         //
7194
7195         if( ( ForceFlush ||
7196               ( 0 != Fcb->Specific.File.ExtentCount &&
7197                 0 != Fcb->Specific.File.LastExtentAccess.QuadPart &&
7198                 (liTime.QuadPart - Fcb->Specific.File.LastExtentAccess.QuadPart) >=
7199                                         (AFS_SERVER_PURGE_SLEEP * pControlDeviceExt->Specific.Control.FcbPurgeTimeCount.QuadPart))))
7200         {
7201
7202             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
7203                           AFS_TRACE_LEVEL_VERBOSE,
7204                           "AFSCleanupFcb Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
7205                           &Fcb->NPFcb->SectionObjectResource,
7206                           PsGetCurrentThread());
7207
7208             if ( AFSAcquireExcl( &Fcb->NPFcb->SectionObjectResource, ForceFlush))
7209             {
7210
7211                 __try
7212                 {
7213
7214                     CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
7215                                   NULL,
7216                                   0,
7217                                   &stIoStatus);
7218
7219                     if( !NT_SUCCESS( stIoStatus.Status))
7220                     {
7221
7222                         AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
7223                                       AFS_TRACE_LEVEL_ERROR,
7224                                       "AFSCleanupFcb CcFlushCache [2] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
7225                                       Fcb->ObjectInformation->FileId.Cell,
7226                                       Fcb->ObjectInformation->FileId.Volume,
7227                                       Fcb->ObjectInformation->FileId.Vnode,
7228                                       Fcb->ObjectInformation->FileId.Unique,
7229                                       stIoStatus.Status,
7230                                       stIoStatus.Information);
7231
7232                         ntStatus = stIoStatus.Status;
7233                     }
7234
7235                     if( ForceFlush &&
7236                         Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
7237                     {
7238
7239                         if ( !CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
7240                                                    NULL,
7241                                                    0,
7242                                                    FALSE))
7243                         {
7244
7245                             AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
7246                                           AFS_TRACE_LEVEL_WARNING,
7247                                           "AFSCleanupFcb CcPurgeCacheSection [2] failure FID %08lX-%08lX-%08lX-%08lX\n",
7248                                           Fcb->ObjectInformation->FileId.Cell,
7249                                           Fcb->ObjectInformation->FileId.Volume,
7250                                           Fcb->ObjectInformation->FileId.Vnode,
7251                                           Fcb->ObjectInformation->FileId.Unique);
7252
7253                             SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
7254                         }
7255                     }
7256                 }
7257                 __except( EXCEPTION_EXECUTE_HANDLER)
7258                 {
7259
7260                     ntStatus = GetExceptionCode();
7261
7262                     AFSDbgLogMsg( 0,
7263                                   0,
7264                                   "EXCEPTION - AFSCleanupFcb Cc [2] FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
7265                                   Fcb->ObjectInformation->FileId.Cell,
7266                                   Fcb->ObjectInformation->FileId.Volume,
7267                                   Fcb->ObjectInformation->FileId.Vnode,
7268                                   Fcb->ObjectInformation->FileId.Unique,
7269                                   ntStatus);
7270                 }
7271
7272                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
7273                               AFS_TRACE_LEVEL_VERBOSE,
7274                               "AFSCleanupFcb Releasing Fcb SectionObject lock %p EXCL %08lX\n",
7275                               &Fcb->NPFcb->SectionObjectResource,
7276                               PsGetCurrentThread());
7277
7278                 AFSReleaseResource( &Fcb->NPFcb->SectionObjectResource);
7279
7280                 if( Fcb->OpenReferenceCount <= 0)
7281                 {
7282
7283                     //
7284                     // Tear em down we'll not be needing them again
7285                     //
7286
7287                     AFSTearDownFcbExtents( Fcb,
7288                                            NULL);
7289                 }
7290             }
7291             else
7292             {
7293
7294                 ntStatus = STATUS_RETRY;
7295             }
7296         }
7297
7298 try_exit:
7299
7300         NOTHING;
7301     }
7302
7303     return ntStatus;
7304 }
7305
7306 NTSTATUS
7307 AFSUpdateDirEntryName( IN AFSDirectoryCB *DirectoryCB,
7308                        IN UNICODE_STRING *NewFileName)
7309 {
7310
7311     NTSTATUS ntStatus = STATUS_SUCCESS;
7312     WCHAR *pTmpBuffer = NULL;
7313
7314     __Enter
7315     {
7316
7317         if( NewFileName->Length > DirectoryCB->NameInformation.FileName.Length)
7318         {
7319
7320             if( BooleanFlagOn( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
7321             {
7322
7323                 AFSExFreePoolWithTag( DirectoryCB->NameInformation.FileName.Buffer, 0);
7324
7325                 ClearFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
7326
7327                 DirectoryCB->NameInformation.FileName.Buffer = NULL;
7328             }
7329
7330             //
7331             // OK, we need to allocate a new name buffer
7332             //
7333
7334             pTmpBuffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
7335                                                             NewFileName->Length,
7336                                                             AFS_NAME_BUFFER_NINE_TAG);
7337
7338             if( pTmpBuffer == NULL)
7339             {
7340
7341                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7342             }
7343
7344             DirectoryCB->NameInformation.FileName.Buffer = pTmpBuffer;
7345
7346             DirectoryCB->NameInformation.FileName.MaximumLength = NewFileName->Length;
7347
7348             SetFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
7349         }
7350
7351         DirectoryCB->NameInformation.FileName.Length = NewFileName->Length;
7352
7353         RtlCopyMemory( DirectoryCB->NameInformation.FileName.Buffer,
7354                        NewFileName->Buffer,
7355                        NewFileName->Length);
7356
7357 try_exit:
7358
7359         NOTHING;
7360     }
7361
7362     return ntStatus;
7363 }
7364
7365 NTSTATUS
7366 AFSReadCacheFile( IN void *ReadBuffer,
7367                   IN LARGE_INTEGER *ReadOffset,
7368                   IN ULONG RequestedDataLength,
7369                   IN OUT PULONG BytesRead)
7370 {
7371
7372     NTSTATUS            ntStatus = STATUS_SUCCESS;
7373     PIRP                pIrp = NULL;
7374     KEVENT              kEvent;
7375     PIO_STACK_LOCATION  pIoStackLocation = NULL;
7376     DEVICE_OBJECT      *pTargetDeviceObject = NULL;
7377     FILE_OBJECT        *pCacheFileObject = NULL;
7378
7379     __Enter
7380     {
7381
7382         pCacheFileObject = AFSReferenceCacheFileObject();
7383
7384         if( pCacheFileObject == NULL)
7385         {
7386             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
7387         }
7388
7389         pTargetDeviceObject = IoGetRelatedDeviceObject( pCacheFileObject);
7390
7391         //
7392         // Initialize the event
7393         //
7394
7395         KeInitializeEvent( &kEvent,
7396                            SynchronizationEvent,
7397                            FALSE);
7398
7399         //
7400         // Allocate an irp for this request.  This could also come from a
7401         // private pool, for instance.
7402         //
7403
7404         pIrp = IoAllocateIrp( pTargetDeviceObject->StackSize,
7405                               FALSE);
7406
7407         if( pIrp == NULL)
7408         {
7409
7410             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7411         }
7412
7413         //
7414         // Build the IRP's main body
7415         //
7416
7417         pIrp->UserBuffer = ReadBuffer;
7418
7419         pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
7420         pIrp->RequestorMode = KernelMode;
7421         pIrp->Flags |= IRP_READ_OPERATION;
7422
7423         //
7424         // Set up the I/O stack location.
7425         //
7426
7427         pIoStackLocation = IoGetNextIrpStackLocation( pIrp);
7428         pIoStackLocation->MajorFunction = IRP_MJ_READ;
7429         pIoStackLocation->DeviceObject = pTargetDeviceObject;
7430         pIoStackLocation->FileObject = pCacheFileObject;
7431         pIoStackLocation->Parameters.Read.Length = RequestedDataLength;
7432
7433         pIoStackLocation->Parameters.Read.ByteOffset.QuadPart = ReadOffset->QuadPart;
7434
7435         //
7436         // Set the completion routine.
7437         //
7438
7439         IoSetCompletionRoutine( pIrp,
7440                                 AFSIrpComplete,
7441                                 &kEvent,
7442                                 TRUE,
7443                                 TRUE,
7444                                 TRUE);
7445
7446         //
7447         // Send it to the FSD
7448         //
7449
7450         ntStatus = IoCallDriver( pTargetDeviceObject,
7451                                  pIrp);
7452
7453         if( NT_SUCCESS( ntStatus))
7454         {
7455
7456             //
7457             // Wait for the I/O
7458             //
7459
7460             ntStatus = KeWaitForSingleObject( &kEvent,
7461                                               Executive,
7462                                               KernelMode,
7463                                               FALSE,
7464                                               0);
7465
7466             if( NT_SUCCESS( ntStatus))
7467             {
7468
7469                 ntStatus = pIrp->IoStatus.Status;
7470
7471                 *BytesRead = (ULONG)pIrp->IoStatus.Information;
7472             }
7473         }
7474
7475 try_exit:
7476
7477         if( pCacheFileObject != NULL)
7478         {
7479             AFSReleaseCacheFileObject( pCacheFileObject);
7480         }
7481
7482         if( pIrp != NULL)
7483         {
7484
7485             if( pIrp->MdlAddress != NULL)
7486             {
7487
7488                 if( FlagOn( pIrp->MdlAddress->MdlFlags, MDL_PAGES_LOCKED))
7489                 {
7490
7491                     MmUnlockPages( pIrp->MdlAddress);
7492                 }
7493
7494                 IoFreeMdl( pIrp->MdlAddress);
7495             }
7496
7497             pIrp->MdlAddress = NULL;
7498
7499             //
7500             // Free the Irp
7501             //
7502
7503             IoFreeIrp( pIrp);
7504         }
7505     }
7506
7507     return ntStatus;
7508 }
7509
7510 NTSTATUS
7511 AFSIrpComplete( IN PDEVICE_OBJECT DeviceObject,
7512                 IN PIRP           Irp,
7513                 IN PVOID          Context)
7514 {
7515
7516     UNREFERENCED_PARAMETER(Irp);
7517     UNREFERENCED_PARAMETER(DeviceObject);
7518     KEVENT *pEvent = (KEVENT *)Context;
7519
7520     KeSetEvent( pEvent,
7521                 0,
7522                 FALSE);
7523
7524     return STATUS_MORE_PROCESSING_REQUIRED;
7525 }
7526
7527 BOOLEAN
7528 AFSIsDirectoryEmptyForDelete( IN AFSFcb *Fcb)
7529 {
7530
7531     BOOLEAN bIsEmpty = FALSE;
7532     AFSDirectoryCB *pDirEntry = NULL;
7533
7534     __Enter
7535     {
7536
7537         AFSAcquireShared( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
7538                           TRUE);
7539
7540         bIsEmpty = TRUE;
7541
7542         if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
7543         {
7544
7545             pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
7546
7547             while( pDirEntry != NULL)
7548             {
7549
7550                 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
7551                     !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
7552                 {
7553
7554                     bIsEmpty = FALSE;
7555
7556                     break;
7557                 }
7558
7559                 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
7560             }
7561
7562         }
7563
7564         AFSReleaseResource( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
7565     }
7566
7567     return bIsEmpty;
7568 }
7569
7570 void
7571 AFSRemoveNameEntry( IN AFSObjectInfoCB *ParentObjectInfo,
7572                     IN AFSDirectoryCB *DirEntry)
7573 {
7574
7575     NTSTATUS ntStatus = STATUS_SUCCESS;
7576
7577     __Enter
7578     {
7579
7580         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7581         {
7582
7583             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7584                           AFS_TRACE_LEVEL_VERBOSE,
7585                           "AFSRemoveNameEntry DE %p for %wZ has NOT_IN flag set\n",
7586                           DirEntry,
7587                           &DirEntry->NameInformation.FileName);
7588
7589             try_return( ntStatus);
7590         }
7591
7592         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
7593
7594         //
7595         // Remove the entry from the parent tree
7596         //
7597
7598         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7599                       AFS_TRACE_LEVEL_VERBOSE,
7600                       "AFSRemoveNameEntry DE %p for %wZ removing from case sensitive tree\n",
7601                       DirEntry,
7602                       &DirEntry->NameInformation.FileName);
7603
7604         AFSRemoveCaseSensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7605                                         DirEntry);
7606
7607         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7608                       AFS_TRACE_LEVEL_VERBOSE,
7609                       "AFSRemoveNameEntry DE %p for %wZ removing from case insensitive tree\n",
7610                       DirEntry,
7611                       &DirEntry->NameInformation.FileName);
7612
7613         AFSRemoveCaseInsensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
7614                                           DirEntry);
7615
7616         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
7617         {
7618
7619             //
7620             // From the short name tree
7621             //
7622
7623             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7624                           AFS_TRACE_LEVEL_VERBOSE,
7625                           "AFSRemoveNameEntry DE %p for %wZ removing from shortname tree\n",
7626                           DirEntry,
7627                           &DirEntry->NameInformation.FileName);
7628
7629             AFSRemoveShortNameDirEntry( &ParentObjectInfo->Specific.Directory.ShortNameTree,
7630                                         DirEntry);
7631
7632             ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
7633         }
7634
7635         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
7636                       AFS_TRACE_LEVEL_VERBOSE,
7637                       "AFSRemoveNameEntry DE %p for %wZ setting NOT_IN flag\n",
7638                       DirEntry,
7639                       &DirEntry->NameInformation.FileName);
7640
7641         SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
7642
7643         ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
7644
7645 try_exit:
7646
7647         NOTHING;
7648     }
7649
7650     return;
7651 }
7652
7653 LARGE_INTEGER
7654 AFSGetAuthenticationId()
7655 {
7656
7657     LARGE_INTEGER liAuthId = {0,0};
7658     NTSTATUS ntStatus = STATUS_SUCCESS;
7659     PACCESS_TOKEN hToken = NULL;
7660     PTOKEN_STATISTICS pTokenInfo = NULL;
7661     BOOLEAN bCopyOnOpen = FALSE;
7662     BOOLEAN bEffectiveOnly = FALSE;
7663     BOOLEAN bPrimaryToken = FALSE;
7664     SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
7665
7666     __Enter
7667     {
7668
7669         hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
7670                                                 &bCopyOnOpen,
7671                                                 &bEffectiveOnly,
7672                                                 &stImpersonationLevel);
7673
7674         if( hToken == NULL)
7675         {
7676
7677             hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
7678
7679             if( hToken == NULL)
7680             {
7681
7682                 AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7683                               AFS_TRACE_LEVEL_ERROR,
7684                               "AFSGetAuthenticationId Failed to retrieve impersonation or primary token\n");
7685
7686                 try_return( ntStatus);
7687             }
7688
7689             bPrimaryToken = TRUE;
7690         }
7691
7692         ntStatus = SeQueryInformationToken( hToken,
7693                                             TokenStatistics,
7694                                             (PVOID *)&pTokenInfo);
7695
7696         if( !NT_SUCCESS( ntStatus))
7697         {
7698
7699             AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7700                           AFS_TRACE_LEVEL_ERROR,
7701                           "AFSGetAuthenticationId Failed to retrieve information Status %08lX\n", ntStatus);
7702
7703             try_return( ntStatus);
7704         }
7705
7706         liAuthId.HighPart = pTokenInfo->AuthenticationId.HighPart;
7707         liAuthId.LowPart = pTokenInfo->AuthenticationId.LowPart;
7708
7709         AFSDbgLogMsg( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7710                       AFS_TRACE_LEVEL_VERBOSE,
7711                       "AFSGetAuthenticationId Successfully retrieved authentication ID %I64X\n",
7712                       liAuthId.QuadPart);
7713
7714 try_exit:
7715
7716         if( hToken != NULL)
7717         {
7718
7719             if( !bPrimaryToken)
7720             {
7721
7722                 PsDereferenceImpersonationToken( hToken);
7723             }
7724             else
7725             {
7726
7727                 PsDereferencePrimaryToken( hToken);
7728             }
7729         }
7730
7731         if( pTokenInfo != NULL)
7732         {
7733
7734             ExFreePool( pTokenInfo);    // Allocated by SeQueryInformationToken
7735         }
7736     }
7737
7738     return liAuthId;
7739 }
7740
7741 void
7742 AFSUnwindFileInfo( IN AFSFcb *Fcb,
7743                    IN AFSCcb *Ccb)
7744 {
7745
7746     UNREFERENCED_PARAMETER(Fcb);
7747     if( Ccb->FileUnwindInfo.FileAttributes != (ULONG)-1)
7748     {
7749         Ccb->DirectoryCB->ObjectInformation->FileAttributes = Ccb->FileUnwindInfo.FileAttributes;
7750     }
7751
7752     if( Ccb->FileUnwindInfo.CreationTime.QuadPart != (ULONGLONG)-1)
7753     {
7754         Ccb->DirectoryCB->ObjectInformation->CreationTime.QuadPart = Ccb->FileUnwindInfo.CreationTime.QuadPart;
7755     }
7756
7757     if( Ccb->FileUnwindInfo.LastAccessTime.QuadPart != (ULONGLONG)-1)
7758     {
7759         Ccb->DirectoryCB->ObjectInformation->LastAccessTime.QuadPart = Ccb->FileUnwindInfo.LastAccessTime.QuadPart;
7760     }
7761
7762     if( Ccb->FileUnwindInfo.LastWriteTime.QuadPart != (ULONGLONG)-1)
7763     {
7764         Ccb->DirectoryCB->ObjectInformation->LastWriteTime.QuadPart = Ccb->FileUnwindInfo.LastWriteTime.QuadPart;
7765     }
7766
7767     if( Ccb->FileUnwindInfo.ChangeTime.QuadPart != (ULONGLONG)-1)
7768     {
7769         Ccb->DirectoryCB->ObjectInformation->ChangeTime.QuadPart = Ccb->FileUnwindInfo.ChangeTime.QuadPart;
7770     }
7771
7772     return;
7773 }
7774
7775 BOOLEAN
7776 AFSValidateDirList( IN AFSObjectInfoCB *ObjectInfo)
7777 {
7778
7779     BOOLEAN bIsValid = TRUE;
7780     ULONG ulCount = 0;
7781     AFSDirectoryCB *pCurrentDirEntry = NULL, *pDirEntry = NULL;
7782
7783     pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
7784
7785     while( pCurrentDirEntry != NULL)
7786     {
7787
7788         if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
7789         {
7790             ulCount++;
7791
7792             if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7793             {
7794
7795                 pDirEntry = NULL;
7796
7797                 AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7798                                                 (ULONG)pCurrentDirEntry->CaseSensitiveTreeEntry.HashIndex,
7799                                                 &pDirEntry);
7800
7801                 if( pDirEntry == NULL)
7802                 {
7803                     DbgBreakPoint();
7804                 }
7805             }
7806         }
7807
7808         pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
7809     }
7810
7811     if( ulCount != (ULONG) ObjectInfo->Specific.Directory.DirectoryNodeCount)
7812     {
7813
7814         AFSPrint("AFSValidateDirList Count off Calc: %d Stored: %d\n",
7815                   ulCount,
7816                   ObjectInfo->Specific.Directory.DirectoryNodeCount);
7817
7818         ObjectInfo->Specific.Directory.DirectoryNodeCount = ulCount;
7819
7820         bIsValid = FALSE;
7821     }
7822
7823     return bIsValid;
7824 }
7825
7826 PFILE_OBJECT
7827 AFSReferenceCacheFileObject()
7828 {
7829
7830     AFSDeviceExt       *pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
7831     FILE_OBJECT        *pCacheFileObject = NULL;
7832
7833     AFSAcquireShared( &pRdrDevExt->Specific.RDR.CacheFileLock,
7834                       TRUE);
7835
7836     pCacheFileObject = pRdrDevExt->Specific.RDR.CacheFileObject;
7837
7838     if( pCacheFileObject != NULL)
7839     {
7840         ObReferenceObject( pCacheFileObject);
7841     }
7842
7843     AFSReleaseResource( &pRdrDevExt->Specific.RDR.CacheFileLock);
7844
7845     return pCacheFileObject;
7846 }
7847
7848 void
7849 AFSReleaseCacheFileObject( IN PFILE_OBJECT CacheFileObject)
7850 {
7851
7852     ASSERT( CacheFileObject != NULL);
7853
7854     ObDereferenceObject( CacheFileObject);
7855
7856     return;
7857 }
7858
7859 NTSTATUS
7860 AFSInitializeLibrary( IN AFSLibraryInitCB *LibraryInit)
7861 {
7862
7863     NTSTATUS ntStatus = STATUS_SUCCESS;
7864     AFSDeviceExt *pControlDevExt = NULL;
7865     ULONG ulTimeIncrement = 0;
7866     LONG lCount;
7867
7868     __Enter
7869     {
7870
7871         AFSControlDeviceObject = LibraryInit->AFSControlDeviceObject;
7872
7873         AFSRDRDeviceObject = LibraryInit->AFSRDRDeviceObject;
7874
7875         AFSServerName = LibraryInit->AFSServerName;
7876
7877         AFSMountRootName = LibraryInit->AFSMountRootName;
7878
7879         AFSDebugFlags = LibraryInit->AFSDebugFlags;
7880
7881         //
7882         // Callbacks in the framework
7883         //
7884
7885         AFSProcessRequest = LibraryInit->AFSProcessRequest;
7886
7887         AFSDbgLogMsg = LibraryInit->AFSDbgLogMsg;
7888
7889         AFSAddConnectionEx = LibraryInit->AFSAddConnectionEx;
7890
7891         AFSExAllocatePoolWithTag = LibraryInit->AFSExAllocatePoolWithTag;
7892
7893         AFSExFreePoolWithTag = LibraryInit->AFSExFreePoolWithTag;
7894
7895         AFSDumpTraceFilesFnc = LibraryInit->AFSDumpTraceFiles;
7896
7897         AFSRetrieveAuthGroupFnc = LibraryInit->AFSRetrieveAuthGroup;
7898
7899         AFSLibCacheManagerCallbacks = LibraryInit->AFSCacheManagerCallbacks;
7900
7901         if( LibraryInit->AFSCacheBaseAddress != NULL)
7902         {
7903
7904             SetFlag( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE);
7905
7906             AFSLibCacheBaseAddress = LibraryInit->AFSCacheBaseAddress;
7907
7908             AFSLibCacheLength = LibraryInit->AFSCacheLength;
7909         }
7910
7911         //
7912         // Initialize some flush parameters
7913         //
7914
7915         pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
7916
7917         ulTimeIncrement = KeQueryTimeIncrement();
7918
7919         pControlDevExt->Specific.Control.ObjectLifeTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_OBJECT_LIFETIME / (ULONGLONG)ulTimeIncrement);
7920         pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart = AFS_SERVER_PURGE_DELAY;
7921         pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart /= ulTimeIncrement;
7922         pControlDevExt->Specific.Control.FcbFlushTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_SERVER_FLUSH_DELAY / (ULONGLONG)ulTimeIncrement);
7923         pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_EXTENT_REQUEST_TIME/(ULONGLONG)ulTimeIncrement);
7924
7925         //
7926         // Initialize the global root entry
7927         //
7928
7929         ntStatus = AFSInitVolume( NULL,
7930                                   &LibraryInit->GlobalRootFid,
7931                                   &AFSGlobalRoot);
7932
7933         if( !NT_SUCCESS( ntStatus))
7934         {
7935
7936             AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
7937                           AFS_TRACE_LEVEL_ERROR,
7938                           "AFSInitializeLibrary AFSInitVolume failure %08lX\n",
7939                           ntStatus);
7940
7941             try_return( ntStatus);
7942         }
7943
7944         ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
7945                                    AFSGlobalRoot);
7946
7947         if( !NT_SUCCESS( ntStatus))
7948         {
7949
7950             AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
7951                           AFS_TRACE_LEVEL_ERROR,
7952                           "AFSInitializeLibrary AFSInitRootFcb failure %08lX\n",
7953                           ntStatus);
7954
7955             lCount = InterlockedDecrement( &AFSGlobalRoot->VolumeReferenceCount);
7956
7957             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7958                           AFS_TRACE_LEVEL_VERBOSE,
7959                           "AFSInitializeLibrary Increment count on volume %p Cnt %d\n",
7960                           AFSGlobalRoot,
7961                           lCount);
7962
7963             AFSReleaseResource( AFSGlobalRoot->VolumeLock);
7964
7965             try_return( ntStatus);
7966         }
7967
7968         //
7969         // Update the node type code to AFS_ROOT_ALL
7970         //
7971
7972         AFSGlobalRoot->ObjectInformation.Fcb->Header.NodeTypeCode = AFS_ROOT_ALL;
7973
7974         SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_ACTIVE_GLOBAL_ROOT);
7975
7976         //
7977         // Invalidate all known volumes since contact with the service and therefore
7978         // the file server was lost.
7979         //
7980
7981         AFSInvalidateAllVolumes();
7982
7983         //
7984         // Drop the locks acquired above
7985         //
7986
7987         AFSInitVolumeWorker( AFSGlobalRoot);
7988
7989         lCount = InterlockedDecrement( &AFSGlobalRoot->VolumeReferenceCount);
7990
7991         AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7992                       AFS_TRACE_LEVEL_VERBOSE,
7993                       "AFSInitializeLibrary Decrement count on volume %p Cnt %d\n",
7994                       AFSGlobalRoot,
7995                       lCount);
7996
7997         AFSReleaseResource( AFSGlobalRoot->VolumeLock);
7998
7999         AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Fcb->Header.Resource);
8000
8001 try_exit:
8002
8003         NOTHING;
8004     }
8005
8006     return ntStatus;
8007 }
8008
8009 NTSTATUS
8010 AFSCloseLibrary()
8011 {
8012
8013     NTSTATUS ntStatus = STATUS_SUCCESS;
8014     AFSDirectoryCB *pDirNode = NULL, *pLastDirNode = NULL;
8015
8016     __Enter
8017     {
8018
8019         if( AFSGlobalDotDirEntry != NULL)
8020         {
8021
8022             AFSDeleteObjectInfo( AFSGlobalDotDirEntry->ObjectInformation);
8023
8024             ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
8025
8026             ExFreePool( AFSGlobalDotDirEntry->NonPaged);
8027
8028             ExFreePool( AFSGlobalDotDirEntry);
8029
8030             AFSGlobalDotDirEntry = NULL;
8031         }
8032
8033         if( AFSGlobalDotDotDirEntry != NULL)
8034         {
8035
8036             AFSDeleteObjectInfo( AFSGlobalDotDotDirEntry->ObjectInformation);
8037
8038             ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
8039
8040             ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
8041
8042             ExFreePool( AFSGlobalDotDotDirEntry);
8043
8044             AFSGlobalDotDotDirEntry = NULL;
8045         }
8046
8047         if( AFSSpecialShareNames != NULL)
8048         {
8049
8050             pDirNode = AFSSpecialShareNames;
8051
8052             while( pDirNode != NULL)
8053             {
8054
8055                 pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
8056
8057                 AFSDeleteObjectInfo( pDirNode->ObjectInformation);
8058
8059                 ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
8060
8061                 ExFreePool( pDirNode->NonPaged);
8062
8063                 ExFreePool( pDirNode);
8064
8065                 pDirNode = pLastDirNode;
8066             }
8067
8068             AFSSpecialShareNames = NULL;
8069         }
8070     }
8071
8072     return ntStatus;
8073 }
8074
8075 NTSTATUS
8076 AFSDefaultLogMsg( IN ULONG Subsystem,
8077                   IN ULONG Level,
8078                   IN PCCH Format,
8079                   ...)
8080 {
8081
8082     UNREFERENCED_PARAMETER(Subsystem);
8083     UNREFERENCED_PARAMETER(Level);
8084     NTSTATUS ntStatus = STATUS_SUCCESS;
8085     va_list va_args;
8086     char chDebugBuffer[ 256];
8087
8088     __Enter
8089     {
8090
8091         va_start( va_args, Format);
8092
8093         ntStatus = RtlStringCbVPrintfA( chDebugBuffer,
8094                                         256,
8095                                         Format,
8096                                         va_args);
8097
8098         if( NT_SUCCESS( ntStatus))
8099         {
8100             DbgPrint( chDebugBuffer);
8101         }
8102
8103         va_end( va_args);
8104     }
8105
8106     return ntStatus;
8107 }
8108
8109 NTSTATUS
8110 AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
8111                     IN ULONG InputBufferLength,
8112                     IN AFSStatusInfoCB *StatusInfo,
8113                     OUT ULONG *ReturnLength)
8114 {
8115
8116     NTSTATUS ntStatus = STATUS_SUCCESS;
8117     AFSVolumeCB *pVolumeCB = NULL;
8118     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
8119     AFSObjectInfoCB *pObjectInfo = NULL;
8120     ULONGLONG   ullIndex = 0;
8121     UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName, uniParsedName;
8122     AFSNameArrayHdr *pNameArray = NULL;
8123     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
8124     LONG lCount;
8125
8126     __Enter
8127     {
8128
8129         //
8130         // If we are given a FID then look up the entry by that, otherwise
8131         // do it by name
8132         //
8133
8134         if( GetStatusInfo->FileID.Cell != 0 &&
8135             GetStatusInfo->FileID.Volume != 0 &&
8136             GetStatusInfo->FileID.Vnode != 0 &&
8137             GetStatusInfo->FileID.Unique != 0)
8138         {
8139
8140             AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
8141
8142             //
8143             // Locate the volume node
8144             //
8145
8146             ullIndex = AFSCreateHighIndex( &GetStatusInfo->FileID);
8147
8148             ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
8149                                            ullIndex,
8150                                            (AFSBTreeEntry **)&pVolumeCB);
8151
8152             if( pVolumeCB != NULL)
8153             {
8154
8155                 lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
8156
8157                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8158                               AFS_TRACE_LEVEL_VERBOSE,
8159                               "AFSGetObjectStatus Increment count on volume %p Cnt %d\n",
8160                               pVolumeCB,
8161                               lCount);
8162             }
8163
8164             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
8165
8166             if( !NT_SUCCESS( ntStatus) ||
8167                 pVolumeCB == NULL)
8168             {
8169                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8170             }
8171
8172             if( AFSIsVolumeFID( &GetStatusInfo->FileID))
8173             {
8174
8175                 pObjectInfo = &pVolumeCB->ObjectInformation;
8176
8177                 lCount = AFSObjectInfoIncrement( pObjectInfo);
8178
8179                 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
8180
8181                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8182                               AFS_TRACE_LEVEL_VERBOSE,
8183                               "AFSGetObjectStatus Decrement count on volume %p Cnt %d\n",
8184                               pVolumeCB,
8185                               lCount);
8186             }
8187             else
8188             {
8189
8190                 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
8191                                   TRUE);
8192
8193                 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
8194
8195                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8196                               AFS_TRACE_LEVEL_VERBOSE,
8197                               "AFSGetObjectStatus Decrement2 count on volume %p Cnt %d\n",
8198                               pVolumeCB,
8199                               lCount);
8200
8201                 ullIndex = AFSCreateLowIndex( &GetStatusInfo->FileID);
8202
8203                 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
8204                                                ullIndex,
8205                                                (AFSBTreeEntry **)&pObjectInfo);
8206
8207                 if( pObjectInfo != NULL)
8208                 {
8209
8210                     //
8211                     // Reference the node so it won't be torn down
8212                     //
8213
8214                     lCount = AFSObjectInfoIncrement( pObjectInfo);
8215
8216                     AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8217                                   AFS_TRACE_LEVEL_VERBOSE,
8218                                   "AFSGetObjectStatus Increment count on object %p Cnt %d\n",
8219                                   pObjectInfo,
8220                                   lCount);
8221                 }
8222
8223                 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
8224
8225                 if( !NT_SUCCESS( ntStatus) ||
8226                     pObjectInfo == NULL)
8227                 {
8228                     try_return( ntStatus = STATUS_INVALID_PARAMETER);
8229                 }
8230             }
8231         }
8232         else
8233         {
8234
8235             if( GetStatusInfo->FileNameLength == 0 ||
8236                 InputBufferLength < (ULONG)(FIELD_OFFSET( AFSGetStatusInfoCB, FileName) + GetStatusInfo->FileNameLength))
8237             {
8238                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8239             }
8240
8241             uniFullPathName.Length = GetStatusInfo->FileNameLength;
8242             uniFullPathName.MaximumLength = uniFullPathName.Length;
8243
8244             uniFullPathName.Buffer = (WCHAR *)GetStatusInfo->FileName;
8245
8246             //
8247             // This name should begin with the \afs server so parse it off and check it
8248             //
8249
8250             FsRtlDissectName( uniFullPathName,
8251                               &uniComponentName,
8252                               &uniRemainingPath);
8253
8254             if( RtlCompareUnicodeString( &uniComponentName,
8255                                          &AFSServerName,
8256                                          TRUE) != 0)
8257             {
8258                 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8259                               AFS_TRACE_LEVEL_ERROR,
8260                               "AFSGetObjectStatus Name %wZ contains invalid server name\n",
8261                               &uniFullPathName);
8262
8263                 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
8264             }
8265
8266             uniFullPathName = uniRemainingPath;
8267
8268             uniParsedName = uniFullPathName;
8269
8270             //
8271             // Our name array
8272             //
8273
8274             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
8275                                            0);
8276
8277             if( pNameArray == NULL)
8278             {
8279                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8280             }
8281
8282             pVolumeCB = AFSGlobalRoot;
8283
8284             pParentDirEntry = AFSGlobalRoot->DirectoryCB;
8285
8286             //
8287             // Increment the ref count on the volume and dir entry for correct processing below
8288             //
8289
8290             lCount = InterlockedIncrement( &pVolumeCB->VolumeReferenceCount);
8291
8292             AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8293                           AFS_TRACE_LEVEL_VERBOSE,
8294                           "AFSGetObjectStatus Increment2 count on volume %p Cnt %d\n",
8295                           pVolumeCB,
8296                           lCount);
8297
8298             lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
8299
8300             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8301                           AFS_TRACE_LEVEL_VERBOSE,
8302                           "AFSGetObjectStatus Increment count on %wZ DE %p Ccb %p Cnt %d\n",
8303                           &pParentDirEntry->NameInformation.FileName,
8304                           pParentDirEntry,
8305                           NULL,
8306                           lCount);
8307
8308             ntStatus = AFSLocateNameEntry( NULL,
8309                                            NULL,
8310                                            &uniFullPathName,
8311                                            &uniParsedName,
8312                                            pNameArray,
8313                                            AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL |
8314                                                         AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL,
8315                                            &pVolumeCB,
8316                                            &pParentDirEntry,
8317                                            &pDirectoryEntry,
8318                                            NULL);
8319
8320             if( !NT_SUCCESS( ntStatus) ||
8321                 ntStatus == STATUS_REPARSE)
8322             {
8323
8324                 //
8325                 // The volume lock was released on failure or reparse above
8326                 // Except for STATUS_OBJECT_NAME_NOT_FOUND
8327                 //
8328
8329                 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND)
8330                 {
8331
8332                     if( pVolumeCB != NULL)
8333                     {
8334
8335                         lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
8336
8337                         AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8338                                       AFS_TRACE_LEVEL_VERBOSE,
8339                                       "AFSGetObjectStatus Decrement3 count on volume %p Cnt %d\n",
8340                                       pVolumeCB,
8341                                       lCount);
8342                     }
8343
8344                     if( pDirectoryEntry != NULL)
8345                     {
8346
8347                         lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
8348
8349                         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8350                                       AFS_TRACE_LEVEL_VERBOSE,
8351                                       "AFSGetObjectStatus Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
8352                                       &pDirectoryEntry->NameInformation.FileName,
8353                                       pDirectoryEntry,
8354                                       NULL,
8355                                       lCount);
8356
8357                         ASSERT( lCount >= 0);
8358                     }
8359                     else
8360                     {
8361
8362                         lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
8363
8364                         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8365                                       AFS_TRACE_LEVEL_VERBOSE,
8366                                       "AFSGetObjectStatus Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
8367                                       &pParentDirEntry->NameInformation.FileName,
8368                                       pParentDirEntry,
8369                                       NULL,
8370                                       lCount);
8371
8372                         ASSERT( lCount >= 0);
8373                     }
8374                 }
8375
8376                 pVolumeCB = NULL;
8377
8378                 try_return( ntStatus);
8379             }
8380
8381             //
8382             // Remove the reference made above
8383             //
8384
8385             lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
8386
8387             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8388                           AFS_TRACE_LEVEL_VERBOSE,
8389                           "AFSGetObjectStatus Decrement3 count on %wZ DE %p Ccb %p Cnt %d\n",
8390                           &pDirectoryEntry->NameInformation.FileName,
8391                           pDirectoryEntry,
8392                           NULL,
8393                           lCount);
8394
8395             ASSERT( lCount >= 0);
8396
8397             pObjectInfo = pDirectoryEntry->ObjectInformation;
8398
8399             lCount = AFSObjectInfoIncrement( pObjectInfo);
8400
8401             if( pVolumeCB != NULL)
8402             {
8403
8404                 lCount = InterlockedDecrement( &pVolumeCB->VolumeReferenceCount);
8405
8406                 AFSDbgLogMsg( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8407                               AFS_TRACE_LEVEL_VERBOSE,
8408                               "AFSGetObjectStatus Decrement4 count on volume %p Cnt %d\n",
8409                               pVolumeCB,
8410                               lCount);
8411             }
8412         }
8413
8414         //
8415         // At this point we have an object info block, return the information
8416         //
8417
8418         StatusInfo->FileId = pObjectInfo->FileId;
8419
8420         StatusInfo->TargetFileId = pObjectInfo->TargetFileId;
8421
8422         StatusInfo->Expiration = pObjectInfo->Expiration;
8423
8424         StatusInfo->DataVersion = pObjectInfo->DataVersion;
8425
8426         StatusInfo->FileType = pObjectInfo->FileType;
8427
8428         StatusInfo->ObjectFlags = pObjectInfo->Flags;
8429
8430         StatusInfo->CreationTime = pObjectInfo->CreationTime;
8431
8432         StatusInfo->LastAccessTime = pObjectInfo->LastAccessTime;
8433
8434         StatusInfo->LastWriteTime = pObjectInfo->LastWriteTime;
8435
8436         StatusInfo->ChangeTime = pObjectInfo->ChangeTime;
8437
8438         StatusInfo->FileAttributes = pObjectInfo->FileAttributes;
8439
8440         StatusInfo->EndOfFile = pObjectInfo->EndOfFile;
8441
8442         StatusInfo->AllocationSize = pObjectInfo->AllocationSize;
8443
8444         StatusInfo->EaSize = pObjectInfo->EaSize;
8445
8446         StatusInfo->Links = pObjectInfo->Links;
8447
8448         //
8449         // Return the information length
8450         //
8451
8452         *ReturnLength = sizeof( AFSStatusInfoCB);
8453
8454 try_exit:
8455
8456         if( pObjectInfo != NULL)
8457         {
8458
8459             lCount = AFSObjectInfoDecrement( pObjectInfo);
8460         }
8461
8462         if( pNameArray != NULL)
8463         {
8464
8465             AFSFreeNameArray( pNameArray);
8466         }
8467     }
8468
8469     return ntStatus;
8470 }
8471
8472 NTSTATUS
8473 AFSCheckSymlinkAccess( IN AFSDirectoryCB *ParentDirectoryCB,
8474                        IN UNICODE_STRING *ComponentName)
8475 {
8476
8477     NTSTATUS ntStatus = STATUS_SUCCESS;
8478     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
8479     AFSDirectoryCB *pDirEntry = NULL;
8480     ULONG ulCRC = 0;
8481     LONG lCount;
8482
8483     __Enter
8484     {
8485
8486         //
8487         // Search for the entry in the parent
8488         //
8489
8490         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8491                       AFS_TRACE_LEVEL_VERBOSE_2,
8492                       "AFSCheckSymlinkAccess Searching for entry %wZ case sensitive\n",
8493                       ComponentName);
8494
8495         ulCRC = AFSGenerateCRC( ComponentName,
8496                                 FALSE);
8497
8498         AFSAcquireShared( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
8499                           TRUE);
8500
8501         AFSLocateCaseSensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
8502                                         ulCRC,
8503                                         &pDirEntry);
8504
8505         if( pDirEntry == NULL)
8506         {
8507
8508             //
8509             // Missed so perform a case insensitive lookup
8510             //
8511
8512             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8513                           AFS_TRACE_LEVEL_VERBOSE_2,
8514                           "AFSCheckSymlinkAccess Searching for entry %wZ case insensitive\n",
8515                           ComponentName);
8516
8517             ulCRC = AFSGenerateCRC( ComponentName,
8518                                     TRUE);
8519
8520             AFSLocateCaseInsensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
8521                                               ulCRC,
8522                                               &pDirEntry);
8523
8524             if( pDirEntry == NULL)
8525             {
8526
8527                 //
8528                 // OK, if this component is a valid short name then try
8529                 // a lookup in the short name tree
8530                 //
8531
8532                 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
8533                     RtlIsNameLegalDOS8Dot3( ComponentName,
8534                                             NULL,
8535                                             NULL))
8536                 {
8537
8538                     AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8539                                   AFS_TRACE_LEVEL_VERBOSE_2,
8540                                   "AFSCheckSymlinkAccess Searching for entry %wZ short name\n",
8541                                   ComponentName);
8542
8543                     AFSLocateShortNameDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.ShortNameTree,
8544                                                 ulCRC,
8545                                                 &pDirEntry);
8546                 }
8547             }
8548         }
8549
8550         if( pDirEntry != NULL)
8551         {
8552             lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
8553
8554             AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8555                           AFS_TRACE_LEVEL_VERBOSE,
8556                           "AFSCheckSymlinkAccess Increment count on %wZ DE %p Ccb %p Cnt %d\n",
8557                           &pDirEntry->NameInformation.FileName,
8558                           pDirEntry,
8559                           NULL,
8560                           lCount);
8561
8562             ASSERT( lCount >= 0);
8563         }
8564
8565         AFSReleaseResource( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
8566
8567         if( pDirEntry == NULL)
8568         {
8569
8570             AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8571                           AFS_TRACE_LEVEL_VERBOSE_2,
8572                           "AFSCheckSymlinkAccess Failed to locate entry %wZ\n",
8573                           ComponentName);
8574
8575             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
8576         }
8577
8578         //
8579         // We have the symlink object but previously failed to process it so return access
8580         // denied.
8581         //
8582
8583         AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
8584                       AFS_TRACE_LEVEL_VERBOSE_2,
8585                       "AFSCheckSymlinkAccess Failing symlink access to entry %wZ REPARSE_POINT_NOT_RESOLVED\n",
8586                       ComponentName);
8587
8588         ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
8589
8590         lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
8591
8592         AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8593                       AFS_TRACE_LEVEL_VERBOSE,
8594                       "AFSCheckSymlinkAccess Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
8595                       &pDirEntry->NameInformation.FileName,
8596                       pDirEntry,
8597                       NULL,
8598                       lCount);
8599
8600         ASSERT( lCount >= 0);
8601
8602 try_exit:
8603
8604         NOTHING;
8605     }
8606
8607     return ntStatus;
8608 }
8609
8610 NTSTATUS
8611 AFSRetrieveFinalComponent( IN UNICODE_STRING *FullPathName,
8612                            OUT UNICODE_STRING *ComponentName)
8613 {
8614
8615     NTSTATUS ntStatus = STATUS_SUCCESS;
8616     UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName;
8617
8618     uniFullPathName = *FullPathName;
8619
8620     while( TRUE)
8621     {
8622
8623         FsRtlDissectName( uniFullPathName,
8624                           &uniComponentName,
8625                           &uniRemainingPath);
8626
8627         if( uniRemainingPath.Length == 0)
8628         {
8629             break;
8630         }
8631
8632         uniFullPathName = uniRemainingPath;
8633     }
8634
8635     if( uniComponentName.Length > 0)
8636     {
8637         *ComponentName = uniComponentName;
8638     }
8639
8640     return ntStatus;
8641 }
8642
8643 void
8644 AFSDumpTraceFiles_Default()
8645 {
8646     return;
8647 }
8648
8649 BOOLEAN
8650 AFSValidNameFormat( IN UNICODE_STRING *FileName)
8651 {
8652
8653     BOOLEAN bIsValidName = TRUE;
8654     USHORT usIndex = 0;
8655
8656     __Enter
8657     {
8658
8659         while( usIndex < FileName->Length/sizeof( WCHAR))
8660         {
8661
8662             if( FileName->Buffer[ usIndex] == L':' ||
8663                 FileName->Buffer[ usIndex] == L'*' ||
8664                 FileName->Buffer[ usIndex] == L'?' ||
8665                 FileName->Buffer[ usIndex] == L'"' ||
8666                 FileName->Buffer[ usIndex] == L'<' ||
8667                 FileName->Buffer[ usIndex] == L'>')
8668             {
8669                 bIsValidName = FALSE;
8670                 break;
8671             }
8672
8673             usIndex++;
8674         }
8675     }
8676
8677     return bIsValidName;
8678 }
8679
8680 NTSTATUS
8681 AFSCreateDefaultSecurityDescriptor()
8682 {
8683
8684     NTSTATUS ntStatus = STATUS_SUCCESS;
8685     PACL pSACL = NULL;
8686     ULONG ulSACLSize = 0;
8687     SYSTEM_MANDATORY_LABEL_ACE* pACE = NULL;
8688     ULONG ulACESize = 0;
8689     SECURITY_DESCRIPTOR *pSecurityDescr = NULL;
8690     ULONG ulSDLength = 0;
8691     SECURITY_DESCRIPTOR *pRelativeSecurityDescr = NULL;
8692     PSID pWorldSID = NULL;
8693     ULONG *pulSubAuthority = NULL;
8694     ULONG ulWorldSIDLEngth = 0;
8695
8696     __Enter
8697     {
8698
8699         ulWorldSIDLEngth = RtlLengthRequiredSid( 1);
8700
8701         pWorldSID = (PSID)ExAllocatePoolWithTag( PagedPool,
8702                                                  ulWorldSIDLEngth,
8703                                                  AFS_GENERIC_MEMORY_29_TAG);
8704
8705         if( pWorldSID == NULL)
8706         {
8707             AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate World SID\n");
8708             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8709         }
8710
8711         RtlZeroMemory( pWorldSID,
8712                        ulWorldSIDLEngth);
8713
8714         RtlInitializeSid( pWorldSID,
8715                           &SeWorldSidAuthority,
8716                           1);
8717
8718         pulSubAuthority = RtlSubAuthoritySid(pWorldSID, 0);
8719         *pulSubAuthority = SECURITY_WORLD_RID;
8720
8721         if( AFSRtlSetSaclSecurityDescriptor == NULL)
8722         {
8723
8724             AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor == NULL\n");
8725         }
8726         else
8727         {
8728
8729             ulACESize = sizeof( SYSTEM_MANDATORY_LABEL_ACE) + 128;
8730
8731             pACE = (SYSTEM_MANDATORY_LABEL_ACE *)ExAllocatePoolWithTag( PagedPool,
8732                                                                         ulACESize,
8733                                                                         AFS_GENERIC_MEMORY_29_TAG);
8734
8735             if( pACE == NULL)
8736             {
8737
8738                 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8739
8740                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8741             }
8742
8743             RtlZeroMemory( pACE,
8744                            ulACESize);
8745
8746             pACE->Header.AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
8747             pACE->Header.AceType = SYSTEM_MANDATORY_LABEL_ACE_TYPE;
8748             pACE->Header.AceSize = FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + (USHORT)RtlLengthSid( SeExports->SeLowMandatorySid);
8749             pACE->Mask = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP;
8750
8751             RtlCopySid( RtlLengthSid( SeExports->SeLowMandatorySid),
8752                         &pACE->SidStart,
8753                         SeExports->SeLowMandatorySid);
8754
8755             ulSACLSize = sizeof(ACL) + RtlLengthSid( SeExports->SeLowMandatorySid) +
8756                 FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + ulACESize;
8757
8758             pSACL = (PACL)ExAllocatePoolWithTag( PagedPool,
8759                                                  ulSACLSize,
8760                                                  AFS_GENERIC_MEMORY_29_TAG);
8761
8762             if( pSACL == NULL)
8763             {
8764
8765                 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8766
8767                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8768             }
8769
8770             ntStatus = RtlCreateAcl( pSACL,
8771                                      ulSACLSize,
8772                                      ACL_REVISION);
8773
8774             if( !NT_SUCCESS( ntStatus))
8775             {
8776
8777                 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateAcl ntStatus %08lX\n",
8778                           ntStatus);
8779
8780                 try_return( ntStatus);
8781             }
8782
8783             ntStatus = RtlAddAce( pSACL,
8784                                   ACL_REVISION,
8785                                   0,
8786                                   pACE,
8787                                   pACE->Header.AceSize);
8788
8789             if( !NT_SUCCESS( ntStatus))
8790             {
8791
8792                 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAddAce ntStatus %08lX\n",
8793                           ntStatus);
8794
8795                 try_return( ntStatus);
8796             }
8797         }
8798
8799         pSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
8800                                                                        sizeof( SECURITY_DESCRIPTOR),
8801                                                                        AFS_GENERIC_MEMORY_27_TAG);
8802
8803         if( pSecurityDescr == NULL)
8804         {
8805
8806             AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8807
8808             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8809         }
8810
8811         ntStatus = RtlCreateSecurityDescriptor( pSecurityDescr,
8812                                                 SECURITY_DESCRIPTOR_REVISION);
8813
8814         if( !NT_SUCCESS( ntStatus))
8815         {
8816
8817             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateSecurityDescriptor ntStatus %08lX\n",
8818                       ntStatus);
8819
8820             try_return( ntStatus);
8821         }
8822
8823         if( AFSRtlSetSaclSecurityDescriptor != NULL)
8824         {
8825             ntStatus = AFSRtlSetSaclSecurityDescriptor( pSecurityDescr,
8826                                                         TRUE,
8827                                                         pSACL,
8828                                                         FALSE);
8829
8830             if( !NT_SUCCESS( ntStatus))
8831             {
8832
8833                 AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor ntStatus %08lX\n",
8834                           ntStatus);
8835
8836                 try_return( ntStatus);
8837             }
8838         }
8839
8840         //
8841         // Add in the group and owner to the SD
8842         //
8843
8844         if( AFSRtlSetGroupSecurityDescriptor != NULL)
8845         {
8846             ntStatus = AFSRtlSetGroupSecurityDescriptor( pSecurityDescr,
8847                                                          pWorldSID,
8848                                                          FALSE);
8849
8850             if( !NT_SUCCESS( ntStatus))
8851             {
8852
8853                 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetGroupSecurityDescriptor failed ntStatus %08lX\n",
8854                           ntStatus);
8855
8856                 try_return( ntStatus);
8857             }
8858         }
8859
8860         ntStatus = RtlSetOwnerSecurityDescriptor( pSecurityDescr,
8861                                                   pWorldSID,
8862                                                   FALSE);
8863
8864         if( !NT_SUCCESS( ntStatus))
8865         {
8866
8867             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetOwnerSecurityDescriptor failed ntStatus %08lX\n",
8868                       ntStatus);
8869
8870             try_return( ntStatus);
8871         }
8872
8873         if( !RtlValidSecurityDescriptor( pSecurityDescr))
8874         {
8875
8876             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlValidSecurityDescriptor NOT\n");
8877
8878             try_return( ntStatus = STATUS_INVALID_PARAMETER);
8879         }
8880
8881         pRelativeSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
8882                                                                                PAGE_SIZE,
8883                                                                                AFS_GENERIC_MEMORY_27_TAG);
8884
8885         if( pRelativeSecurityDescr == NULL)
8886         {
8887
8888             AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8889
8890             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8891         }
8892
8893         ulSDLength = PAGE_SIZE;
8894
8895         ntStatus = RtlAbsoluteToSelfRelativeSD( pSecurityDescr,
8896                                                 pRelativeSecurityDescr,
8897                                                 &ulSDLength);
8898
8899         if( !NT_SUCCESS( ntStatus))
8900         {
8901
8902             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAbsoluteToSelfRelativeSD ntStatus %08lX\n",
8903                       ntStatus);
8904
8905             try_return( ntStatus);
8906         }
8907
8908         AFSDefaultSD = pRelativeSecurityDescr;
8909
8910 try_exit:
8911
8912         if( !NT_SUCCESS( ntStatus))
8913         {
8914
8915             if( pRelativeSecurityDescr != NULL)
8916             {
8917                 ExFreePool( pRelativeSecurityDescr);
8918             }
8919         }
8920
8921         if( pSecurityDescr != NULL)
8922         {
8923             ExFreePool( pSecurityDescr);
8924         }
8925
8926         if( pSACL != NULL)
8927         {
8928             ExFreePool( pSACL);
8929         }
8930
8931         if( pACE != NULL)
8932         {
8933             ExFreePool( pACE);
8934         }
8935
8936         if( pWorldSID != NULL)
8937         {
8938             ExFreePool( pWorldSID);
8939         }
8940     }
8941
8942     return ntStatus;
8943 }
8944
8945 void
8946 AFSRetrieveParentPath( IN UNICODE_STRING *FullFileName,
8947                        OUT UNICODE_STRING *ParentPath)
8948 {
8949
8950     *ParentPath = *FullFileName;
8951
8952     //
8953     // If the final character is a \, jump over it
8954     //
8955
8956     if( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] == L'\\')
8957     {
8958         ParentPath->Length -= sizeof( WCHAR);
8959     }
8960
8961     while( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] != L'\\')
8962     {
8963         ParentPath->Length -= sizeof( WCHAR);
8964     }
8965
8966     //
8967     // And the separator
8968     //
8969
8970     ParentPath->Length -= sizeof( WCHAR);
8971
8972     return;
8973 }
8974
8975 NTSTATUS
8976 AFSRetrieveValidAuthGroup( IN AFSFcb *Fcb,
8977                            IN AFSObjectInfoCB *ObjectInfo,
8978                            IN BOOLEAN WriteAccess,
8979                            OUT GUID *AuthGroup)
8980 {
8981
8982     NTSTATUS ntStatus = STATUS_SUCCESS;
8983     GUID     stAuthGroup, stZeroAuthGroup;
8984     BOOLEAN  bFoundAuthGroup = FALSE;
8985     AFSCcb  *pCcb = NULL;
8986     AFSFcb *pFcb = Fcb;
8987
8988     __Enter
8989     {
8990
8991         RtlZeroMemory( &stAuthGroup,
8992                        sizeof( GUID));
8993
8994         RtlZeroMemory( &stZeroAuthGroup,
8995                        sizeof( GUID));
8996
8997         if( Fcb == NULL)
8998         {
8999
9000             if( ObjectInfo != NULL &&
9001                 ObjectInfo->Fcb != NULL)
9002             {
9003                 pFcb = ObjectInfo->Fcb;
9004             }
9005         }
9006
9007         if( pFcb != NULL)
9008         {
9009
9010             AFSAcquireShared( &Fcb->NPFcb->CcbListLock,
9011                               TRUE);
9012
9013             pCcb = Fcb->CcbListHead;
9014
9015             while( pCcb != NULL)
9016             {
9017
9018                 if( WriteAccess &&
9019                     pCcb->GrantedAccess & FILE_WRITE_DATA)
9020                 {
9021                     RtlCopyMemory( &stAuthGroup,
9022                                    &pCcb->AuthGroup,
9023                                    sizeof( GUID));
9024
9025                     bFoundAuthGroup = TRUE;
9026
9027                     break;
9028                 }
9029                 else if( pCcb->GrantedAccess & FILE_READ_DATA)
9030                 {
9031                     //
9032                     // At least get the read-only access
9033                     //
9034
9035                     RtlCopyMemory( &stAuthGroup,
9036                                    &pCcb->AuthGroup,
9037                                    sizeof( GUID));
9038
9039                     bFoundAuthGroup = TRUE;
9040                 }
9041
9042                 pCcb = (AFSCcb *)pCcb->ListEntry.fLink;
9043             }
9044
9045             AFSReleaseResource( &Fcb->NPFcb->CcbListLock);
9046         }
9047
9048         if( !bFoundAuthGroup)
9049         {
9050
9051             AFSRetrieveAuthGroupFnc( (ULONGLONG)PsGetCurrentProcessId(),
9052                                      (ULONGLONG)PsGetCurrentThreadId(),
9053                                       &stAuthGroup);
9054
9055             if( RtlCompareMemory( &stZeroAuthGroup,
9056                                   &stAuthGroup,
9057                                   sizeof( GUID)) == sizeof( GUID))
9058             {
9059
9060                 DbgPrint("AFSRetrieveValidAuthGroup Failed to locate PAG\n");
9061
9062                 try_return( ntStatus = STATUS_ACCESS_DENIED);
9063             }
9064         }
9065
9066         RtlCopyMemory( AuthGroup,
9067                        &stAuthGroup,
9068                        sizeof( GUID));
9069
9070 try_exit:
9071
9072         NOTHING;
9073     }
9074
9075     return ntStatus;
9076 }
9077
9078 NTSTATUS
9079 AFSPerformObjectInvalidate( IN AFSObjectInfoCB *ObjectInfo,
9080                             IN ULONG InvalidateReason)
9081 {
9082
9083     NTSTATUS            ntStatus = STATUS_SUCCESS;
9084     LIST_ENTRY         *le;
9085     AFSExtent          *pEntry;
9086     ULONG               ulProcessCount = 0;
9087     ULONG               ulCount = 0;
9088
9089     __Enter
9090     {
9091
9092         switch( InvalidateReason)
9093         {
9094
9095             case AFS_INVALIDATE_DELETED:
9096             {
9097
9098                 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
9099                     ObjectInfo->Fcb != NULL)
9100                 {
9101
9102                     AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9103                                     TRUE);
9104
9105                     ObjectInfo->Links = 0;
9106
9107                     ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
9108
9109                     KeSetEvent( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
9110                                 0,
9111                                 FALSE);
9112
9113                     //
9114                     // Clear out the extents
9115                     // And get rid of them (note this involves waiting
9116                     // for any writes or reads to the cache to complete)
9117                     //
9118
9119                     AFSTearDownFcbExtents( ObjectInfo->Fcb,
9120                                            NULL);
9121
9122                     AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
9123                 }
9124
9125                 break;
9126             }
9127
9128             case AFS_INVALIDATE_DATA_VERSION:
9129             {
9130
9131                 LARGE_INTEGER liCurrentOffset = {0,0};
9132                 LARGE_INTEGER liFlushLength = {0,0};
9133                 ULONG ulFlushLength = 0;
9134                 BOOLEAN bLocked = FALSE;
9135                 BOOLEAN bExtentsLocked = FALSE;
9136                 BOOLEAN bCleanExtents = FALSE;
9137
9138                 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
9139                     ObjectInfo->Fcb != NULL)
9140                 {
9141
9142                     AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Resource,
9143                                     TRUE);
9144
9145                     bLocked = TRUE;
9146
9147                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
9148                                   AFS_TRACE_LEVEL_VERBOSE,
9149                                   "AFSPerformObjectInvalidate Acquiring Fcb extents lock %p SHARED %08lX\n",
9150                                   &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9151                                   PsGetCurrentThread());
9152
9153                     AFSAcquireShared( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9154                                       TRUE);
9155
9156                     bExtentsLocked = TRUE;
9157
9158                     //
9159                     // There are several possibilities here:
9160                     //
9161                     // 0. If there are no extents or all of the extents are dirty, do nothing.
9162                     //
9163                     // 1. There could be nothing dirty and an open reference count of zero
9164                     //    in which case we can just tear down all of the extents without
9165                     //    holding any resources.
9166                     //
9167                     // 2. There could be nothing dirty and a non-zero open reference count
9168                     //    in which case we can issue a CcPurge against the entire file
9169                     //    while holding just the Fcb Resource.
9170                     //
9171                     // 3. There can be dirty extents in which case we need to identify
9172                     //    the non-dirty ranges and then perform a CcPurge on just the
9173                     //    non-dirty ranges while holding just the Fcb Resource.
9174                     //
9175
9176                     if ( ObjectInfo->Fcb->Specific.File.ExtentCount != ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount)
9177                     {
9178
9179                         if ( ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount == 0)
9180                         {
9181
9182                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9183
9184                             bExtentsLocked = FALSE;
9185
9186                             if ( ObjectInfo->Fcb->OpenReferenceCount == 0)
9187                             {
9188
9189                                 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9190
9191                                 bLocked = FALSE;
9192
9193                                 AFSTearDownFcbExtents( ObjectInfo->Fcb,
9194                                                        NULL);
9195                             }
9196                             else
9197                             {
9198
9199                                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
9200                                               AFS_TRACE_LEVEL_VERBOSE,
9201                                               "AFSPerformObjectInvalidation Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
9202                                               &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9203                                               PsGetCurrentThread());
9204
9205                                 AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9206                                                 TRUE);
9207
9208                                 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9209
9210                                 bLocked = FALSE;
9211
9212                                 __try
9213                                 {
9214
9215                                     if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
9216                                         !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9217                                                               NULL,
9218                                                               0,
9219                                                               FALSE))
9220                                     {
9221
9222                                         AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
9223                                                       AFS_TRACE_LEVEL_WARNING,
9224                                                       "AFSPerformObjectInvalidation CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9225                                                       ObjectInfo->FileId.Cell,
9226                                                       ObjectInfo->FileId.Volume,
9227                                                       ObjectInfo->FileId.Vnode,
9228                                                       ObjectInfo->FileId.Unique);
9229
9230                                         SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9231                                     }
9232                                     else
9233                                     {
9234
9235                                         bCleanExtents = TRUE;
9236                                     }
9237                                 }
9238                                 __except( EXCEPTION_EXECUTE_HANDLER)
9239                                 {
9240
9241                                     ntStatus = GetExceptionCode();
9242
9243                                     AFSDbgLogMsg( 0,
9244                                                   0,
9245                                                   "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
9246                                                   ObjectInfo->FileId.Cell,
9247                                                   ObjectInfo->FileId.Volume,
9248                                                   ObjectInfo->FileId.Vnode,
9249                                                   ObjectInfo->FileId.Unique,
9250                                                   ntStatus);
9251
9252                                     SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9253                                 }
9254
9255                                 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
9256                                               AFS_TRACE_LEVEL_VERBOSE,
9257                                               "AFSPerformObjectInvalidation Releasing Fcb SectionObject lock %p EXCL %08lX\n",
9258                                               &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9259                                               PsGetCurrentThread());
9260
9261                                 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
9262                             }
9263                         }
9264                         else
9265                         {
9266
9267                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9268
9269                             bExtentsLocked = FALSE;
9270
9271                             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
9272                                           AFS_TRACE_LEVEL_VERBOSE,
9273                                           "AFSPerformObjectInvalidation Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
9274                                           &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9275                                           PsGetCurrentThread());
9276
9277                             AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9278                                             TRUE);
9279
9280                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9281
9282                             bLocked = FALSE;
9283
9284                             //
9285                             // Must build a list of non-dirty ranges from the beginning of the file
9286                             // to the end.  There can be at most (Fcb->Specific.File.ExtentsDirtyCount + 1)
9287                             // ranges.  In all but the most extreme random data write scenario there will
9288                             // be significantly fewer.
9289                             //
9290                             // For each range we need offset and size.
9291                             //
9292
9293                             AFSByteRange * ByteRangeList = NULL;
9294                             ULONG          ulByteRangeCount = 0;
9295                             ULONG          ulIndex;
9296                             BOOLEAN        bPurgeOnClose = FALSE;
9297
9298                             __try
9299                             {
9300
9301                                 ulByteRangeCount = AFSConstructCleanByteRangeList( ObjectInfo->Fcb,
9302                                                                                    &ByteRangeList);
9303
9304                                 if ( ByteRangeList != NULL ||
9305                                      ulByteRangeCount == 0)
9306                                 {
9307
9308                                     for ( ulIndex = 0; ulIndex < ulByteRangeCount; ulIndex++)
9309                                     {
9310
9311                                         ULONG ulSize;
9312
9313                                         do {
9314
9315                                             ulSize = ByteRangeList[ulIndex].Length.QuadPart > DWORD_MAX ? DWORD_MAX : ByteRangeList[ulIndex].Length.LowPart;
9316
9317                                             if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
9318                                                 !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9319                                                                       &ByteRangeList[ulIndex].FileOffset,
9320                                                                       ulSize,
9321                                                                       FALSE))
9322                                             {
9323
9324                                                 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
9325                                                               AFS_TRACE_LEVEL_WARNING,
9326                                                               "AFSPerformObjectInvalidation [1] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9327                                                               ObjectInfo->FileId.Cell,
9328                                                               ObjectInfo->FileId.Volume,
9329                                                               ObjectInfo->FileId.Vnode,
9330                                                               ObjectInfo->FileId.Unique);
9331
9332                                                 bPurgeOnClose = TRUE;
9333                                             }
9334                                             else
9335                                             {
9336
9337                                                 bCleanExtents = TRUE;
9338                                             }
9339
9340                                             ByteRangeList[ulIndex].Length.QuadPart -= ulSize;
9341
9342                                             ByteRangeList[ulIndex].FileOffset.QuadPart += ulSize;
9343
9344                                         } while ( ByteRangeList[ulIndex].Length.QuadPart > 0);
9345                                     }
9346                                 }
9347                                 else
9348                                 {
9349
9350                                     //
9351                                     // We couldn't allocate the memory to build the purge list
9352                                     // so just walk the extent list while holding the ExtentsList Resource.
9353                                     // This could deadlock but we do not have much choice.
9354                                     //
9355
9356                                     AFSAcquireExcl(  &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9357                                                     TRUE);
9358                                     bExtentsLocked = TRUE;
9359
9360                                     le = ObjectInfo->Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
9361
9362                                     ulProcessCount = 0;
9363
9364                                     ulCount = (ULONG)ObjectInfo->Fcb->Specific.File.ExtentCount;
9365
9366                                     if( ulCount > 0)
9367                                     {
9368                                         pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
9369
9370                                         while( ulProcessCount < ulCount)
9371                                         {
9372                                             pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
9373
9374                                             if( !BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
9375                                             {
9376                                                 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9377                                                                           &pEntry->FileOffset,
9378                                                                           pEntry->Size,
9379                                                                           FALSE))
9380                                                 {
9381
9382                                                     AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
9383                                                                   AFS_TRACE_LEVEL_WARNING,
9384                                                                   "AFSPerformObjectInvalidation [2] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9385                                                                   ObjectInfo->FileId.Cell,
9386                                                                   ObjectInfo->FileId.Volume,
9387                                                                   ObjectInfo->FileId.Vnode,
9388                                                                   ObjectInfo->FileId.Unique);
9389
9390                                                     bPurgeOnClose = TRUE;
9391                                                 }
9392                                                 else
9393                                                 {
9394
9395                                                     bCleanExtents = TRUE;
9396                                                 }
9397                                             }
9398
9399                                             if( liCurrentOffset.QuadPart < pEntry->FileOffset.QuadPart)
9400                                             {
9401
9402                                                 liFlushLength.QuadPart = pEntry->FileOffset.QuadPart - liCurrentOffset.QuadPart;
9403
9404                                                 while( liFlushLength.QuadPart > 0)
9405                                                 {
9406
9407                                                     if( liFlushLength.QuadPart > 512 * 1024000)
9408                                                     {
9409                                                         ulFlushLength = 512 * 1024000;
9410                                                     }
9411                                                     else
9412                                                     {
9413                                                         ulFlushLength = liFlushLength.LowPart;
9414                                                     }
9415
9416                                                     if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9417                                                                               &liCurrentOffset,
9418                                                                               ulFlushLength,
9419                                                                               FALSE))
9420                                                     {
9421
9422                                                         AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
9423                                                                       AFS_TRACE_LEVEL_WARNING,
9424                                                                       "AFSPerformObjectInvalidation [3] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9425                                                                       ObjectInfo->FileId.Cell,
9426                                                                       ObjectInfo->FileId.Volume,
9427                                                                       ObjectInfo->FileId.Vnode,
9428                                                                       ObjectInfo->FileId.Unique);
9429
9430                                                         bPurgeOnClose = TRUE;
9431                                                     }
9432                                                     else
9433                                                     {
9434
9435                                                         bCleanExtents = TRUE;
9436                                                     }
9437
9438                                                     liFlushLength.QuadPart -= ulFlushLength;
9439                                                 }
9440                                             }
9441
9442                                             liCurrentOffset.QuadPart = pEntry->FileOffset.QuadPart + pEntry->Size;
9443
9444                                             ulProcessCount++;
9445                                             le = le->Flink;
9446                                         }
9447                                     }
9448                                     else
9449                                     {
9450                                         if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9451                                                                   NULL,
9452                                                                   0,
9453                                                                   FALSE))
9454                                         {
9455
9456                                             AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
9457                                                           AFS_TRACE_LEVEL_WARNING,
9458                                                           "AFSPerformObjectInvalidation [4] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9459                                                           ObjectInfo->FileId.Cell,
9460                                                           ObjectInfo->FileId.Volume,
9461                                                           ObjectInfo->FileId.Vnode,
9462                                                           ObjectInfo->FileId.Unique);
9463
9464                                             bPurgeOnClose = TRUE;
9465                                         }
9466                                         else
9467                                         {
9468
9469                                             bCleanExtents = TRUE;
9470                                         }
9471                                     }
9472
9473                                     if ( bPurgeOnClose)
9474                                     {
9475
9476                                         SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9477                                     }
9478                                 }
9479                             }
9480                             __except( EXCEPTION_EXECUTE_HANDLER)
9481                             {
9482
9483                                 ntStatus = GetExceptionCode();
9484
9485                                 AFSDbgLogMsg( 0,
9486                                               0,
9487                                               "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
9488                                               ObjectInfo->FileId.Cell,
9489                                               ObjectInfo->FileId.Volume,
9490                                               ObjectInfo->FileId.Vnode,
9491                                               ObjectInfo->FileId.Unique,
9492                                               ntStatus);
9493                             }
9494
9495                             AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
9496                                           AFS_TRACE_LEVEL_VERBOSE,
9497                                           "AFSPerformObjectInvalidation Releasing Fcb SectionObject lock %p EXCL %08lX\n",
9498                                           &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9499                                           PsGetCurrentThread());
9500
9501                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
9502                         }
9503                     }
9504
9505                     if ( bExtentsLocked)
9506                     {
9507
9508                         AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9509                     }
9510
9511                     if ( bLocked)
9512                     {
9513
9514                         AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9515                     }
9516
9517                     if ( bCleanExtents)
9518                     {
9519
9520                         AFSReleaseCleanExtents( ObjectInfo->Fcb,
9521                                                 NULL);
9522                     }
9523                 }
9524
9525                 break;
9526             }
9527         }
9528
9529         if( ObjectInfo != NULL)
9530         {
9531
9532             AFSObjectInfoDecrement( ObjectInfo);
9533         }
9534     }
9535
9536     return ntStatus;
9537 }