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