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