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