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