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