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