Windows: AFSDeleteDirEntry set input to NULL
[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     BOOLEAN bAllocatedObjectCB = FALSE;
1006     ULONGLONG ullIndex = 0;
1007     AFSNonPagedDirectoryCB *pNonPagedDirEntry = NULL;
1008     LONG lCount;
1009
1010     __Enter
1011     {
1012
1013         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1014                       AFS_TRACE_LEVEL_VERBOSE,
1015                       "AFSInitDirEntry Initializing entry %wZ parent FID %08lX-%08lX-%08lX-%08lX\n",
1016                       FileName,
1017                       ParentObjectInfo->FileId.Cell,
1018                       ParentObjectInfo->FileId.Volume,
1019                       ParentObjectInfo->FileId.Vnode,
1020                       ParentObjectInfo->FileId.Unique));
1021
1022         //
1023         // First thing is to locate/create our object information block
1024         // for this entry
1025         //
1026
1027         AFSAcquireExcl( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock,
1028                         TRUE);
1029
1030         ullIndex = AFSCreateLowIndex( &DirEnumEntry->FileId);
1031
1032         ntStatus = AFSLocateHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
1033                                        ullIndex,
1034                                        (AFSBTreeEntry **)&pObjectInfoCB);
1035
1036         if( !NT_SUCCESS( ntStatus) ||
1037             pObjectInfoCB == NULL)
1038         {
1039
1040             //
1041             // Allocate our object info cb
1042             //
1043
1044             pObjectInfoCB = AFSAllocateObjectInfo( ParentObjectInfo,
1045                                                    ullIndex);
1046
1047             if( pObjectInfoCB == NULL)
1048             {
1049
1050                 AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
1051
1052                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1053             }
1054
1055             bAllocatedObjectCB = TRUE;
1056
1057             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1058                           AFS_TRACE_LEVEL_VERBOSE,
1059                           "AFSInitDirEntry initialized object %p Parent Object %p for %wZ\n",
1060                           pObjectInfoCB,
1061                           ParentObjectInfo,
1062                           FileName));
1063         }
1064
1065         //
1066         // This reference count is either stored into the return DirectoryCB
1067         // or released before function exit.
1068         //
1069
1070         lCount = AFSObjectInfoIncrement( pObjectInfoCB,
1071                                          AFS_OBJECT_REFERENCE_DIRENTRY);
1072
1073         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1074                       AFS_TRACE_LEVEL_VERBOSE,
1075                       "AFSInitDirEntry Increment count on object %p Cnt %d\n",
1076                       pObjectInfoCB,
1077                       lCount));
1078
1079         AFSReleaseResource( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeLock);
1080
1081         ntStatus = STATUS_SUCCESS;
1082
1083         ulEntryLength = sizeof( AFSDirectoryCB) +
1084                                      FileName->Length;
1085
1086         if( TargetName != NULL)
1087         {
1088
1089             ulEntryLength += TargetName->Length;
1090         }
1091
1092         pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
1093                                                                ulEntryLength,
1094                                                                AFS_DIR_ENTRY_TAG);
1095
1096         if( pDirNode == NULL)
1097         {
1098
1099             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1100         }
1101
1102         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1103                       AFS_TRACE_LEVEL_VERBOSE,
1104                       "AFSInitDirEntry AFS_DIR_ENTRY_TAG allocated %p\n",
1105                       pDirNode));
1106
1107         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
1108                                                                                 sizeof( AFSNonPagedDirectoryCB),
1109                                                                                 AFS_DIR_ENTRY_NP_TAG);
1110
1111         if( pNonPagedDirEntry == NULL)
1112         {
1113
1114             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1115         }
1116
1117         RtlZeroMemory( pDirNode,
1118                        ulEntryLength);
1119
1120         RtlZeroMemory( pNonPagedDirEntry,
1121                        sizeof( AFSNonPagedDirectoryCB));
1122
1123         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
1124
1125         pDirNode->NonPaged = pNonPagedDirEntry;
1126
1127         pDirNode->ObjectInformation = pObjectInfoCB;
1128
1129         //
1130         // Set valid entry and NOT_IN_PARENT flag
1131         //
1132
1133         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
1134
1135         pDirNode->FileIndex = FileIndex;
1136
1137         //
1138         // Setup the names in the entry
1139         //
1140
1141         if( FileName->Length > 0)
1142         {
1143
1144             pDirNode->NameInformation.FileName.Length = FileName->Length;
1145
1146             pDirNode->NameInformation.FileName.MaximumLength = FileName->Length;
1147
1148             pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
1149
1150             RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
1151                            FileName->Buffer,
1152                            pDirNode->NameInformation.FileName.Length);
1153
1154             //
1155             // Create a CRC for the file
1156             //
1157
1158             pDirNode->CaseSensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1159                                                                          FALSE);
1160
1161             pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
1162                                                                            TRUE);
1163         }
1164
1165         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1166                       AFS_TRACE_LEVEL_VERBOSE,
1167                       "AFSInitDirEntry Initialized DE %p for %wZ in parent FID %08lX-%08lX-%08lX-%08lX\n",
1168                       pDirNode,
1169                       FileName,
1170                       ParentObjectInfo->FileId.Cell,
1171                       ParentObjectInfo->FileId.Volume,
1172                       ParentObjectInfo->FileId.Vnode,
1173                       ParentObjectInfo->FileId.Unique));
1174
1175         if( TargetName != NULL &&
1176             TargetName->Length > 0)
1177         {
1178
1179             pDirNode->NameInformation.TargetName.Length = TargetName->Length;
1180
1181             pDirNode->NameInformation.TargetName.MaximumLength = pDirNode->NameInformation.TargetName.Length;
1182
1183             pDirNode->NameInformation.TargetName.Buffer = (WCHAR *)((char *)pDirNode +
1184                                                                             sizeof( AFSDirectoryCB) +
1185                                                                             pDirNode->NameInformation.FileName.Length);
1186
1187             RtlCopyMemory( pDirNode->NameInformation.TargetName.Buffer,
1188                            TargetName->Buffer,
1189                            pDirNode->NameInformation.TargetName.Length);
1190         }
1191
1192         //
1193         // If we allocated the object information cb then update the information
1194         //
1195
1196         if( bAllocatedObjectCB)
1197         {
1198
1199             //
1200             // Populate the rest of the data
1201             //
1202
1203             pObjectInfoCB->FileId = DirEnumEntry->FileId;
1204
1205             pObjectInfoCB->TargetFileId = DirEnumEntry->TargetFileId;
1206
1207             pObjectInfoCB->FileType = DirEnumEntry->FileType;
1208
1209             pObjectInfoCB->CreationTime = DirEnumEntry->CreationTime;
1210
1211             pObjectInfoCB->LastAccessTime = DirEnumEntry->LastAccessTime;
1212
1213             pObjectInfoCB->LastWriteTime = DirEnumEntry->LastWriteTime;
1214
1215             pObjectInfoCB->ChangeTime = DirEnumEntry->ChangeTime;
1216
1217             pObjectInfoCB->EndOfFile = DirEnumEntry->EndOfFile;
1218
1219             pObjectInfoCB->AllocationSize = DirEnumEntry->AllocationSize;
1220
1221             pObjectInfoCB->FileAttributes = DirEnumEntry->FileAttributes;
1222
1223             if( pObjectInfoCB->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1224                 pObjectInfoCB->FileType == AFS_FILE_TYPE_DFSLINK)
1225             {
1226
1227                 pObjectInfoCB->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1228             }
1229
1230             if (pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK)
1231             {
1232
1233                 if ( pObjectInfoCB->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1234                 {
1235
1236                     pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1237                 }
1238                 else
1239                 {
1240
1241                     pObjectInfoCB->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1242                 }
1243             }
1244
1245             pObjectInfoCB->EaSize = DirEnumEntry->EaSize;
1246
1247             //
1248             // Check for the case where we have a filetype of SymLink but both the TargetFid and the
1249             // TargetName are empty. In this case set the filetype to zero so we evaluate it later in
1250             // the code
1251             //
1252
1253             if( pObjectInfoCB->FileType == AFS_FILE_TYPE_SYMLINK &&
1254                 pObjectInfoCB->TargetFileId.Vnode == 0 &&
1255                 pObjectInfoCB->TargetFileId.Unique == 0 &&
1256                 pDirNode->NameInformation.TargetName.Length == 0)
1257             {
1258
1259                 //
1260                 // This will ensure we perform a validation on the node
1261                 //
1262
1263                 pObjectInfoCB->FileType = AFS_FILE_TYPE_UNKNOWN;
1264             }
1265
1266             if( pObjectInfoCB->FileType == AFS_FILE_TYPE_UNKNOWN)
1267             {
1268
1269                 SetFlag( pObjectInfoCB->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
1270             }
1271         }
1272
1273         //
1274         // Object specific information
1275         //
1276
1277         pObjectInfoCB->Links = DirEnumEntry->Links;
1278
1279         pObjectInfoCB->Expiration = DirEnumEntry->Expiration;
1280
1281         pObjectInfoCB->DataVersion = DirEnumEntry->DataVersion;
1282
1283 try_exit:
1284
1285         if( !NT_SUCCESS( ntStatus))
1286         {
1287
1288             if( pNonPagedDirEntry != NULL)
1289             {
1290
1291                 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
1292
1293                 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
1294             }
1295
1296             if( pDirNode != NULL)
1297             {
1298
1299                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1300                               AFS_TRACE_LEVEL_VERBOSE,
1301                               "AFSInitDirEntry AFS_DIR_ENTRY_TAG deallocating %p\n",
1302                               pDirNode));
1303
1304                 AFSExFreePoolWithTag( pDirNode, AFS_DIR_ENTRY_TAG);
1305
1306                 pDirNode = NULL;
1307             }
1308
1309             //
1310             // Dereference our object info block if we have one
1311             //
1312
1313             if( pObjectInfoCB != NULL)
1314             {
1315
1316                 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
1317                                                  AFS_OBJECT_REFERENCE_DIRENTRY);
1318
1319                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1320                               AFS_TRACE_LEVEL_VERBOSE,
1321                               "AFSInitDirEntry Decrement count on object %p Cnt %d\n",
1322                               pObjectInfoCB,
1323                               lCount));
1324
1325                 if( bAllocatedObjectCB &&
1326                     lCount == 0)
1327                 {
1328
1329                     AFSDeleteObjectInfo( &pObjectInfoCB);
1330                 }
1331             }
1332         }
1333     }
1334
1335     return pDirNode;
1336 }
1337
1338 BOOLEAN
1339 AFSCheckForReadOnlyAccess( IN ACCESS_MASK DesiredAccess,
1340                            IN BOOLEAN DirectoryEntry)
1341 {
1342
1343     BOOLEAN bReturn = TRUE;
1344     ACCESS_MASK stAccessMask = 0;
1345
1346     //
1347     // Get rid of anything we don't know about
1348     //
1349
1350     DesiredAccess = (DesiredAccess   &
1351                           ( DELETE |
1352                             READ_CONTROL |
1353                             WRITE_OWNER |
1354                             WRITE_DAC |
1355                             SYNCHRONIZE |
1356                             ACCESS_SYSTEM_SECURITY |
1357                             FILE_WRITE_DATA |
1358                             FILE_READ_EA |
1359                             FILE_WRITE_EA |
1360                             FILE_READ_ATTRIBUTES |
1361                             FILE_WRITE_ATTRIBUTES |
1362                             FILE_LIST_DIRECTORY |
1363                             FILE_TRAVERSE |
1364                             FILE_DELETE_CHILD |
1365                             FILE_APPEND_DATA));
1366
1367     //
1368     // Our 'read only' access mask. These are the accesses we will
1369     // allow for a read only file
1370     //
1371
1372     stAccessMask = DELETE |
1373                         READ_CONTROL |
1374                         WRITE_OWNER |
1375                         WRITE_DAC |
1376                         SYNCHRONIZE |
1377                         ACCESS_SYSTEM_SECURITY |
1378                         FILE_READ_DATA |
1379                         FILE_READ_EA |
1380                         FILE_WRITE_EA |
1381                         FILE_READ_ATTRIBUTES |
1382                         FILE_WRITE_ATTRIBUTES |
1383                         FILE_EXECUTE |
1384                         FILE_LIST_DIRECTORY |
1385                         FILE_TRAVERSE;
1386
1387     //
1388     // For a directory, add in the directory specific accesses
1389     //
1390
1391     if( DirectoryEntry)
1392     {
1393
1394         stAccessMask |= FILE_ADD_SUBDIRECTORY |
1395                                 FILE_ADD_FILE |
1396                                 FILE_DELETE_CHILD;
1397     }
1398
1399     if( FlagOn( DesiredAccess, ~stAccessMask))
1400     {
1401
1402         //
1403         // A write access is set ...
1404         //
1405
1406         bReturn = FALSE;
1407     }
1408
1409     return bReturn;
1410 }
1411
1412 NTSTATUS
1413 AFSEvaluateNode( IN GUID *AuthGroup,
1414                  IN AFSDirectoryCB *DirEntry)
1415 {
1416
1417     NTSTATUS ntStatus = STATUS_SUCCESS;
1418     AFSDirEnumEntry *pDirEntry = NULL;
1419     UNICODE_STRING uniTargetName;
1420
1421     __Enter
1422     {
1423
1424         ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1425                                           AuthGroup,
1426                                           FALSE,
1427                                           &pDirEntry);
1428
1429         if( !NT_SUCCESS( ntStatus))
1430         {
1431
1432             try_return( ntStatus);
1433         }
1434
1435         DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1436
1437         DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1438
1439         DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1440
1441         DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1442
1443         DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1444
1445         DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1446
1447         DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1448
1449         DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1450
1451         DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1452
1453         DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1454
1455         DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1456
1457         if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1458             pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1459         {
1460
1461             DirEntry->ObjectInformation->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1462         }
1463
1464         if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK)
1465         {
1466
1467             if ( DirEntry->ObjectInformation->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1468             {
1469
1470                 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1471             }
1472             else
1473             {
1474
1475                 DirEntry->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1476             }
1477         }
1478
1479         DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1480
1481         DirEntry->ObjectInformation->Links = pDirEntry->Links;
1482
1483         //
1484         // If we have a target name then see if it needs updating ...
1485         //
1486
1487         if( pDirEntry->TargetNameLength > 0)
1488         {
1489
1490             //
1491             // Update the target name information if needed
1492             //
1493
1494             uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1495
1496             uniTargetName.MaximumLength = uniTargetName.Length;
1497
1498             uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1499
1500             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1501                             TRUE);
1502
1503             if( DirEntry->NameInformation.TargetName.Length == 0 ||
1504                 RtlCompareUnicodeString( &uniTargetName,
1505                                          &DirEntry->NameInformation.TargetName,
1506                                          TRUE) != 0)
1507             {
1508
1509                 //
1510                 // Update the target name
1511                 //
1512
1513                 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1514                                                 &DirEntry->Flags,
1515                                                 uniTargetName.Buffer,
1516                                                 uniTargetName.Length);
1517
1518                 if( !NT_SUCCESS( ntStatus))
1519                 {
1520
1521                     AFSReleaseResource( &DirEntry->NonPaged->Lock);
1522
1523                     try_return( ntStatus);
1524                 }
1525             }
1526
1527             AFSReleaseResource( &DirEntry->NonPaged->Lock);
1528         }
1529
1530 try_exit:
1531
1532         if( pDirEntry != NULL)
1533         {
1534
1535             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
1536         }
1537     }
1538
1539     return ntStatus;
1540 }
1541
1542 NTSTATUS
1543 AFSValidateSymLink( IN GUID *AuthGroup,
1544                     IN AFSDirectoryCB *DirEntry)
1545 {
1546
1547     NTSTATUS ntStatus = STATUS_SUCCESS;
1548     AFSDirEnumEntry *pDirEntry = NULL;
1549     UNICODE_STRING uniTargetName;
1550
1551     __Enter
1552     {
1553
1554         ntStatus = AFSEvaluateTargetByID( DirEntry->ObjectInformation,
1555                                           AuthGroup,
1556                                           FALSE,
1557                                           &pDirEntry);
1558
1559         if( !NT_SUCCESS( ntStatus))
1560         {
1561
1562             try_return( ntStatus);
1563         }
1564
1565         if( pDirEntry->FileType == AFS_FILE_TYPE_UNKNOWN ||
1566             pDirEntry->FileType == AFS_FILE_TYPE_INVALID)
1567         {
1568
1569             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1570                           AFS_TRACE_LEVEL_VERBOSE_2,
1571                           "AFSValidateSymLink Invalid type Status %08lX\n",
1572                           STATUS_OBJECT_NAME_NOT_FOUND));
1573
1574             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
1575         }
1576
1577         DirEntry->ObjectInformation->TargetFileId = pDirEntry->TargetFileId;
1578
1579         DirEntry->ObjectInformation->Expiration = pDirEntry->Expiration;
1580
1581         DirEntry->ObjectInformation->DataVersion = pDirEntry->DataVersion;
1582
1583         //
1584         // Update the target name information if needed
1585         //
1586
1587         uniTargetName.Length = (USHORT)pDirEntry->TargetNameLength;
1588
1589         uniTargetName.MaximumLength = uniTargetName.Length;
1590
1591         uniTargetName.Buffer = (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset);
1592
1593         if( uniTargetName.Length > 0)
1594         {
1595
1596             AFSAcquireExcl( &DirEntry->NonPaged->Lock,
1597                             TRUE);
1598
1599             if( DirEntry->NameInformation.TargetName.Length == 0 ||
1600                 RtlCompareUnicodeString( &uniTargetName,
1601                                          &DirEntry->NameInformation.TargetName,
1602                                          TRUE) != 0)
1603             {
1604
1605                 //
1606                 // Update the target name
1607                 //
1608
1609                 ntStatus = AFSUpdateTargetName( &DirEntry->NameInformation.TargetName,
1610                                                 &DirEntry->Flags,
1611                                                 uniTargetName.Buffer,
1612                                                 uniTargetName.Length);
1613
1614                 if( !NT_SUCCESS( ntStatus))
1615                 {
1616
1617                     AFSReleaseResource( &DirEntry->NonPaged->Lock);
1618
1619                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
1620                 }
1621             }
1622
1623             AFSReleaseResource( &DirEntry->NonPaged->Lock);
1624         }
1625
1626         //
1627         // If the FileType is the same then nothing to do since it IS
1628         // a SymLink
1629         //
1630
1631         if( pDirEntry->FileType == DirEntry->ObjectInformation->FileType)
1632         {
1633
1634             ASSERT( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK);
1635
1636             try_return( ntStatus = STATUS_SUCCESS);
1637         }
1638
1639         DirEntry->ObjectInformation->FileType = pDirEntry->FileType;
1640
1641         DirEntry->ObjectInformation->CreationTime = pDirEntry->CreationTime;
1642
1643         DirEntry->ObjectInformation->LastAccessTime = pDirEntry->LastAccessTime;
1644
1645         DirEntry->ObjectInformation->LastWriteTime = pDirEntry->LastWriteTime;
1646
1647         DirEntry->ObjectInformation->ChangeTime = pDirEntry->ChangeTime;
1648
1649         DirEntry->ObjectInformation->EndOfFile = pDirEntry->EndOfFile;
1650
1651         DirEntry->ObjectInformation->AllocationSize = pDirEntry->AllocationSize;
1652
1653         DirEntry->ObjectInformation->FileAttributes = pDirEntry->FileAttributes;
1654
1655         if( pDirEntry->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
1656             pDirEntry->FileType == AFS_FILE_TYPE_DFSLINK)
1657         {
1658
1659             DirEntry->ObjectInformation->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
1660         }
1661
1662         if( pDirEntry->FileType == AFS_FILE_TYPE_SYMLINK)
1663         {
1664
1665             if ( DirEntry->ObjectInformation->FileAttributes == FILE_ATTRIBUTE_NORMAL)
1666             {
1667
1668                 DirEntry->ObjectInformation->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
1669             }
1670             else
1671             {
1672
1673                 DirEntry->ObjectInformation->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
1674             }
1675         }
1676
1677         DirEntry->ObjectInformation->EaSize = pDirEntry->EaSize;
1678
1679         DirEntry->ObjectInformation->Links = pDirEntry->Links;
1680
1681 try_exit:
1682
1683         if( pDirEntry != NULL)
1684         {
1685
1686             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
1687         }
1688     }
1689
1690     return ntStatus;
1691 }
1692
1693 NTSTATUS
1694 AFSInvalidateObject( IN OUT AFSObjectInfoCB **ppObjectInfo,
1695                      IN     ULONG Reason)
1696 {
1697
1698     NTSTATUS ntStatus = STATUS_SUCCESS;
1699     IO_STATUS_BLOCK stIoStatus;
1700     ULONG ulFilter = 0;
1701     AFSObjectInfoCB * pParentObjectInfo = NULL;
1702
1703     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1704                   AFS_TRACE_LEVEL_VERBOSE,
1705                   "AFSInvalidateObject Invalidation on node type %d for fid %08lX-%08lX-%08lX-%08lX Reason %d\n",
1706                   (*ppObjectInfo)->FileType,
1707                   (*ppObjectInfo)->FileId.Cell,
1708                   (*ppObjectInfo)->FileId.Volume,
1709                   (*ppObjectInfo)->FileId.Vnode,
1710                   (*ppObjectInfo)->FileId.Unique,
1711                   Reason));
1712
1713     if ( BooleanFlagOn( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
1714     {
1715
1716         pParentObjectInfo = AFSFindObjectInfo( (*ppObjectInfo)->VolumeCB,
1717                                                &(*ppObjectInfo)->ParentFileId);
1718     }
1719
1720     if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_SYMLINK ||
1721         (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DFSLINK ||
1722         (*ppObjectInfo)->FileType == AFS_FILE_TYPE_MOUNTPOINT)
1723     {
1724         //
1725         // We only act on the mount point itself, not the target. If the
1726         // node has been deleted then mark it as such otherwise indicate
1727         // it requires verification
1728         //
1729
1730         if( Reason == AFS_INVALIDATE_DELETED)
1731         {
1732             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
1733         }
1734         else
1735         {
1736
1737             if( Reason == AFS_INVALIDATE_FLUSHED)
1738             {
1739
1740                 (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1741
1742                 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1743             }
1744
1745             (*ppObjectInfo)->Expiration.QuadPart = 0;
1746
1747             (*ppObjectInfo)->TargetFileId.Vnode = 0;
1748
1749             (*ppObjectInfo)->TargetFileId.Unique = 0;
1750
1751             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1752                           AFS_TRACE_LEVEL_VERBOSE,
1753                           "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
1754                           (*ppObjectInfo)->FileId.Cell,
1755                           (*ppObjectInfo)->FileId.Volume,
1756                           (*ppObjectInfo)->FileId.Vnode,
1757                           (*ppObjectInfo)->FileId.Unique));
1758
1759             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
1760         }
1761
1762         if ( pParentObjectInfo != NULL)
1763         {
1764
1765             ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1766
1767             if( Reason == AFS_INVALIDATE_CREDS)
1768             {
1769                 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1770             }
1771
1772             if( Reason == AFS_INVALIDATE_DATA_VERSION ||
1773                 Reason == AFS_INVALIDATE_FLUSHED)
1774             {
1775                 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1776             }
1777             else
1778             {
1779                 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1780             }
1781
1782             AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1783                                             NULL,
1784                                             ulFilter,
1785                                             FILE_ACTION_MODIFIED);
1786         }
1787
1788         try_return( ntStatus);
1789     }
1790
1791     //
1792     // Depending on the reason for invalidation then perform work on the node
1793     //
1794
1795     switch( Reason)
1796     {
1797
1798     case AFS_INVALIDATE_DELETED:
1799         {
1800
1801             //
1802             // Mark this node as invalid
1803             //
1804
1805             (*ppObjectInfo)->Links = 0;
1806
1807             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_DELETED);
1808
1809             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1810                           AFS_TRACE_LEVEL_VERBOSE,
1811                           "AFSInvalidateObject Set DELETE flag on fid %08lX-%08lX-%08lX-%08lX\n",
1812                           (*ppObjectInfo)->FileId.Cell,
1813                           (*ppObjectInfo)->FileId.Volume,
1814                           (*ppObjectInfo)->FileId.Vnode,
1815                           (*ppObjectInfo)->FileId.Unique));
1816
1817             if( pParentObjectInfo != NULL)
1818             {
1819
1820                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1821                               AFS_TRACE_LEVEL_VERBOSE,
1822                               "AFSInvalidateObject Set VERIFY flag on parent fid %08lX-%08lX-%08lX-%08lX\n",
1823                               pParentObjectInfo->FileId.Cell,
1824                               pParentObjectInfo->FileId.Volume,
1825                               pParentObjectInfo->FileId.Vnode,
1826                               pParentObjectInfo->FileId.Unique));
1827
1828                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
1829
1830                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
1831
1832                 pParentObjectInfo->Expiration.QuadPart = 0;
1833
1834                 if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1835                 {
1836                     ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1837                 }
1838                 else
1839                 {
1840                     ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1841                 }
1842
1843                 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
1844                                                 NULL,
1845                                                 ulFilter,
1846                                                 FILE_ACTION_REMOVED);
1847             }
1848
1849             if( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
1850                                                       Reason)))
1851             {
1852                 (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
1853             }
1854
1855             break;
1856         }
1857
1858     case AFS_INVALIDATE_FLUSHED:
1859         {
1860
1861             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
1862                 (*ppObjectInfo)->Fcb != NULL)
1863             {
1864
1865                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1866                               AFS_TRACE_LEVEL_VERBOSE,
1867                               "AFSInvalidateObject Flush/purge file fid %08lX-%08lX-%08lX-%08lX\n",
1868                               (*ppObjectInfo)->FileId.Cell,
1869                               (*ppObjectInfo)->FileId.Volume,
1870                               (*ppObjectInfo)->FileId.Vnode,
1871                               (*ppObjectInfo)->FileId.Unique));
1872
1873                 AFSAcquireExcl( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectResource,
1874                                 TRUE);
1875
1876                 __try
1877                 {
1878
1879                     CcFlushCache( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1880                                   NULL,
1881                                   0,
1882                                   &stIoStatus);
1883
1884                     if( !NT_SUCCESS( stIoStatus.Status))
1885                     {
1886
1887                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1888                                       AFS_TRACE_LEVEL_ERROR,
1889                                       "AFSInvalidateObject CcFlushCache failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
1890                                       (*ppObjectInfo)->FileId.Cell,
1891                                       (*ppObjectInfo)->FileId.Volume,
1892                                       (*ppObjectInfo)->FileId.Vnode,
1893                                       (*ppObjectInfo)->FileId.Unique,
1894                                       stIoStatus.Status,
1895                                       stIoStatus.Information));
1896
1897                         ntStatus = stIoStatus.Status;
1898                     }
1899
1900
1901                     if ( (*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
1902                     {
1903
1904                         if ( !CcPurgeCacheSection( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectPointers,
1905                                                    NULL,
1906                                                    0,
1907                                                    FALSE))
1908                         {
1909
1910                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
1911                                           AFS_TRACE_LEVEL_WARNING,
1912                                           "AFSInvalidateObject CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
1913                                           (*ppObjectInfo)->FileId.Cell,
1914                                           (*ppObjectInfo)->FileId.Volume,
1915                                           (*ppObjectInfo)->FileId.Vnode,
1916                                           (*ppObjectInfo)->FileId.Unique));
1917
1918                             SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1919                         }
1920                     }
1921                 }
1922                 __except( EXCEPTION_EXECUTE_HANDLER)
1923                 {
1924
1925                     ntStatus = GetExceptionCode();
1926
1927                     AFSDbgTrace(( 0,
1928                                   0,
1929                                   "EXCEPTION - AFSInvalidateObject Cc FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
1930                                   (*ppObjectInfo)->FileId.Cell,
1931                                   (*ppObjectInfo)->FileId.Volume,
1932                                   (*ppObjectInfo)->FileId.Vnode,
1933                                   (*ppObjectInfo)->FileId.Unique,
1934                                   ntStatus));
1935
1936                     SetFlag( (*ppObjectInfo)->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
1937                 }
1938
1939                 AFSReleaseResource( &(*ppObjectInfo)->Fcb->NPFcb->SectionObjectResource);
1940
1941                 //
1942                 // Clear out the extents
1943                 // Get rid of them (note this involves waiting
1944                 // for any writes or reads to the cache to complete)
1945                 //
1946
1947                 AFSTearDownFcbExtents( (*ppObjectInfo)->Fcb,
1948                                        NULL);
1949             }
1950
1951             (*ppObjectInfo)->DataVersion.QuadPart = (ULONGLONG)-1;
1952
1953
1954             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE)
1955             {
1956
1957                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1958                               AFS_TRACE_LEVEL_VERBOSE,
1959                               "AFSInvalidateObject Setting VERIFY_DATA flag on fid %08lX-%08lX-%08lX-%08lX\n",
1960                               (*ppObjectInfo)->FileId.Cell,
1961                               (*ppObjectInfo)->FileId.Volume,
1962                               (*ppObjectInfo)->FileId.Vnode,
1963                               (*ppObjectInfo)->FileId.Unique));
1964
1965                 SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY_DATA);
1966             }
1967
1968             // Fall through to the default processing
1969         }
1970
1971     default:
1972         {
1973
1974             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1975             {
1976                 ulFilter = FILE_NOTIFY_CHANGE_DIR_NAME;
1977             }
1978             else
1979             {
1980                 ulFilter = FILE_NOTIFY_CHANGE_FILE_NAME;
1981             }
1982
1983             if( Reason == AFS_INVALIDATE_CREDS)
1984             {
1985                 ulFilter |= FILE_NOTIFY_CHANGE_SECURITY;
1986             }
1987
1988             if( Reason == AFS_INVALIDATE_DATA_VERSION)
1989             {
1990                 ulFilter |= FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
1991             }
1992             else
1993             {
1994                 ulFilter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
1995             }
1996
1997             if( (*ppObjectInfo)->FileType == AFS_FILE_TYPE_DIRECTORY)
1998             {
1999
2000                 AFSFsRtlNotifyFullReportChange( (*ppObjectInfo),
2001                                                 NULL,
2002                                                 ulFilter,
2003                                                 FILE_ACTION_MODIFIED);
2004             }
2005             else if ( pParentObjectInfo != NULL)
2006             {
2007
2008                 AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
2009                                                 NULL,
2010                                                 ulFilter,
2011                                                 FILE_ACTION_MODIFIED);
2012             }
2013
2014             //
2015             // Indicate this node requires re-evaluation for the remaining reasons
2016             //
2017
2018             (*ppObjectInfo)->Expiration.QuadPart = 0;
2019
2020             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2021                           AFS_TRACE_LEVEL_VERBOSE,
2022                           "AFSInvalidateObject Setting VERIFY flag on fid %08lX-%08lX-%08lX-%08lX\n",
2023                           (*ppObjectInfo)->FileId.Cell,
2024                           (*ppObjectInfo)->FileId.Volume,
2025                           (*ppObjectInfo)->FileId.Vnode,
2026                           (*ppObjectInfo)->FileId.Unique));
2027
2028             SetFlag( (*ppObjectInfo)->Flags, AFS_OBJECT_FLAGS_VERIFY);
2029
2030             if( Reason == AFS_INVALIDATE_DATA_VERSION ||
2031                 (*ppObjectInfo)->FileType == AFS_FILE_TYPE_FILE &&
2032                 ( Reason == AFS_INVALIDATE_CALLBACK ||
2033                   Reason == AFS_INVALIDATE_EXPIRED))
2034             {
2035                 if ( NT_SUCCESS( AFSQueueInvalidateObject( (*ppObjectInfo),
2036                                                            AFS_INVALIDATE_DATA_VERSION)))
2037                 {
2038
2039                     (*ppObjectInfo) = NULL; // We'll dec the count in the worker item
2040                 }
2041             }
2042
2043             break;
2044         }
2045     }
2046
2047   try_exit:
2048
2049     if ( pParentObjectInfo != NULL)
2050     {
2051
2052         AFSReleaseObjectInfo( &pParentObjectInfo);
2053     }
2054
2055     return ntStatus;
2056 }
2057
2058 NTSTATUS
2059 AFSInvalidateCache( IN AFSInvalidateCacheCB *InvalidateCB)
2060 {
2061
2062     NTSTATUS ntStatus = STATUS_SUCCESS;
2063     AFSVolumeCB *pVolumeCB = NULL;
2064     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
2065     ULONGLONG   ullIndex = 0;
2066     AFSObjectInfoCB *pObjectInfo = NULL;
2067     LONG lCount;
2068
2069     __Enter
2070     {
2071
2072         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2073                       AFS_TRACE_LEVEL_VERBOSE,
2074                       "AFSInvalidateCache Invalidation FID %08lX-%08lX-%08lX-%08lX Type %d WholeVolume %d Reason %d\n",
2075                       InvalidateCB->FileID.Cell,
2076                       InvalidateCB->FileID.Volume,
2077                       InvalidateCB->FileID.Vnode,
2078                       InvalidateCB->FileID.Unique,
2079                       InvalidateCB->FileType,
2080                       InvalidateCB->WholeVolume,
2081                       InvalidateCB->Reason));
2082
2083         //
2084         // Need to locate the Fcb for the directory to purge
2085         //
2086
2087         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2088                       AFS_TRACE_LEVEL_VERBOSE,
2089                       "AFSInvalidateCache Acquiring RDR VolumeTreeLock lock %p SHARED %08lX\n",
2090                       &pDevExt->Specific.RDR.VolumeTreeLock,
2091                       PsGetCurrentThread()));
2092
2093         //
2094         // Starve any exclusive waiters on this paticular call
2095         //
2096
2097         AFSAcquireSharedStarveExclusive( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
2098
2099         //
2100         // Locate the volume node
2101         //
2102
2103         ullIndex = AFSCreateHighIndex( &InvalidateCB->FileID);
2104
2105         ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
2106                                        ullIndex,
2107                                        (AFSBTreeEntry **)&pVolumeCB);
2108
2109         if( pVolumeCB != NULL)
2110         {
2111
2112             lCount = AFSVolumeIncrement( pVolumeCB,
2113                                          AFS_VOLUME_REFERENCE_INVALIDATE);
2114
2115             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2116                           AFS_TRACE_LEVEL_VERBOSE,
2117                           "AFSInvalidateCache Increment count on volume %p Cnt %d\n",
2118                           pVolumeCB,
2119                           lCount));
2120         }
2121
2122         AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
2123
2124         if( !NT_SUCCESS( ntStatus) ||
2125             pVolumeCB == NULL)
2126         {
2127
2128             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2129                           AFS_TRACE_LEVEL_WARNING,
2130                           "AFSInvalidateCache Invalidation FAILURE Unable to locate volume node FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2131                           InvalidateCB->FileID.Cell,
2132                           InvalidateCB->FileID.Volume,
2133                           InvalidateCB->FileID.Vnode,
2134                           InvalidateCB->FileID.Unique,
2135                           ntStatus));
2136
2137             try_return( ntStatus = STATUS_SUCCESS);
2138         }
2139
2140         //
2141         // If this is a whole volume invalidation then go do it now
2142         //
2143
2144         if( InvalidateCB->WholeVolume)
2145         {
2146
2147             ntStatus = AFSInvalidateVolume( pVolumeCB,
2148                                             InvalidateCB->Reason);
2149
2150             try_return( ntStatus);
2151         }
2152
2153         AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
2154                           TRUE);
2155
2156         if ( AFSIsVolumeFID( &InvalidateCB->FileID))
2157         {
2158
2159             pObjectInfo = &pVolumeCB->ObjectInformation;
2160         }
2161         else
2162         {
2163
2164             ullIndex = AFSCreateLowIndex( &InvalidateCB->FileID);
2165
2166             ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
2167                                            ullIndex,
2168                                            (AFSBTreeEntry **)&pObjectInfo);
2169         }
2170
2171         if( pObjectInfo != NULL)
2172         {
2173
2174             //
2175             // Reference the node so it won't be torn down
2176             //
2177
2178             lCount = AFSObjectInfoIncrement( pObjectInfo,
2179                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2180
2181             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2182                           AFS_TRACE_LEVEL_VERBOSE,
2183                           "AFSInvalidateCache Increment count on object %p Cnt %d\n",
2184                           pObjectInfo,
2185                           lCount));
2186         }
2187
2188         AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
2189
2190         if( !NT_SUCCESS( ntStatus) ||
2191             pObjectInfo == NULL)
2192         {
2193
2194             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2195                           AFS_TRACE_LEVEL_VERBOSE,
2196                           "AFSInvalidateCache Invalidation FAILURE Unable to locate object FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2197                           InvalidateCB->FileID.Cell,
2198                           InvalidateCB->FileID.Volume,
2199                           InvalidateCB->FileID.Vnode,
2200                           InvalidateCB->FileID.Unique,
2201                           ntStatus));
2202
2203             try_return( ntStatus = STATUS_SUCCESS);
2204         }
2205
2206         AFSInvalidateObject( &pObjectInfo,
2207                              InvalidateCB->Reason);
2208
2209 try_exit:
2210
2211         if( pObjectInfo != NULL)
2212         {
2213
2214             lCount = AFSObjectInfoDecrement( pObjectInfo,
2215                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2216
2217             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2218                           AFS_TRACE_LEVEL_VERBOSE,
2219                           "AFSInvalidateCache Decrement count on object %p Cnt %d\n",
2220                           pObjectInfo,
2221                           lCount));
2222         }
2223
2224         if ( pVolumeCB != NULL)
2225         {
2226
2227             lCount = AFSVolumeDecrement( pVolumeCB,
2228                                          AFS_VOLUME_REFERENCE_INVALIDATE);
2229
2230             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
2231                           AFS_TRACE_LEVEL_VERBOSE,
2232                           "AFSInvalidateCache Decrement count on volume %p Cnt %d\n",
2233                           pVolumeCB,
2234                           lCount));
2235         }
2236     }
2237
2238     return ntStatus;
2239 }
2240
2241 BOOLEAN
2242 AFSIsChildOfParent( IN AFSFcb *Dcb,
2243                     IN AFSFcb *Fcb)
2244 {
2245
2246     BOOLEAN bIsChild = FALSE;
2247     AFSFcb *pCurrentFcb = Fcb;
2248     AFSObjectInfoCB * pParentObjectInfo = NULL;
2249
2250     while( pCurrentFcb != NULL)
2251     {
2252
2253         if( BooleanFlagOn( pCurrentFcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
2254             AFSIsEqualFID( &pCurrentFcb->ObjectInformation->ParentFileId, &Dcb->ObjectInformation->FileId))
2255         {
2256
2257             bIsChild = TRUE;
2258
2259             break;
2260         }
2261
2262         pParentObjectInfo = AFSFindObjectInfo( pCurrentFcb->ObjectInformation->VolumeCB,
2263                                                &pCurrentFcb->ObjectInformation->ParentFileId);
2264
2265         if ( pParentObjectInfo != NULL)
2266         {
2267
2268             pCurrentFcb = pParentObjectInfo->Fcb;
2269
2270             AFSReleaseObjectInfo( &pParentObjectInfo);
2271         }
2272         else
2273         {
2274
2275             pCurrentFcb = NULL;
2276         }
2277     }
2278
2279     return bIsChild;
2280 }
2281
2282 inline
2283 ULONGLONG
2284 AFSCreateHighIndex( IN AFSFileID *FileID)
2285 {
2286
2287     ULONGLONG ullIndex = 0;
2288
2289     ullIndex = (((ULONGLONG)FileID->Cell << 32) | FileID->Volume);
2290
2291     return ullIndex;
2292 }
2293
2294 inline
2295 ULONGLONG
2296 AFSCreateLowIndex( IN AFSFileID *FileID)
2297 {
2298
2299     ULONGLONG ullIndex = 0;
2300
2301     ullIndex = (((ULONGLONG)FileID->Vnode << 32) | FileID->Unique);
2302
2303     return ullIndex;
2304 }
2305
2306 BOOLEAN
2307 AFSCheckAccess( IN ACCESS_MASK DesiredAccess,
2308                 IN ACCESS_MASK GrantedAccess,
2309                 IN BOOLEAN DirectoryEntry)
2310 {
2311
2312     BOOLEAN bAccessGranted = TRUE;
2313
2314     //
2315     // Check if we are asking for read/write and granted only read only
2316     // NOTE: There will be more checks here
2317     //
2318
2319     if( !AFSCheckForReadOnlyAccess( DesiredAccess,
2320                                     DirectoryEntry) &&
2321         AFSCheckForReadOnlyAccess( GrantedAccess,
2322                                    DirectoryEntry))
2323     {
2324
2325         bAccessGranted = FALSE;
2326     }
2327
2328     return bAccessGranted;
2329 }
2330
2331 NTSTATUS
2332 AFSGetDriverStatus( IN AFSDriverStatusRespCB *DriverStatus)
2333 {
2334
2335     NTSTATUS         ntStatus = STATUS_SUCCESS;
2336     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2337
2338     //
2339     // Start with read
2340     //
2341
2342     DriverStatus->Status = AFS_DRIVER_STATUS_READY;
2343
2344     if( AFSGlobalRoot == NULL)
2345     {
2346
2347         //
2348         // We are not ready
2349         //
2350
2351         DriverStatus->Status = AFS_DRIVER_STATUS_NOT_READY;
2352     }
2353
2354     if( pControlDevExt->Specific.Control.CommServiceCB.IrpPoolControlFlag != POOL_ACTIVE)
2355     {
2356
2357         //
2358         // No service yet
2359         //
2360
2361         DriverStatus->Status = AFS_DRIVER_STATUS_NO_SERVICE;
2362     }
2363
2364     return ntStatus;
2365 }
2366
2367 NTSTATUS
2368 AFSSubstituteSysName( IN UNICODE_STRING *ComponentName,
2369                       IN UNICODE_STRING *SubstituteName,
2370                       IN ULONG StringIndex)
2371 {
2372
2373     NTSTATUS ntStatus = STATUS_SUCCESS;
2374     AFSDeviceExt    *pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2375     AFSSysNameCB    *pSysName = NULL;
2376     ERESOURCE       *pSysNameLock = NULL;
2377     ULONG            ulIndex = 1;
2378     USHORT           usIndex = 0;
2379     UNICODE_STRING   uniSysName;
2380
2381     __Enter
2382     {
2383
2384 #if defined(_WIN64)
2385
2386         if( IoIs32bitProcess( NULL))
2387         {
2388
2389             pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2390
2391             pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2392         }
2393         else
2394         {
2395
2396             pSysNameLock = &pControlDevExt->Specific.Control.SysName64ListLock;
2397
2398             pSysName = pControlDevExt->Specific.Control.SysName64ListHead;
2399         }
2400 #else
2401
2402         pSysNameLock = &pControlDevExt->Specific.Control.SysName32ListLock;
2403
2404         pSysName = pControlDevExt->Specific.Control.SysName32ListHead;
2405
2406 #endif
2407
2408         AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2409                       AFS_TRACE_LEVEL_VERBOSE,
2410                       "AFSSubstituteSysName Acquiring SysName lock %p SHARED %08lX\n",
2411                       pSysNameLock,
2412                       PsGetCurrentThread()));
2413
2414         AFSAcquireShared( pSysNameLock,
2415                           TRUE);
2416
2417         //
2418         // Find where we are in the list
2419         //
2420
2421         while( pSysName != NULL &&
2422             ulIndex < StringIndex)
2423         {
2424
2425             pSysName = pSysName->fLink;
2426
2427             ulIndex++;
2428         }
2429
2430         if( pSysName == NULL)
2431         {
2432
2433             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2434                           AFS_TRACE_LEVEL_VERBOSE_2,
2435                           "AFSSubstituteSysName No sysname %wZ Status %08lX\n",
2436                           &ComponentName,
2437                           STATUS_OBJECT_NAME_NOT_FOUND));
2438
2439             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
2440         }
2441
2442         RtlInitUnicodeString( &uniSysName,
2443                               L"@SYS");
2444         //
2445         // If it is a full component of @SYS then just substitue the
2446         // name in
2447         //
2448
2449         if( RtlCompareUnicodeString( &uniSysName,
2450                                      ComponentName,
2451                                      TRUE) == 0)
2452         {
2453
2454             SubstituteName->Length = pSysName->SysName.Length;
2455             SubstituteName->MaximumLength = SubstituteName->Length;
2456
2457             SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2458                                                                         SubstituteName->Length,
2459                                                                         AFS_SUBST_BUFFER_TAG);
2460
2461             if( SubstituteName->Buffer == NULL)
2462             {
2463
2464                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2465             }
2466
2467             RtlCopyMemory( SubstituteName->Buffer,
2468                            pSysName->SysName.Buffer,
2469                            pSysName->SysName.Length);
2470         }
2471         else
2472         {
2473
2474             usIndex = 0;
2475
2476             while( ComponentName->Buffer[ usIndex] != L'@')
2477             {
2478
2479                 usIndex++;
2480             }
2481
2482             SubstituteName->Length = (usIndex * sizeof( WCHAR)) + pSysName->SysName.Length;
2483             SubstituteName->MaximumLength = SubstituteName->Length;
2484
2485             SubstituteName->Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2486                                                                         SubstituteName->Length,
2487                                                                         AFS_SUBST_BUFFER_TAG);
2488
2489             if( SubstituteName->Buffer == NULL)
2490             {
2491
2492                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2493             }
2494
2495             RtlCopyMemory( SubstituteName->Buffer,
2496                            ComponentName->Buffer,
2497                            usIndex * sizeof( WCHAR));
2498
2499             RtlCopyMemory( &SubstituteName->Buffer[ usIndex],
2500                            pSysName->SysName.Buffer,
2501                            pSysName->SysName.Length);
2502         }
2503
2504 try_exit:
2505
2506         AFSReleaseResource( pSysNameLock);
2507     }
2508
2509     return ntStatus;
2510 }
2511
2512 NTSTATUS
2513 AFSSubstituteNameInPath( IN OUT UNICODE_STRING *FullPathName,
2514                          IN OUT UNICODE_STRING *ComponentName,
2515                          IN UNICODE_STRING *SubstituteName,
2516                          IN OUT UNICODE_STRING *RemainingPath,
2517                          IN BOOLEAN FreePathName)
2518 {
2519
2520     NTSTATUS ntStatus = STATUS_SUCCESS;
2521     UNICODE_STRING uniPathName;
2522     USHORT usPrefixNameLen = 0;
2523     SHORT  sNameLenDelta = 0;
2524
2525     __Enter
2526     {
2527
2528         //
2529         // If the passed in name can handle the additional length
2530         // then just moves things around
2531         //
2532
2533         sNameLenDelta = SubstituteName->Length - ComponentName->Length;
2534
2535         usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2536
2537         if( FullPathName->MaximumLength > FullPathName->Length + sNameLenDelta)
2538         {
2539
2540             if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2541             {
2542
2543                 RtlMoveMemory( &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + SubstituteName->Length)/sizeof( WCHAR))],
2544                                &FullPathName->Buffer[ ((usPrefixNameLen*sizeof( WCHAR) + ComponentName->Length)/sizeof( WCHAR))],
2545                                FullPathName->Length - usPrefixNameLen*sizeof( WCHAR) - ComponentName->Length);
2546             }
2547
2548             RtlCopyMemory( &FullPathName->Buffer[ usPrefixNameLen],
2549                            SubstituteName->Buffer,
2550                            SubstituteName->Length);
2551
2552             FullPathName->Length += sNameLenDelta;
2553
2554             ComponentName->Length += sNameLenDelta;
2555
2556             ComponentName->MaximumLength = ComponentName->Length;
2557
2558             if ( RemainingPath->Buffer)
2559             {
2560
2561                 RemainingPath->Buffer += sNameLenDelta/sizeof( WCHAR);
2562             }
2563
2564             try_return( ntStatus);
2565         }
2566
2567         //
2568         // Need to re-allocate the buffer
2569         //
2570
2571         uniPathName.Length = FullPathName->Length -
2572                                          ComponentName->Length +
2573                                          SubstituteName->Length;
2574
2575         uniPathName.MaximumLength = FullPathName->MaximumLength + PAGE_SIZE;
2576
2577         uniPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
2578                                                                 uniPathName.MaximumLength,
2579                                                                 AFS_NAME_BUFFER_FOUR_TAG);
2580
2581         if( uniPathName.Buffer == NULL)
2582         {
2583
2584             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2585         }
2586
2587         usPrefixNameLen = (USHORT)(ComponentName->Buffer - FullPathName->Buffer);
2588
2589         usPrefixNameLen *= sizeof( WCHAR);
2590
2591         RtlZeroMemory( uniPathName.Buffer,
2592                        uniPathName.MaximumLength);
2593
2594         RtlCopyMemory( uniPathName.Buffer,
2595                        FullPathName->Buffer,
2596                        usPrefixNameLen);
2597
2598         RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen/sizeof( WCHAR))],
2599                        SubstituteName->Buffer,
2600                        SubstituteName->Length);
2601
2602         if( FullPathName->Length > usPrefixNameLen + ComponentName->Length)
2603         {
2604
2605             RtlCopyMemory( &uniPathName.Buffer[ (usPrefixNameLen + SubstituteName->Length)/sizeof( WCHAR)],
2606                            &FullPathName->Buffer[ (usPrefixNameLen + ComponentName->Length)/sizeof( WCHAR)],
2607                            FullPathName->Length - usPrefixNameLen - ComponentName->Length);
2608         }
2609
2610         ComponentName->Buffer = uniPathName.Buffer + (ComponentName->Buffer - FullPathName->Buffer);
2611
2612         ComponentName->Length += sNameLenDelta;
2613
2614         ComponentName->MaximumLength = ComponentName->Length;
2615
2616         if ( RemainingPath->Buffer)
2617         {
2618
2619             RemainingPath->Buffer = uniPathName.Buffer
2620                 + (RemainingPath->Buffer - FullPathName->Buffer)
2621                 + sNameLenDelta/sizeof( WCHAR);
2622         }
2623
2624         if( FreePathName)
2625         {
2626             AFSExFreePoolWithTag( FullPathName->Buffer, 0);
2627         }
2628
2629         *FullPathName = uniPathName;
2630
2631 try_exit:
2632
2633         NOTHING;
2634     }
2635
2636     return ntStatus;
2637 }
2638
2639 NTSTATUS
2640 AFSInvalidateVolume( IN AFSVolumeCB *VolumeCB,
2641                      IN ULONG Reason)
2642 {
2643
2644     NTSTATUS ntStatus = STATUS_SUCCESS;
2645     AFSObjectInfoCB *pCurrentObject = NULL;
2646     AFSObjectInfoCB *pNextObject = NULL;
2647     LONG lCount;
2648
2649     __Enter
2650     {
2651
2652         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2653                       AFS_TRACE_LEVEL_VERBOSE,
2654                       "AFSInvalidateVolume Invalidate volume fid %08lX-%08lX-%08lX-%08lX Reason %08lX\n",
2655                       VolumeCB->ObjectInformation.FileId.Cell,
2656                       VolumeCB->ObjectInformation.FileId.Volume,
2657                       VolumeCB->ObjectInformation.FileId.Vnode,
2658                       VolumeCB->ObjectInformation.FileId.Unique,
2659                       Reason));
2660
2661         //
2662         // Depending on the reason for invalidation then perform work on the node
2663         //
2664
2665         switch( Reason)
2666         {
2667
2668             case AFS_INVALIDATE_DELETED:
2669             {
2670
2671                 //
2672                 // Mark this volume as invalid
2673                 //
2674
2675                 SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID);
2676
2677                 SetFlag( VolumeCB->Flags, AFS_VOLUME_FLAGS_OFFLINE);
2678
2679                 break;
2680             }
2681         }
2682
2683         //
2684         // Invalidate the volume root directory
2685         //
2686
2687         pCurrentObject = &VolumeCB->ObjectInformation;
2688
2689         if ( pCurrentObject )
2690         {
2691
2692             lCount = AFSObjectInfoIncrement( pCurrentObject,
2693                                              AFS_OBJECT_REFERENCE_INVALIDATION);
2694
2695             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2696                           AFS_TRACE_LEVEL_VERBOSE,
2697                           "AFSInvalidateVolumeObjects Increment count on object %p Cnt %d\n",
2698                           pCurrentObject,
2699                           lCount));
2700
2701             AFSInvalidateObject( &pCurrentObject,
2702                                  Reason);
2703
2704             if ( pCurrentObject)
2705             {
2706
2707                 lCount = AFSObjectInfoDecrement( pCurrentObject,
2708                                                  AFS_OBJECT_REFERENCE_INVALIDATION);
2709
2710                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2711                               AFS_TRACE_LEVEL_VERBOSE,
2712                               "AFSInvalidateVolumeObjects Decrement count on object %p Cnt %d\n",
2713                               pCurrentObject,
2714                               lCount));
2715             }
2716         }
2717
2718         //
2719         // Apply invalidation to all other volume objects
2720         //
2721
2722         AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2723                           TRUE);
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             if ( pCurrentObject )
2772             {
2773
2774                 lCount = AFSObjectInfoDecrement( pCurrentObject,
2775                                                  AFS_OBJECT_REFERENCE_INVALIDATION);
2776
2777                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2778                               AFS_TRACE_LEVEL_VERBOSE,
2779                               "AFSInvalidateVolumeObjects Decrement count on object %p Cnt %d\n",
2780                               pCurrentObject,
2781                               lCount));
2782             }
2783
2784             AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
2785                               TRUE);
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         pObjectInfoCB = AFSAllocateObjectInfo( ParentObjectInfo,
5342                                                0);
5343
5344         if( pObjectInfoCB == NULL)
5345         {
5346
5347             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5348         }
5349
5350         lCount = AFSObjectInfoIncrement( pObjectInfoCB,
5351                                          AFS_OBJECT_REFERENCE_PIOCTL);
5352
5353         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
5354                       AFS_TRACE_LEVEL_VERBOSE,
5355                       "AFSInitPIOCtlDirectoryCB Increment count on object %p Cnt %d\n",
5356                       pObjectInfoCB,
5357                       lCount));
5358
5359         pObjectInfoCB->FileType = (ULONG) AFS_FILE_TYPE_PIOCTL;
5360
5361         pObjectInfoCB->FileAttributes = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
5362
5363         ulEntryLength = sizeof( AFSDirectoryCB) + AFSPIOCtlName.Length;
5364
5365         pDirNode = (AFSDirectoryCB *)AFSExAllocatePoolWithTag( PagedPool,
5366                                                                ulEntryLength,
5367                                                                AFS_DIR_ENTRY_TAG);
5368
5369         if( pDirNode == NULL)
5370         {
5371
5372             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5373         }
5374
5375         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
5376                       AFS_TRACE_LEVEL_VERBOSE,
5377                       "AFSInitPIOCtlDirectoryCB AFS_DIR_ENTRY_TAG allocated %p\n",
5378                       pDirNode));
5379
5380         pNonPagedDirEntry = (AFSNonPagedDirectoryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
5381                                                                                 sizeof( AFSNonPagedDirectoryCB),
5382                                                                                 AFS_DIR_ENTRY_NP_TAG);
5383
5384         if( pNonPagedDirEntry == NULL)
5385         {
5386
5387             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5388         }
5389
5390         RtlZeroMemory( pDirNode,
5391                        ulEntryLength);
5392
5393         RtlZeroMemory( pNonPagedDirEntry,
5394                        sizeof( AFSNonPagedDirectoryCB));
5395
5396         ExInitializeResourceLite( &pNonPagedDirEntry->Lock);
5397
5398         pDirNode->NonPaged = pNonPagedDirEntry;
5399
5400         pDirNode->ObjectInformation = pObjectInfoCB;
5401
5402         pDirNode->FileIndex = (ULONG)AFS_DIR_ENTRY_PIOCTL_INDEX;
5403
5404         //
5405         // Set valid entry
5406         //
5407
5408         SetFlag( pDirNode->Flags, AFS_DIR_ENTRY_VALID | AFS_DIR_ENTRY_FAKE);
5409
5410         pDirNode->NameInformation.FileName.Length = AFSPIOCtlName.Length;
5411
5412         pDirNode->NameInformation.FileName.MaximumLength = AFSPIOCtlName.Length;
5413
5414         pDirNode->NameInformation.FileName.Buffer = (WCHAR *)((char *)pDirNode + sizeof( AFSDirectoryCB));
5415
5416         RtlCopyMemory( pDirNode->NameInformation.FileName.Buffer,
5417                        AFSPIOCtlName.Buffer,
5418                        pDirNode->NameInformation.FileName.Length);
5419
5420         pDirNode->CaseInsensitiveTreeEntry.HashIndex = AFSGenerateCRC( &pDirNode->NameInformation.FileName,
5421                                                                        TRUE);
5422
5423         if ( InterlockedCompareExchangePointer( (PVOID *)&ParentObjectInfo->Specific.Directory.PIOCtlDirectoryCB, pDirNode, NULL) != NULL)
5424         {
5425
5426             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5427                           AFS_TRACE_LEVEL_WARNING,
5428                           "AFSInitPIOCtlDirectoryCB Raced PIOCtlDirectoryCB %p pFcb %p\n",
5429                           ParentObjectInfo->Specific.Directory.PIOCtlDirectoryCB,
5430                           pDirNode));
5431
5432             try_return( ntStatus = STATUS_REPARSE);
5433         }
5434
5435 try_exit:
5436
5437         if ( ntStatus != STATUS_SUCCESS)
5438         {
5439
5440             if ( pDirNode != NULL)
5441             {
5442
5443                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
5444                               AFS_TRACE_LEVEL_VERBOSE,
5445                               "AFSInitPIOCtlDirectoryCB AFS_DIR_ENTRY_TAG deallocating %p\n",
5446                               pDirNode));
5447
5448                 AFSExFreePoolWithTag( pDirNode, AFS_DIR_ENTRY_TAG);
5449             }
5450
5451             if( pNonPagedDirEntry != NULL)
5452             {
5453
5454                 ExDeleteResourceLite( &pNonPagedDirEntry->Lock);
5455
5456                 AFSExFreePoolWithTag( pNonPagedDirEntry, AFS_DIR_ENTRY_NP_TAG);
5457             }
5458
5459             if ( pObjectInfoCB != NULL)
5460             {
5461
5462                 lCount = AFSObjectInfoDecrement( pObjectInfoCB,
5463                                                  AFS_OBJECT_REFERENCE_PIOCTL);
5464
5465                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
5466                               AFS_TRACE_LEVEL_VERBOSE,
5467                               "AFSInitPIOCtlDirectoryCB Decrement count on object %p Cnt %d\n",
5468                               pObjectInfoCB,
5469                               lCount));
5470
5471                 if ( lCount == 0)
5472                 {
5473
5474                     AFSDeleteObjectInfo( &pObjectInfoCB);
5475                 }
5476             }
5477         }
5478     }
5479
5480     return ntStatus;
5481 }
5482
5483 NTSTATUS
5484 AFSRetrieveFileAttributes( IN AFSDirectoryCB *ParentDirectoryCB,
5485                            IN AFSDirectoryCB *DirectoryCB,
5486                            IN UNICODE_STRING *ParentPathName,
5487                            IN AFSNameArrayHdr *RelatedNameArray,
5488                            IN GUID           *AuthGroup,
5489                            OUT AFSFileInfoCB *FileInfo)
5490 {
5491
5492     NTSTATUS ntStatus = STATUS_SUCCESS;
5493     AFSDirEnumEntry *pDirEntry = NULL;
5494     UNICODE_STRING uniFullPathName = {0};
5495     AFSNameArrayHdr    *pNameArray = NULL;
5496     AFSVolumeCB *pVolumeCB = NULL;
5497     LONG VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
5498     AFSVolumeCB *pNewVolumeCB = NULL;
5499     LONG NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
5500     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
5501     AFSDirectoryCB *pNewParentDirEntry = NULL;
5502     WCHAR *pwchBuffer = NULL;
5503     UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
5504     ULONG ulNameDifference = 0;
5505     LONG lCount;
5506
5507     __Enter
5508     {
5509
5510         //
5511         // Retrieve a target name for the entry
5512         //
5513
5514         AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
5515                           TRUE);
5516
5517         if( DirectoryCB->NameInformation.TargetName.Length == 0)
5518         {
5519
5520             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5521
5522             ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
5523                                               AuthGroup,
5524                                               FALSE,
5525                                               &pDirEntry);
5526
5527             if( !NT_SUCCESS( ntStatus) ||
5528                 pDirEntry->TargetNameLength == 0)
5529             {
5530
5531                 if( pDirEntry != NULL)
5532                 {
5533
5534                     ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
5535                 }
5536
5537                 try_return( ntStatus);
5538             }
5539
5540             AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
5541                             TRUE);
5542
5543             if( DirectoryCB->NameInformation.TargetName.Length == 0)
5544             {
5545
5546                 //
5547                 // Update the target name
5548                 //
5549
5550                 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
5551                                                 &DirectoryCB->Flags,
5552                                                 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
5553                                                 (USHORT)pDirEntry->TargetNameLength);
5554
5555                 if( !NT_SUCCESS( ntStatus))
5556                 {
5557
5558                     AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5559
5560                     try_return( ntStatus);
5561                 }
5562             }
5563
5564             AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
5565         }
5566
5567         //
5568         // Need to pass the full path in for parsing.
5569         //
5570
5571         if( AFSIsRelativeName( &DirectoryCB->NameInformation.TargetName))
5572         {
5573
5574             uniFullPathName.Length = 0;
5575             uniFullPathName.MaximumLength = ParentPathName->Length +
5576                                                     sizeof( WCHAR) +
5577                                                     DirectoryCB->NameInformation.TargetName.Length;
5578
5579             uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5580                                                                         uniFullPathName.MaximumLength,
5581                                                                         AFS_NAME_BUFFER_SIX_TAG);
5582
5583             if( uniFullPathName.Buffer == NULL)
5584             {
5585
5586                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5587
5588                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5589             }
5590
5591             pwchBuffer = uniFullPathName.Buffer;
5592
5593             RtlZeroMemory( uniFullPathName.Buffer,
5594                            uniFullPathName.MaximumLength);
5595
5596             RtlCopyMemory( uniFullPathName.Buffer,
5597                            ParentPathName->Buffer,
5598                            ParentPathName->Length);
5599
5600             uniFullPathName.Length = ParentPathName->Length;
5601
5602             if( uniFullPathName.Buffer[ (uniFullPathName.Length/sizeof( WCHAR)) - 1] != L'\\' &&
5603                 DirectoryCB->NameInformation.TargetName.Buffer[ 0] != L'\\')
5604             {
5605
5606                 uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)] = L'\\';
5607
5608                 uniFullPathName.Length += sizeof( WCHAR);
5609             }
5610
5611             RtlCopyMemory( &uniFullPathName.Buffer[ uniFullPathName.Length/sizeof( WCHAR)],
5612                            DirectoryCB->NameInformation.TargetName.Buffer,
5613                            DirectoryCB->NameInformation.TargetName.Length);
5614
5615             uniFullPathName.Length += DirectoryCB->NameInformation.TargetName.Length;
5616
5617             uniParsedName.Length = uniFullPathName.Length - ParentPathName->Length;
5618             uniParsedName.MaximumLength = uniParsedName.Length;
5619
5620             uniParsedName.Buffer = &uniFullPathName.Buffer[ ParentPathName->Length/sizeof( WCHAR)];
5621
5622             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5623
5624             //
5625             // We populate up to the current parent
5626             //
5627
5628             if( RelatedNameArray != NULL)
5629             {
5630
5631                 pNameArray = AFSInitNameArray( NULL,
5632                                                RelatedNameArray->MaxElementCount);
5633
5634                 if( pNameArray == NULL)
5635                 {
5636
5637                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5638                 }
5639
5640                 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArray,
5641                                                                  RelatedNameArray,
5642                                                                  ParentDirectoryCB);
5643             }
5644             else
5645             {
5646
5647                 pNameArray = AFSInitNameArray( NULL,
5648                                                0);
5649
5650                 if( pNameArray == NULL)
5651                 {
5652
5653                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5654                 }
5655
5656                 ntStatus = AFSPopulateNameArray( pNameArray,
5657                                                  NULL,
5658                                                  ParentDirectoryCB);
5659             }
5660
5661             if( !NT_SUCCESS( ntStatus))
5662             {
5663
5664                 try_return( ntStatus);
5665             }
5666
5667             pVolumeCB = ParentDirectoryCB->ObjectInformation->VolumeCB;
5668
5669             pParentDirEntry = ParentDirectoryCB;
5670         }
5671         else
5672         {
5673
5674             uniFullPathName.Length = 0;
5675             uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
5676
5677             uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
5678                                                                         uniFullPathName.MaximumLength,
5679                                                                         AFS_NAME_BUFFER_SEVEN_TAG);
5680
5681             if( uniFullPathName.Buffer == NULL)
5682             {
5683
5684                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5685
5686                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5687             }
5688
5689             pwchBuffer = uniFullPathName.Buffer;
5690
5691             RtlZeroMemory( uniFullPathName.Buffer,
5692                            uniFullPathName.MaximumLength);
5693
5694             RtlCopyMemory( uniFullPathName.Buffer,
5695                            DirectoryCB->NameInformation.TargetName.Buffer,
5696                            DirectoryCB->NameInformation.TargetName.Length);
5697
5698             uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
5699
5700             //
5701             // This name should begin with the \afs server so parse it off and check it
5702             //
5703
5704             FsRtlDissectName( uniFullPathName,
5705                               &uniComponentName,
5706                               &uniRemainingPath);
5707
5708             if( RtlCompareUnicodeString( &uniComponentName,
5709                                          &AFSServerName,
5710                                          TRUE) != 0)
5711             {
5712
5713                 AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5714
5715                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
5716                               AFS_TRACE_LEVEL_ERROR,
5717                               "AFSRetrieveFileAttributes Name %wZ contains invalid server name\n",
5718                               &uniFullPathName));
5719
5720                 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
5721             }
5722
5723             uniFullPathName = uniRemainingPath;
5724
5725             uniParsedName = uniFullPathName;
5726
5727             ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
5728
5729             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
5730
5731             //
5732             // Our name array
5733             //
5734
5735             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
5736                                            0);
5737
5738             if( pNameArray == NULL)
5739             {
5740
5741                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
5742             }
5743
5744             pVolumeCB = AFSGlobalRoot;
5745
5746             pParentDirEntry = AFSGlobalRoot->DirectoryCB;
5747         }
5748
5749         //
5750         // Increment the ref count on the volume and dir entry for correct processing below
5751         //
5752
5753         VolumeReferenceReason = AFS_VOLUME_REFERENCE_FILE_ATTRS;
5754
5755         lCount = AFSVolumeIncrement( pVolumeCB,
5756                                      VolumeReferenceReason);
5757
5758         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
5759                       AFS_TRACE_LEVEL_VERBOSE,
5760                       "AFSRetrieveFileAttributes Increment count on volume %p Reason %u Cnt %d\n",
5761                       pVolumeCB,
5762                       VolumeReferenceReason,
5763                       lCount));
5764
5765         lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
5766
5767         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5768                       AFS_TRACE_LEVEL_VERBOSE,
5769                       "AFSRetrieveFileAttributes Increment count on %wZ DE %p Ccb %p Cnt %d\n",
5770                       &pParentDirEntry->NameInformation.FileName,
5771                       pParentDirEntry,
5772                       NULL,
5773                       lCount));
5774
5775         ntStatus = AFSLocateNameEntry( NULL,
5776                                        NULL,
5777                                        &uniFullPathName,
5778                                        &uniParsedName,
5779                                        pNameArray,
5780                                        AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL,
5781                                        pVolumeCB,
5782                                        pParentDirEntry,
5783                                        &pNewVolumeCB,
5784                                        &NewVolumeReferenceReason,
5785                                        &pNewParentDirEntry,
5786                                        &pDirectoryEntry,
5787                                        NULL);
5788
5789         if ( pNewVolumeCB != NULL)
5790         {
5791             //
5792             // AFSLocateNameEntry returns pNewVolumeCB with a reference held
5793             // even if pVolumeCB == pNewVolumeCB.  It is always safe to release
5794             // the reference on pVolumeCB that was held prior to the call.
5795             // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
5796             // will be released second.
5797             //
5798
5799             lCount = AFSVolumeDecrement( pVolumeCB,
5800                                          VolumeReferenceReason);
5801
5802             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
5803                           AFS_TRACE_LEVEL_VERBOSE,
5804                           "AFSRetrieveFileAttributes Decrement count on volume %p Reason %u Cnt %d\n",
5805                           pVolumeCB,
5806                           VolumeReferenceReason,
5807                           lCount));
5808
5809             pVolumeCB = pNewVolumeCB;
5810
5811             pNewVolumeCB = NULL;
5812
5813             VolumeReferenceReason = NewVolumeReferenceReason;
5814
5815             NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
5816         }
5817
5818         //
5819         // AFSLocateNameEntry does not alter the reference count of
5820         // pParentDirectoryCB and it returns pNewParentDirectoryCB with
5821         // a reference held.
5822         //
5823
5824         lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
5825
5826         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5827                       AFS_TRACE_LEVEL_VERBOSE,
5828                       "AFSRetrieveFileAttributes DecrementX count on %wZ DE %p Cnt %d\n",
5829                       &pParentDirEntry->NameInformation.FileName,
5830                       pParentDirEntry,
5831                       lCount));
5832
5833         pParentDirEntry = pNewParentDirEntry;
5834
5835         pNewParentDirEntry = NULL;
5836
5837         if( !NT_SUCCESS( ntStatus) ||
5838             ntStatus == STATUS_REPARSE)
5839         {
5840
5841             try_return( ntStatus);
5842         }
5843
5844         //
5845         // Store off the information
5846         //
5847
5848         FileInfo->FileAttributes = pDirectoryEntry->ObjectInformation->FileAttributes;
5849
5850         //
5851         // Check for the mount point being returned
5852         //
5853
5854         if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_MOUNTPOINT ||
5855             pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DFSLINK)
5856         {
5857
5858             FileInfo->FileAttributes |= (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
5859         }
5860         else if( pDirectoryEntry->ObjectInformation->FileType == AFS_FILE_TYPE_SYMLINK)
5861         {
5862
5863             if ( FileInfo->FileAttributes == FILE_ATTRIBUTE_NORMAL)
5864             {
5865
5866                 FileInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT;
5867             }
5868             else
5869             {
5870
5871                 FileInfo->FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
5872             }
5873         }
5874
5875         FileInfo->AllocationSize = pDirectoryEntry->ObjectInformation->AllocationSize;
5876
5877         FileInfo->EndOfFile = pDirectoryEntry->ObjectInformation->EndOfFile;
5878
5879         FileInfo->CreationTime = pDirectoryEntry->ObjectInformation->CreationTime;
5880
5881         FileInfo->LastAccessTime = pDirectoryEntry->ObjectInformation->LastAccessTime;
5882
5883         FileInfo->LastWriteTime = pDirectoryEntry->ObjectInformation->LastWriteTime;
5884
5885         FileInfo->ChangeTime = pDirectoryEntry->ObjectInformation->ChangeTime;
5886
5887 try_exit:
5888
5889         if( pDirEntry != NULL)
5890         {
5891
5892             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
5893         }
5894
5895         if( pDirectoryEntry != NULL)
5896         {
5897
5898             lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
5899
5900             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5901                           AFS_TRACE_LEVEL_VERBOSE,
5902                           "AFSRetrieveFileAttributes Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
5903                           &pDirectoryEntry->NameInformation.FileName,
5904                           pDirectoryEntry,
5905                           NULL,
5906                           lCount));
5907
5908             ASSERT( lCount >= 0);
5909         }
5910
5911         if ( pParentDirEntry != NULL)
5912         {
5913
5914             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
5915
5916             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
5917                           AFS_TRACE_LEVEL_VERBOSE,
5918                           "AFSRetrieveFileAttributes Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
5919                           &pParentDirEntry->NameInformation.FileName,
5920                           pParentDirEntry,
5921                           NULL,
5922                           lCount));
5923
5924             ASSERT( lCount >= 0);
5925         }
5926
5927         if( pVolumeCB != NULL)
5928         {
5929
5930             lCount = AFSVolumeDecrement( pVolumeCB,
5931                                          VolumeReferenceReason);
5932
5933             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
5934                           AFS_TRACE_LEVEL_VERBOSE,
5935                           "AFSRetrieveFileAttributes Decrement2 count on volume %p Reason %u Cnt %d\n",
5936                           pVolumeCB,
5937                           VolumeReferenceReason,
5938                           lCount));
5939         }
5940
5941         if( pNameArray != NULL)
5942         {
5943
5944             AFSFreeNameArray( pNameArray);
5945         }
5946
5947         if( pwchBuffer != NULL)
5948         {
5949
5950             //
5951             // Always free the buffer that we allocated as AFSLocateNameEntry
5952             // will not free it.  If uniFullPathName.Buffer was allocated by
5953             // AFSLocateNameEntry, then we must free that as well.
5954             // Check that the uniFullPathName.Buffer in the string is not the same
5955             // offset by the length of the server name
5956             //
5957
5958             if( uniFullPathName.Length > 0 &&
5959                 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
5960             {
5961
5962                 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
5963             }
5964
5965             AFSExFreePoolWithTag( pwchBuffer, 0);
5966         }
5967     }
5968
5969     return ntStatus;
5970 }
5971
5972 AFSObjectInfoCB *
5973 AFSAllocateObjectInfo( IN AFSObjectInfoCB *ParentObjectInfo,
5974                        IN ULONGLONG HashIndex)
5975 {
5976
5977     NTSTATUS ntStatus = STATUS_SUCCESS;
5978     AFSObjectInfoCB *pObjectInfo = NULL;
5979     LONG lCount;
5980
5981     __Enter
5982     {
5983
5984         pObjectInfo = (AFSObjectInfoCB *)AFSExAllocatePoolWithTag( PagedPool,
5985                                                                    sizeof( AFSObjectInfoCB),
5986                                                                    AFS_OBJECT_INFO_TAG);
5987
5988         if( pObjectInfo == NULL)
5989         {
5990
5991             try_return( pObjectInfo);
5992         }
5993
5994         RtlZeroMemory( pObjectInfo,
5995                        sizeof( AFSObjectInfoCB));
5996
5997         pObjectInfo->NonPagedInfo = (AFSNonPagedObjectInfoCB *)AFSExAllocatePoolWithTag( NonPagedPool,
5998                                                                                          sizeof( AFSNonPagedObjectInfoCB),
5999                                                                                          AFS_NP_OBJECT_INFO_TAG);
6000
6001         if( pObjectInfo->NonPagedInfo == NULL)
6002         {
6003
6004             AFSExFreePoolWithTag( pObjectInfo, AFS_OBJECT_INFO_TAG);
6005
6006             try_return( pObjectInfo = NULL);
6007         }
6008
6009         ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6010
6011         ExInitializeResourceLite( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
6012
6013         pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock = &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock;
6014
6015         if( ParentObjectInfo != NULL)
6016         {
6017
6018             pObjectInfo->VolumeCB = ParentObjectInfo->VolumeCB;
6019
6020             pObjectInfo->ParentFileId = ParentObjectInfo->FileId;
6021
6022             SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID);
6023
6024             lCount = AFSObjectInfoIncrement( ParentObjectInfo,
6025                                              AFS_OBJECT_REFERENCE_CHILD);
6026
6027             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
6028                           AFS_TRACE_LEVEL_VERBOSE,
6029                           "AFSAllocateObjectInfo Increment count on parent object %p Cnt %d\n",
6030                           ParentObjectInfo,
6031                           lCount));
6032         }
6033
6034         //
6035         // Initialize the access time
6036         //
6037
6038         KeQueryTickCount( &pObjectInfo->LastAccessCount);
6039
6040         if( HashIndex != 0)
6041         {
6042
6043             ASSERT( ParentObjectInfo);
6044
6045             //
6046             // Insert the entry into the object tree and list
6047             //
6048
6049             pObjectInfo->TreeEntry.HashIndex = HashIndex;
6050
6051             if( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead == NULL)
6052             {
6053
6054                 ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead = &pObjectInfo->TreeEntry;
6055             }
6056             else
6057             {
6058
6059                 ntStatus = AFSInsertHashEntry( ParentObjectInfo->VolumeCB->ObjectInfoTree.TreeHead,
6060                                                &pObjectInfo->TreeEntry);
6061
6062                 ASSERT( NT_SUCCESS( ntStatus));
6063             }
6064
6065             //
6066             // And the object list in the volume
6067             //
6068
6069             if( ParentObjectInfo->VolumeCB->ObjectInfoListHead == NULL)
6070             {
6071
6072                 ParentObjectInfo->VolumeCB->ObjectInfoListHead = pObjectInfo;
6073             }
6074             else
6075             {
6076
6077                 ParentObjectInfo->VolumeCB->ObjectInfoListTail->ListEntry.fLink = (void *)pObjectInfo;
6078
6079                 pObjectInfo->ListEntry.bLink = (void *)ParentObjectInfo->VolumeCB->ObjectInfoListTail;
6080             }
6081
6082             ParentObjectInfo->VolumeCB->ObjectInfoListTail = pObjectInfo;
6083
6084             //
6085             // Indicate the object is in the hash tree and linked list in the volume
6086             //
6087
6088             SetFlag( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE | AFS_OBJECT_INSERTED_VOLUME_LIST);
6089         }
6090
6091 try_exit:
6092
6093         NOTHING;
6094     }
6095
6096     return pObjectInfo;
6097 }
6098
6099 LONG
6100 AFSObjectInfoIncrement( IN AFSObjectInfoCB *ObjectInfo,
6101                         IN LONG Reason)
6102 {
6103
6104     LONG lCount;
6105
6106     if ( ObjectInfo->ObjectReferenceCount == 0)
6107     {
6108
6109         AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6110                         TRUE);
6111
6112         lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6113     }
6114     else
6115     {
6116
6117         AFSAcquireShared( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6118                           TRUE);
6119
6120         lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6121
6122         if ( lCount == 1)
6123         {
6124
6125             AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6126
6127             AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6128                             TRUE);
6129         }
6130     }
6131
6132     InterlockedIncrement( &ObjectInfo->ObjectReferences[ Reason]);
6133
6134     AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6135
6136     return lCount;
6137 }
6138
6139 LONG
6140 AFSObjectInfoDecrement( IN AFSObjectInfoCB *ObjectInfo,
6141                         IN LONG Reason)
6142 {
6143
6144     LONG lCount, lCount2;
6145
6146     AFSAcquireShared( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6147                       TRUE);
6148
6149     lCount = InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);
6150
6151     if ( lCount == 0)
6152     {
6153
6154         lCount = InterlockedIncrement( &ObjectInfo->ObjectReferenceCount);
6155
6156         AFSReleaseResource(&ObjectInfo->NonPagedInfo->ObjectInfoLock);
6157
6158         AFSAcquireExcl( &ObjectInfo->NonPagedInfo->ObjectInfoLock,
6159                         TRUE);
6160
6161         lCount = InterlockedDecrement( &ObjectInfo->ObjectReferenceCount);
6162     }
6163
6164     lCount2 = InterlockedDecrement( &ObjectInfo->ObjectReferences[ Reason]);
6165
6166     ASSERT( lCount2 >= 0);
6167
6168     AFSReleaseResource( &ObjectInfo->NonPagedInfo->ObjectInfoLock);
6169
6170     return lCount;
6171 }
6172
6173 AFSObjectInfoCB *
6174 AFSFindObjectInfo( IN AFSVolumeCB *VolumeCB,
6175                    IN AFSFileID   *FileId)
6176 {
6177     DWORD            ntStatus = STATUS_SUCCESS;
6178     ULONGLONG        ullIndex;
6179     AFSObjectInfoCB *pObjectInfo = NULL;
6180     LONG             lCount;
6181
6182     ullIndex = AFSCreateLowIndex( FileId);
6183
6184     AFSAcquireShared( VolumeCB->ObjectInfoTree.TreeLock,
6185                       TRUE);
6186
6187     if ( AFSIsEqualFID( &VolumeCB->ObjectInformation.FileId, FileId))
6188     {
6189
6190         pObjectInfo = &VolumeCB->ObjectInformation;
6191     }
6192     else
6193     {
6194
6195         ntStatus = AFSLocateHashEntry( VolumeCB->ObjectInfoTree.TreeHead,
6196                                        ullIndex,
6197                                        (AFSBTreeEntry **)&pObjectInfo);
6198     }
6199
6200     if ( NT_SUCCESS( ntStatus)) {
6201
6202         lCount = AFSObjectInfoIncrement( pObjectInfo,
6203                                          AFS_OBJECT_REFERENCE_FIND);
6204
6205         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
6206                       AFS_TRACE_LEVEL_VERBOSE,
6207                       "AFSFindObjectInfo Decrement count on object %p Cnt %d\n",
6208                       pObjectInfo,
6209                       lCount));
6210     }
6211
6212     AFSReleaseResource( VolumeCB->ObjectInfoTree.TreeLock);
6213
6214     return pObjectInfo;
6215 }
6216
6217 void
6218 AFSReleaseObjectInfo( IN AFSObjectInfoCB **ppObjectInfo)
6219 {
6220     LONG lCount;
6221
6222     lCount = AFSObjectInfoDecrement( *ppObjectInfo,
6223                                      AFS_OBJECT_REFERENCE_FIND);
6224
6225     AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
6226                   AFS_TRACE_LEVEL_VERBOSE,
6227                   "AFSReleaseObjectInfo Decrement count on object %p Cnt %d\n",
6228                   *ppObjectInfo,
6229                   lCount));
6230
6231     *ppObjectInfo = NULL;
6232 }
6233
6234 void
6235 AFSDeleteObjectInfo( IN AFSObjectInfoCB **ppObjectInfo)
6236 {
6237     BOOLEAN bAcquiredTreeLock = FALSE;
6238     AFSObjectInfoCB *pObjectInfo = NULL;
6239     AFSVolumeCB * pVolume = NULL;
6240     BOOLEAN bHeldInService;
6241     AFSObjectInfoCB * pParentObjectInfo = NULL;
6242     AFSFileID FileId;
6243     LONG lCount;
6244
6245     __Enter
6246     {
6247         if ( BooleanFlagOn( (*ppObjectInfo)->Flags, AFS_OBJECT_ROOT_VOLUME))
6248         {
6249
6250             //
6251             // AFSDeleteObjectInfo should never be called on the ObjectInformationCB
6252             // embedded in the VolumeCB.
6253             //
6254
6255             ASSERT( FALSE);
6256
6257             return;
6258         }
6259
6260         pVolume = (*ppObjectInfo)->VolumeCB;
6261
6262         if( !ExIsResourceAcquiredExclusiveLite( pVolume->ObjectInfoTree.TreeLock))
6263         {
6264
6265             ASSERT( !ExIsResourceAcquiredLite( pVolume->ObjectInfoTree.TreeLock));
6266
6267             AFSAcquireExcl( pVolume->ObjectInfoTree.TreeLock,
6268                             TRUE);
6269
6270             bAcquiredTreeLock = TRUE;
6271         }
6272
6273         for ( lCount = 0; lCount < AFS_OBJECT_REFERENCE_MAX; lCount++)
6274         {
6275
6276             ASSERT( (*ppObjectInfo)->ObjectReferences[ lCount] >= 0);
6277         }
6278
6279         ASSERT( (*ppObjectInfo)->ObjectReferenceCount == 0);
6280
6281         pObjectInfo = (AFSObjectInfoCB *) InterlockedCompareExchangePointer( (PVOID *)ppObjectInfo,
6282                                                                              NULL,
6283                                                                              *ppObjectInfo);
6284
6285         if ( pObjectInfo == NULL)
6286         {
6287
6288             try_return( NOTHING);
6289         }
6290
6291         ASSERT( *ppObjectInfo == NULL);
6292
6293         if ( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
6294         {
6295
6296             pParentObjectInfo = AFSFindObjectInfo( pVolume,
6297                                                    &pObjectInfo->ParentFileId);
6298             if( pParentObjectInfo != NULL)
6299             {
6300
6301                 ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID);
6302
6303                 lCount = AFSObjectInfoDecrement( pParentObjectInfo,
6304                                                  AFS_OBJECT_REFERENCE_CHILD);
6305
6306                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
6307                               AFS_TRACE_LEVEL_VERBOSE,
6308                               "AFSDeleteObjectInfo Decrement count on parent object %p Cnt %d\n",
6309                               pParentObjectInfo,
6310                               lCount));
6311
6312                 AFSReleaseObjectInfo( &pParentObjectInfo);
6313             }
6314         }
6315
6316         //
6317         // Remove it from the tree and list if it was inserted
6318         //
6319
6320         if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_HASH_TREE))
6321         {
6322
6323             AFSRemoveHashEntry( &pVolume->ObjectInfoTree.TreeHead,
6324                                 &pObjectInfo->TreeEntry);
6325         }
6326
6327         if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_INSERTED_VOLUME_LIST))
6328         {
6329
6330             if( pObjectInfo->ListEntry.fLink == NULL)
6331             {
6332
6333                 pVolume->ObjectInfoListTail = (AFSObjectInfoCB *)pObjectInfo->ListEntry.bLink;
6334
6335                 if( pVolume->ObjectInfoListTail != NULL)
6336                 {
6337
6338                     pVolume->ObjectInfoListTail->ListEntry.fLink = NULL;
6339                 }
6340             }
6341             else
6342             {
6343
6344                 ((AFSObjectInfoCB *)(pObjectInfo->ListEntry.fLink))->ListEntry.bLink = pObjectInfo->ListEntry.bLink;
6345             }
6346
6347             if( pObjectInfo->ListEntry.bLink == NULL)
6348             {
6349
6350                 pVolume->ObjectInfoListHead = (AFSObjectInfoCB *)pObjectInfo->ListEntry.fLink;
6351
6352                 if( pVolume->ObjectInfoListHead != NULL)
6353                 {
6354
6355                     pVolume->ObjectInfoListHead->ListEntry.bLink = NULL;
6356                 }
6357             }
6358             else
6359             {
6360
6361                 ((AFSObjectInfoCB *)(pObjectInfo->ListEntry.bLink))->ListEntry.fLink = pObjectInfo->ListEntry.fLink;
6362             }
6363         }
6364
6365         bHeldInService = BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_HELD_IN_SERVICE);
6366
6367         if( bHeldInService)
6368         {
6369
6370             FileId = pObjectInfo->FileId;
6371         }
6372
6373         ASSERT( pObjectInfo->ObjectReferenceCount == 0);
6374
6375         ExDeleteResourceLite( &pObjectInfo->NonPagedInfo->ObjectInfoLock);
6376
6377         ExDeleteResourceLite( &pObjectInfo->NonPagedInfo->DirectoryNodeHdrLock);
6378
6379         AFSExFreePoolWithTag( pObjectInfo->NonPagedInfo, AFS_NP_OBJECT_INFO_TAG);
6380
6381         AFSExFreePoolWithTag( pObjectInfo, AFS_OBJECT_INFO_TAG);
6382
6383 try_exit:
6384
6385         if( bAcquiredTreeLock)
6386         {
6387
6388             AFSReleaseResource( pVolume->ObjectInfoTree.TreeLock);
6389         }
6390
6391         //
6392         // Release the fid in the service
6393         //
6394
6395         if( bHeldInService)
6396         {
6397
6398             AFSReleaseFid( &FileId);
6399         }
6400     }
6401
6402     return;
6403 }
6404
6405 NTSTATUS
6406 AFSEvaluateRootEntry( IN AFSDirectoryCB *DirectoryCB,
6407                       OUT AFSDirectoryCB **TargetDirEntry)
6408 {
6409
6410     NTSTATUS ntStatus = STATUS_SUCCESS;
6411     AFSDirEnumEntry *pDirEntry = NULL;
6412     UNICODE_STRING uniFullPathName = {0};
6413     AFSNameArrayHdr    *pNameArray = NULL;
6414     AFSVolumeCB *pVolumeCB = NULL;
6415     LONG VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
6416     AFSVolumeCB *pNewVolumeCB = NULL;
6417     LONG NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
6418     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
6419     AFSDirectoryCB *pNewParentDirEntry = NULL;
6420     WCHAR *pwchBuffer = NULL;
6421     UNICODE_STRING uniComponentName, uniRemainingPath, uniParsedName;
6422     ULONG ulNameDifference = 0;
6423     GUID    stAuthGroup;
6424     LONG lCount;
6425
6426     __Enter
6427     {
6428
6429         ntStatus = AFSRetrieveValidAuthGroup( NULL,
6430                                               DirectoryCB->ObjectInformation,
6431                                               FALSE,
6432                                               &stAuthGroup);
6433
6434         if( !NT_SUCCESS( ntStatus))
6435         {
6436             try_return( ntStatus);
6437         }
6438
6439         //
6440         // Retrieve a target name for the entry
6441         //
6442
6443         AFSAcquireShared( &DirectoryCB->NonPaged->Lock,
6444                           TRUE);
6445
6446         if( DirectoryCB->NameInformation.TargetName.Length == 0)
6447         {
6448
6449             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6450
6451             ntStatus = AFSEvaluateTargetByID( DirectoryCB->ObjectInformation,
6452                                               &stAuthGroup,
6453                                               FALSE,
6454                                               &pDirEntry);
6455
6456             if( !NT_SUCCESS( ntStatus) ||
6457                 pDirEntry->TargetNameLength == 0)
6458             {
6459
6460                 if( pDirEntry != NULL)
6461                 {
6462
6463                     ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
6464                 }
6465
6466                 try_return( ntStatus);
6467             }
6468
6469             AFSAcquireExcl( &DirectoryCB->NonPaged->Lock,
6470                             TRUE);
6471
6472             if( DirectoryCB->NameInformation.TargetName.Length == 0)
6473             {
6474
6475                 //
6476                 // Update the target name
6477                 //
6478
6479                 ntStatus = AFSUpdateTargetName( &DirectoryCB->NameInformation.TargetName,
6480                                                 &DirectoryCB->Flags,
6481                                                 (WCHAR *)((char *)pDirEntry + pDirEntry->TargetNameOffset),
6482                                                 (USHORT)pDirEntry->TargetNameLength);
6483
6484                 if( !NT_SUCCESS( ntStatus))
6485                 {
6486
6487                     AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6488
6489                     try_return( ntStatus);
6490                 }
6491             }
6492
6493             AFSConvertToShared( &DirectoryCB->NonPaged->Lock);
6494         }
6495
6496         //
6497         // Need to pass the full path in for parsing.
6498         //
6499
6500         uniFullPathName.Length = 0;
6501         uniFullPathName.MaximumLength = DirectoryCB->NameInformation.TargetName.Length;
6502
6503         uniFullPathName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
6504                                                                     uniFullPathName.MaximumLength,
6505                                                                     AFS_NAME_BUFFER_EIGHT_TAG);
6506
6507         if( uniFullPathName.Buffer == NULL)
6508         {
6509
6510             AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6511
6512             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6513         }
6514
6515         pwchBuffer = uniFullPathName.Buffer;
6516
6517         RtlZeroMemory( uniFullPathName.Buffer,
6518                        uniFullPathName.MaximumLength);
6519
6520         RtlCopyMemory( uniFullPathName.Buffer,
6521                        DirectoryCB->NameInformation.TargetName.Buffer,
6522                        DirectoryCB->NameInformation.TargetName.Length);
6523
6524         uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6525
6526         //
6527         // This name should begin with the \afs server so parse it off and chech it
6528         //
6529
6530         FsRtlDissectName( uniFullPathName,
6531                           &uniComponentName,
6532                           &uniRemainingPath);
6533
6534         if( RtlCompareUnicodeString( &uniComponentName,
6535                                      &AFSServerName,
6536                                      TRUE) != 0)
6537         {
6538
6539             //
6540             // Try evaluating the full path
6541             //
6542
6543             uniFullPathName.Buffer = pwchBuffer;
6544
6545             uniFullPathName.Length = DirectoryCB->NameInformation.TargetName.Length;
6546
6547             uniFullPathName.MaximumLength = uniFullPathName.Length;
6548         }
6549         else
6550         {
6551
6552             uniFullPathName = uniRemainingPath;
6553         }
6554
6555         uniParsedName = uniFullPathName;
6556
6557         ulNameDifference = (ULONG)(uniFullPathName.Length > 0 ? ((char *)uniFullPathName.Buffer - (char *)pwchBuffer) : 0);
6558
6559         AFSReleaseResource( &DirectoryCB->NonPaged->Lock);
6560
6561         //
6562         // Our name array
6563         //
6564
6565         pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
6566                                        0);
6567
6568         if( pNameArray == NULL)
6569         {
6570
6571             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
6572         }
6573
6574         pVolumeCB = AFSGlobalRoot;
6575
6576         pParentDirEntry = AFSGlobalRoot->DirectoryCB;
6577
6578         VolumeReferenceReason = AFS_VOLUME_REFERENCE_EVAL_ROOT;
6579
6580         lCount = AFSVolumeIncrement( pVolumeCB,
6581                                      VolumeReferenceReason);
6582
6583         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6584                       AFS_TRACE_LEVEL_VERBOSE,
6585                       "AFSEvaluateRootEntry Increment count on volume %p Reason %u Cnt %d\n",
6586                       pVolumeCB,
6587                       VolumeReferenceReason,
6588                       lCount));
6589
6590         lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
6591
6592         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6593                       AFS_TRACE_LEVEL_VERBOSE,
6594                       "AFSEvaluateRootEntry Increment count on %wZ DE %p Ccb %p Cnt %d\n",
6595                       &pParentDirEntry->NameInformation.FileName,
6596                       pParentDirEntry,
6597                       NULL,
6598                       lCount));
6599
6600         ntStatus = AFSLocateNameEntry( NULL,
6601                                        NULL,
6602                                        &uniFullPathName,
6603                                        &uniParsedName,
6604                                        pNameArray,
6605                                        0,
6606                                        pVolumeCB,
6607                                        pParentDirEntry,
6608                                        &pNewVolumeCB,
6609                                        &VolumeReferenceReason,
6610                                        &pNewParentDirEntry,
6611                                        &pDirectoryEntry,
6612                                        NULL);
6613
6614         if ( pNewVolumeCB != NULL)
6615         {
6616             //
6617             // AFSLocateNameEntry returns pNewVolumeCB with a reference held
6618             // even if pVolumeCB == pNewVolumeCB.  It is always safe to release
6619             // the reference on pVolumeCB that was held prior to the call.
6620             // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
6621             // will be released second.
6622             //
6623
6624             lCount = AFSVolumeDecrement( pVolumeCB,
6625                                          VolumeReferenceReason);
6626
6627             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6628                           AFS_TRACE_LEVEL_VERBOSE,
6629                           "AFSEvaluateRootEntry Decrement count on volume %p Reason %u Cnt %d\n",
6630                           pVolumeCB,
6631                           VolumeReferenceReason,
6632                           lCount));
6633
6634             pVolumeCB = pNewVolumeCB;
6635
6636             pNewVolumeCB = NULL;
6637
6638             VolumeReferenceReason = NewVolumeReferenceReason;
6639
6640             NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
6641         }
6642
6643         //
6644         // AFSLocateNameEntry does not alter the reference count of
6645         // pParentDirectoryCB and it returns pNewParentDirectoryCB with
6646         // a reference held.
6647         //
6648
6649         lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
6650
6651         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6652                       AFS_TRACE_LEVEL_VERBOSE,
6653                       "AFSEvaluateRootEntry DecrementX count on %wZ DE %p Cnt %d\n",
6654                       &pParentDirEntry->NameInformation.FileName,
6655                       pParentDirEntry,
6656                       lCount));
6657
6658         pParentDirEntry = pNewParentDirEntry;
6659
6660         pNewParentDirEntry = NULL;
6661
6662         if( !NT_SUCCESS( ntStatus) ||
6663             ntStatus == STATUS_REPARSE)
6664         {
6665
6666             pVolumeCB = NULL;
6667
6668             try_return( ntStatus);
6669         }
6670
6671         //
6672         // Pass back the target dir entry for this request
6673         // The caller must release the DirOpenReferenceCount
6674         //
6675
6676         *TargetDirEntry = pDirectoryEntry;
6677
6678         pDirectoryEntry = NULL;
6679
6680 try_exit:
6681
6682         if( pDirectoryEntry != NULL)
6683         {
6684
6685             lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
6686
6687             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6688                           AFS_TRACE_LEVEL_VERBOSE,
6689                           "AFSEvaluateRootEntry Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
6690                           &pDirectoryEntry->NameInformation.FileName,
6691                           pDirectoryEntry,
6692                           NULL,
6693                           lCount));
6694
6695             ASSERT( lCount >= 0);
6696         }
6697
6698         if ( pParentDirEntry != NULL)
6699         {
6700
6701             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
6702
6703             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
6704                           AFS_TRACE_LEVEL_VERBOSE,
6705                           "AFSEvaluateRootEntry Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
6706                           &pParentDirEntry->NameInformation.FileName,
6707                           pParentDirEntry,
6708                           NULL,
6709                           lCount));
6710
6711             ASSERT( lCount >= 0);
6712         }
6713
6714         if( pDirEntry != NULL)
6715         {
6716
6717             AFSExFreePoolWithTag( pDirEntry, AFS_GENERIC_MEMORY_2_TAG);
6718         }
6719
6720         if( pVolumeCB != NULL)
6721         {
6722
6723             lCount = AFSVolumeDecrement( pVolumeCB,
6724                                          VolumeReferenceReason);
6725
6726             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
6727                           AFS_TRACE_LEVEL_VERBOSE,
6728                           "AFSEvaluateRootEntry Decrement2 count on volume %p Reason %u Cnt %d\n",
6729                           pVolumeCB,
6730                           VolumeReferenceReason,
6731                           lCount));
6732         }
6733
6734         if( pNameArray != NULL)
6735         {
6736
6737             AFSFreeNameArray( pNameArray);
6738         }
6739
6740         if( pwchBuffer != NULL)
6741         {
6742
6743             //
6744             // Always free the buffer that we allocated as AFSLocateNameEntry
6745             // will not free it.  If uniFullPathName.Buffer was allocated by
6746             // AFSLocateNameEntry, then we must free that as well.
6747             // Check that the uniFullPathName.Buffer in the string is not the same
6748             // offset by the length of the server name
6749             //
6750
6751             if( uniFullPathName.Length > 0 &&
6752                 pwchBuffer != (WCHAR *)((char *)uniFullPathName.Buffer - ulNameDifference))
6753             {
6754
6755                 AFSExFreePoolWithTag( uniFullPathName.Buffer, 0);
6756             }
6757
6758             AFSExFreePoolWithTag( pwchBuffer, 0);
6759         }
6760     }
6761
6762     return ntStatus;
6763 }
6764
6765 NTSTATUS
6766 AFSCleanupFcb( IN AFSFcb *Fcb,
6767                IN BOOLEAN ForceFlush)
6768 {
6769
6770     NTSTATUS ntStatus = STATUS_SUCCESS;
6771     AFSDeviceExt *pRDRDeviceExt = NULL, *pControlDeviceExt = NULL;
6772     LARGE_INTEGER liTime;
6773     IO_STATUS_BLOCK stIoStatus;
6774
6775     __Enter
6776     {
6777
6778         pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
6779
6780         pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
6781
6782         if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
6783         {
6784
6785             if( !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) &&
6786                 !BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
6787             {
6788
6789                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
6790                               AFS_TRACE_LEVEL_VERBOSE,
6791                               "AFSCleanupEntry Acquiring Fcb lock %p SHARED %08lX\n",
6792                               &Fcb->NPFcb->Resource,
6793                               PsGetCurrentThread()));
6794
6795                 AFSAcquireShared( &Fcb->NPFcb->Resource,
6796                                   TRUE);
6797
6798                 if( Fcb->OpenReferenceCount > 0)
6799                 {
6800
6801                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
6802                                   AFS_TRACE_LEVEL_VERBOSE,
6803                                   "AFSCleanupEntry Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
6804                                   &Fcb->NPFcb->SectionObjectResource,
6805                                   PsGetCurrentThread()));
6806
6807                     AFSAcquireExcl( &Fcb->NPFcb->SectionObjectResource,
6808                                     TRUE);
6809
6810                     __try
6811                     {
6812
6813                         CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
6814                                       NULL,
6815                                       0,
6816                                       &stIoStatus);
6817
6818                         if( !NT_SUCCESS( stIoStatus.Status))
6819                         {
6820
6821                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
6822                                           AFS_TRACE_LEVEL_ERROR,
6823                                           "AFSCleanupFcb CcFlushCache [1] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
6824                                           Fcb->ObjectInformation->FileId.Cell,
6825                                           Fcb->ObjectInformation->FileId.Volume,
6826                                           Fcb->ObjectInformation->FileId.Vnode,
6827                                           Fcb->ObjectInformation->FileId.Unique,
6828                                           stIoStatus.Status,
6829                                           stIoStatus.Information));
6830
6831                             ntStatus = stIoStatus.Status;
6832                         }
6833
6834                         if (  Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
6835                         {
6836
6837                             if ( !CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
6838                                                        NULL,
6839                                                        0,
6840                                                        FALSE))
6841                             {
6842
6843                                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
6844                                               AFS_TRACE_LEVEL_WARNING,
6845                                               "AFSCleanupFcb CcPurgeCacheSection [1] failure FID %08lX-%08lX-%08lX-%08lX\n",
6846                                               Fcb->ObjectInformation->FileId.Cell,
6847                                               Fcb->ObjectInformation->FileId.Volume,
6848                                               Fcb->ObjectInformation->FileId.Vnode,
6849                                               Fcb->ObjectInformation->FileId.Unique));
6850
6851                                 SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
6852                             }
6853                         }
6854                     }
6855                     __except( EXCEPTION_EXECUTE_HANDLER)
6856                     {
6857
6858                         ntStatus = GetExceptionCode();
6859
6860                         AFSDbgTrace(( 0,
6861                                       0,
6862                                       "EXCEPTION - AFSCleanupFcb Cc [1] FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
6863                                       Fcb->ObjectInformation->FileId.Cell,
6864                                       Fcb->ObjectInformation->FileId.Volume,
6865                                       Fcb->ObjectInformation->FileId.Vnode,
6866                                       Fcb->ObjectInformation->FileId.Unique,
6867                                       ntStatus));
6868
6869                         SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
6870                     }
6871
6872                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
6873                                   AFS_TRACE_LEVEL_VERBOSE,
6874                                   "AFSCleanupFcb Releasing Fcb SectionObject lock %p EXCL %08lX\n",
6875                                   &Fcb->NPFcb->SectionObjectResource,
6876                                   PsGetCurrentThread()));
6877
6878                     AFSReleaseResource( &Fcb->NPFcb->SectionObjectResource);
6879                 }
6880
6881                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
6882                               AFS_TRACE_LEVEL_VERBOSE,
6883                               "AFSCleanupEntry Releasing Fcb lock %p SHARED %08lX\n",
6884                               &Fcb->NPFcb->Resource,
6885                               PsGetCurrentThread()));
6886
6887                 AFSReleaseResource( &Fcb->NPFcb->Resource);
6888
6889                 //
6890                 // Wait for any currently running flush or release requests to complete
6891                 //
6892
6893                 AFSWaitOnQueuedFlushes( Fcb);
6894
6895                 //
6896                 // Now perform another flush on the file
6897                 //
6898
6899                 if( !NT_SUCCESS( AFSFlushExtents( Fcb,
6900                                                   NULL)))
6901                 {
6902
6903                     AFSReleaseExtentsWithFlush( Fcb,
6904                                                 NULL,
6905                                                 TRUE);
6906                 }
6907             }
6908
6909             if( Fcb->OpenReferenceCount == 0 ||
6910                 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
6911                 BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
6912             {
6913
6914                 AFSTearDownFcbExtents( Fcb,
6915                                        NULL);
6916             }
6917
6918             try_return( ntStatus);
6919         }
6920
6921         KeQueryTickCount( &liTime);
6922
6923         //
6924         // First up are there dirty extents in the cache to flush?
6925         //
6926
6927         if( BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_OBJECT_INVALID) ||
6928             BooleanFlagOn( Fcb->ObjectInformation->Flags, AFS_OBJECT_FLAGS_DELETED))
6929         {
6930
6931             //
6932             // The file has been marked as invalid.  Dump it
6933             //
6934
6935             AFSTearDownFcbExtents( Fcb,
6936                                    NULL);
6937         }
6938         else if( ForceFlush ||
6939             ( ( Fcb->Specific.File.ExtentsDirtyCount ||
6940                 Fcb->Specific.File.ExtentCount) &&
6941               (liTime.QuadPart - Fcb->Specific.File.LastServerFlush.QuadPart)
6942                                                     >= pControlDeviceExt->Specific.Control.FcbFlushTimeCount.QuadPart))
6943         {
6944             if( !NT_SUCCESS( AFSFlushExtents( Fcb,
6945                                               NULL)) &&
6946                 Fcb->OpenReferenceCount == 0)
6947             {
6948
6949                 AFSReleaseExtentsWithFlush( Fcb,
6950                                             NULL,
6951                                             TRUE);
6952             }
6953         }
6954
6955         //
6956         // If there are extents and they haven't been used recently *and*
6957         // are not being used
6958         //
6959
6960         if( ( ForceFlush ||
6961               ( 0 != Fcb->Specific.File.ExtentCount &&
6962                 0 != Fcb->Specific.File.LastExtentAccess.QuadPart &&
6963                 (liTime.QuadPart - Fcb->Specific.File.LastExtentAccess.QuadPart) >=
6964                                         (AFS_SERVER_PURGE_SLEEP * pControlDeviceExt->Specific.Control.FcbPurgeTimeCount.QuadPart))))
6965         {
6966
6967             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
6968                           AFS_TRACE_LEVEL_VERBOSE,
6969                           "AFSCleanupFcb Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
6970                           &Fcb->NPFcb->SectionObjectResource,
6971                           PsGetCurrentThread()));
6972
6973             if ( AFSAcquireExcl( &Fcb->NPFcb->SectionObjectResource, ForceFlush))
6974             {
6975
6976                 __try
6977                 {
6978
6979                     CcFlushCache( &Fcb->NPFcb->SectionObjectPointers,
6980                                   NULL,
6981                                   0,
6982                                   &stIoStatus);
6983
6984                     if( !NT_SUCCESS( stIoStatus.Status))
6985                     {
6986
6987                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
6988                                       AFS_TRACE_LEVEL_ERROR,
6989                                       "AFSCleanupFcb CcFlushCache [2] failure FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX Bytes 0x%08lX\n",
6990                                       Fcb->ObjectInformation->FileId.Cell,
6991                                       Fcb->ObjectInformation->FileId.Volume,
6992                                       Fcb->ObjectInformation->FileId.Vnode,
6993                                       Fcb->ObjectInformation->FileId.Unique,
6994                                       stIoStatus.Status,
6995                                       stIoStatus.Information));
6996
6997                         ntStatus = stIoStatus.Status;
6998                     }
6999
7000                     if( ForceFlush &&
7001                         Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL)
7002                     {
7003
7004                         if ( !CcPurgeCacheSection( &Fcb->NPFcb->SectionObjectPointers,
7005                                                    NULL,
7006                                                    0,
7007                                                    FALSE))
7008                         {
7009
7010                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
7011                                           AFS_TRACE_LEVEL_WARNING,
7012                                           "AFSCleanupFcb CcPurgeCacheSection [2] failure FID %08lX-%08lX-%08lX-%08lX\n",
7013                                           Fcb->ObjectInformation->FileId.Cell,
7014                                           Fcb->ObjectInformation->FileId.Volume,
7015                                           Fcb->ObjectInformation->FileId.Vnode,
7016                                           Fcb->ObjectInformation->FileId.Unique));
7017
7018                             SetFlag( Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
7019                         }
7020                     }
7021                 }
7022                 __except( EXCEPTION_EXECUTE_HANDLER)
7023                 {
7024
7025                     ntStatus = GetExceptionCode();
7026
7027                     AFSDbgTrace(( 0,
7028                                   0,
7029                                   "EXCEPTION - AFSCleanupFcb Cc [2] FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
7030                                   Fcb->ObjectInformation->FileId.Cell,
7031                                   Fcb->ObjectInformation->FileId.Volume,
7032                                   Fcb->ObjectInformation->FileId.Vnode,
7033                                   Fcb->ObjectInformation->FileId.Unique,
7034                                   ntStatus));
7035                 }
7036
7037                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
7038                               AFS_TRACE_LEVEL_VERBOSE,
7039                               "AFSCleanupFcb Releasing Fcb SectionObject lock %p EXCL %08lX\n",
7040                               &Fcb->NPFcb->SectionObjectResource,
7041                               PsGetCurrentThread()));
7042
7043                 AFSReleaseResource( &Fcb->NPFcb->SectionObjectResource);
7044
7045                 if( Fcb->OpenReferenceCount <= 0)
7046                 {
7047
7048                     //
7049                     // Tear em down we'll not be needing them again
7050                     //
7051
7052                     AFSTearDownFcbExtents( Fcb,
7053                                            NULL);
7054                 }
7055             }
7056             else
7057             {
7058
7059                 ntStatus = STATUS_RETRY;
7060             }
7061         }
7062
7063 try_exit:
7064
7065         NOTHING;
7066     }
7067
7068     return ntStatus;
7069 }
7070
7071 NTSTATUS
7072 AFSUpdateDirEntryName( IN AFSDirectoryCB *DirectoryCB,
7073                        IN UNICODE_STRING *NewFileName)
7074 {
7075
7076     NTSTATUS ntStatus = STATUS_SUCCESS;
7077     WCHAR *pTmpBuffer = NULL;
7078
7079     __Enter
7080     {
7081
7082         if( NewFileName->Length > DirectoryCB->NameInformation.FileName.Length)
7083         {
7084
7085             if( BooleanFlagOn( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER))
7086             {
7087
7088                 AFSExFreePoolWithTag( DirectoryCB->NameInformation.FileName.Buffer, 0);
7089
7090                 ClearFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
7091
7092                 DirectoryCB->NameInformation.FileName.Buffer = NULL;
7093             }
7094
7095             //
7096             // OK, we need to allocate a new name buffer
7097             //
7098
7099             pTmpBuffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
7100                                                             NewFileName->Length,
7101                                                             AFS_NAME_BUFFER_NINE_TAG);
7102
7103             if( pTmpBuffer == NULL)
7104             {
7105
7106                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7107             }
7108
7109             DirectoryCB->NameInformation.FileName.Buffer = pTmpBuffer;
7110
7111             DirectoryCB->NameInformation.FileName.MaximumLength = NewFileName->Length;
7112
7113             SetFlag( DirectoryCB->Flags, AFS_DIR_RELEASE_NAME_BUFFER);
7114         }
7115
7116         DirectoryCB->NameInformation.FileName.Length = NewFileName->Length;
7117
7118         RtlCopyMemory( DirectoryCB->NameInformation.FileName.Buffer,
7119                        NewFileName->Buffer,
7120                        NewFileName->Length);
7121
7122 try_exit:
7123
7124         NOTHING;
7125     }
7126
7127     return ntStatus;
7128 }
7129
7130 NTSTATUS
7131 AFSReadCacheFile( IN void *ReadBuffer,
7132                   IN LARGE_INTEGER *ReadOffset,
7133                   IN ULONG RequestedDataLength,
7134                   IN OUT PULONG BytesRead)
7135 {
7136
7137     NTSTATUS            ntStatus = STATUS_SUCCESS;
7138     PIRP                pIrp = NULL;
7139     KEVENT              kEvent;
7140     PIO_STACK_LOCATION  pIoStackLocation = NULL;
7141     DEVICE_OBJECT      *pTargetDeviceObject = NULL;
7142     FILE_OBJECT        *pCacheFileObject = NULL;
7143
7144     __Enter
7145     {
7146
7147         pCacheFileObject = AFSReferenceCacheFileObject();
7148
7149         if( pCacheFileObject == NULL)
7150         {
7151             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
7152         }
7153
7154         pTargetDeviceObject = IoGetRelatedDeviceObject( pCacheFileObject);
7155
7156         //
7157         // Initialize the event
7158         //
7159
7160         KeInitializeEvent( &kEvent,
7161                            SynchronizationEvent,
7162                            FALSE);
7163
7164         //
7165         // Allocate an irp for this request.  This could also come from a
7166         // private pool, for instance.
7167         //
7168
7169         pIrp = IoAllocateIrp( pTargetDeviceObject->StackSize,
7170                               FALSE);
7171
7172         if( pIrp == NULL)
7173         {
7174
7175             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
7176         }
7177
7178         //
7179         // Build the IRP's main body
7180         //
7181
7182         pIrp->UserBuffer = ReadBuffer;
7183
7184         pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
7185         pIrp->RequestorMode = KernelMode;
7186         pIrp->Flags |= IRP_READ_OPERATION;
7187
7188         //
7189         // Set up the I/O stack location.
7190         //
7191
7192         pIoStackLocation = IoGetNextIrpStackLocation( pIrp);
7193         pIoStackLocation->MajorFunction = IRP_MJ_READ;
7194         pIoStackLocation->DeviceObject = pTargetDeviceObject;
7195         pIoStackLocation->FileObject = pCacheFileObject;
7196         pIoStackLocation->Parameters.Read.Length = RequestedDataLength;
7197
7198         pIoStackLocation->Parameters.Read.ByteOffset.QuadPart = ReadOffset->QuadPart;
7199
7200         //
7201         // Set the completion routine.
7202         //
7203
7204         IoSetCompletionRoutine( pIrp,
7205                                 AFSIrpComplete,
7206                                 &kEvent,
7207                                 TRUE,
7208                                 TRUE,
7209                                 TRUE);
7210
7211         //
7212         // Send it to the FSD
7213         //
7214
7215         ntStatus = IoCallDriver( pTargetDeviceObject,
7216                                  pIrp);
7217
7218         if( NT_SUCCESS( ntStatus))
7219         {
7220
7221             //
7222             // Wait for the I/O
7223             //
7224
7225             ntStatus = KeWaitForSingleObject( &kEvent,
7226                                               Executive,
7227                                               KernelMode,
7228                                               FALSE,
7229                                               0);
7230
7231             if( NT_SUCCESS( ntStatus))
7232             {
7233
7234                 ntStatus = pIrp->IoStatus.Status;
7235
7236                 *BytesRead = (ULONG)pIrp->IoStatus.Information;
7237             }
7238         }
7239
7240 try_exit:
7241
7242         if( pCacheFileObject != NULL)
7243         {
7244             AFSReleaseCacheFileObject( pCacheFileObject);
7245         }
7246
7247         if( pIrp != NULL)
7248         {
7249
7250             if( pIrp->MdlAddress != NULL)
7251             {
7252
7253                 if( FlagOn( pIrp->MdlAddress->MdlFlags, MDL_PAGES_LOCKED))
7254                 {
7255
7256                     MmUnlockPages( pIrp->MdlAddress);
7257                 }
7258
7259                 IoFreeMdl( pIrp->MdlAddress);
7260             }
7261
7262             pIrp->MdlAddress = NULL;
7263
7264             //
7265             // Free the Irp
7266             //
7267
7268             IoFreeIrp( pIrp);
7269         }
7270     }
7271
7272     return ntStatus;
7273 }
7274
7275 NTSTATUS
7276 AFSIrpComplete( IN PDEVICE_OBJECT DeviceObject,
7277                 IN PIRP           Irp,
7278                 IN PVOID          Context)
7279 {
7280
7281     UNREFERENCED_PARAMETER(Irp);
7282     UNREFERENCED_PARAMETER(DeviceObject);
7283     KEVENT *pEvent = (KEVENT *)Context;
7284
7285     KeSetEvent( pEvent,
7286                 0,
7287                 FALSE);
7288
7289     return STATUS_MORE_PROCESSING_REQUIRED;
7290 }
7291
7292 BOOLEAN
7293 AFSIsDirectoryEmptyForDelete( IN AFSFcb *Fcb)
7294 {
7295
7296     BOOLEAN bIsEmpty = FALSE;
7297     AFSDirectoryCB *pDirEntry = NULL;
7298
7299     __Enter
7300     {
7301
7302         AFSAcquireShared( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
7303                           TRUE);
7304
7305         bIsEmpty = TRUE;
7306
7307         if( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
7308         {
7309
7310             pDirEntry = Fcb->ObjectInformation->Specific.Directory.DirectoryNodeListHead;
7311
7312             while( pDirEntry != NULL)
7313             {
7314
7315                 if( !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_FAKE) &&
7316                     !BooleanFlagOn( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED))
7317                 {
7318
7319                     bIsEmpty = FALSE;
7320
7321                     break;
7322                 }
7323
7324                 pDirEntry = (AFSDirectoryCB *)pDirEntry->ListEntry.fLink;
7325             }
7326
7327         }
7328
7329         AFSReleaseResource( Fcb->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
7330     }
7331
7332     return bIsEmpty;
7333 }
7334
7335 void
7336 AFSRemoveNameEntry( IN AFSObjectInfoCB *ParentObjectInfo,
7337                     IN AFSDirectoryCB *DirEntry)
7338 {
7339
7340     NTSTATUS ntStatus = STATUS_SUCCESS;
7341
7342     __Enter
7343     {
7344
7345         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7346         {
7347
7348             AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7349                           AFS_TRACE_LEVEL_VERBOSE,
7350                           "AFSRemoveNameEntry DE %p for %wZ has NOT_IN flag set\n",
7351                           DirEntry,
7352                           &DirEntry->NameInformation.FileName));
7353
7354             try_return( ntStatus);
7355         }
7356
7357         ASSERT( ExIsResourceAcquiredExclusiveLite( ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock));
7358
7359         //
7360         // Remove the entry from the parent tree
7361         //
7362
7363         AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7364                       AFS_TRACE_LEVEL_VERBOSE,
7365                       "AFSRemoveNameEntry DE %p for %wZ removing from case sensitive tree\n",
7366                       DirEntry,
7367                       &DirEntry->NameInformation.FileName));
7368
7369         AFSRemoveCaseSensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7370                                         DirEntry);
7371
7372         AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7373                       AFS_TRACE_LEVEL_VERBOSE,
7374                       "AFSRemoveNameEntry DE %p for %wZ removing from case insensitive tree\n",
7375                       DirEntry,
7376                       &DirEntry->NameInformation.FileName));
7377
7378         AFSRemoveCaseInsensitiveDirEntry( &ParentObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
7379                                           DirEntry);
7380
7381         if( BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME))
7382         {
7383
7384             //
7385             // From the short name tree
7386             //
7387
7388             AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7389                           AFS_TRACE_LEVEL_VERBOSE,
7390                           "AFSRemoveNameEntry DE %p for %wZ removing from shortname tree\n",
7391                           DirEntry,
7392                           &DirEntry->NameInformation.FileName));
7393
7394             AFSRemoveShortNameDirEntry( &ParentObjectInfo->Specific.Directory.ShortNameTree,
7395                                         DirEntry);
7396
7397             ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_INSERTED_SHORT_NAME);
7398         }
7399
7400         AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
7401                       AFS_TRACE_LEVEL_VERBOSE,
7402                       "AFSRemoveNameEntry DE %p for %wZ setting NOT_IN flag\n",
7403                       DirEntry,
7404                       &DirEntry->NameInformation.FileName));
7405
7406         SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE);
7407
7408         ClearFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
7409
7410 try_exit:
7411
7412         NOTHING;
7413     }
7414
7415     return;
7416 }
7417
7418 LARGE_INTEGER
7419 AFSGetAuthenticationId()
7420 {
7421
7422     LARGE_INTEGER liAuthId = {0,0};
7423     NTSTATUS ntStatus = STATUS_SUCCESS;
7424     PACCESS_TOKEN hToken = NULL;
7425     PTOKEN_STATISTICS pTokenInfo = NULL;
7426     BOOLEAN bCopyOnOpen = FALSE;
7427     BOOLEAN bEffectiveOnly = FALSE;
7428     BOOLEAN bPrimaryToken = FALSE;
7429     SECURITY_IMPERSONATION_LEVEL stImpersonationLevel;
7430
7431     __Enter
7432     {
7433
7434         hToken = PsReferenceImpersonationToken( PsGetCurrentThread(),
7435                                                 &bCopyOnOpen,
7436                                                 &bEffectiveOnly,
7437                                                 &stImpersonationLevel);
7438
7439         if( hToken == NULL)
7440         {
7441
7442             hToken = PsReferencePrimaryToken( PsGetCurrentProcess());
7443
7444             if( hToken == NULL)
7445             {
7446
7447                 AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7448                               AFS_TRACE_LEVEL_ERROR,
7449                               "AFSGetAuthenticationId Failed to retrieve impersonation or primary token\n"));
7450
7451                 try_return( ntStatus);
7452             }
7453
7454             bPrimaryToken = TRUE;
7455         }
7456
7457         ntStatus = SeQueryInformationToken( hToken,
7458                                             TokenStatistics,
7459                                             (PVOID *)&pTokenInfo);
7460
7461         if( !NT_SUCCESS( ntStatus))
7462         {
7463
7464             AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7465                           AFS_TRACE_LEVEL_ERROR,
7466                           "AFSGetAuthenticationId Failed to retrieve information Status %08lX\n",
7467                           ntStatus));
7468
7469             try_return( ntStatus);
7470         }
7471
7472         liAuthId.HighPart = pTokenInfo->AuthenticationId.HighPart;
7473         liAuthId.LowPart = pTokenInfo->AuthenticationId.LowPart;
7474
7475         AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER,
7476                       AFS_TRACE_LEVEL_VERBOSE,
7477                       "AFSGetAuthenticationId Successfully retrieved authentication ID %I64X\n",
7478                       liAuthId.QuadPart));
7479
7480 try_exit:
7481
7482         if( hToken != NULL)
7483         {
7484
7485             if( !bPrimaryToken)
7486             {
7487
7488                 PsDereferenceImpersonationToken( hToken);
7489             }
7490             else
7491             {
7492
7493                 PsDereferencePrimaryToken( hToken);
7494             }
7495         }
7496
7497         if( pTokenInfo != NULL)
7498         {
7499
7500             ExFreePool( pTokenInfo);    // Allocated by SeQueryInformationToken
7501         }
7502     }
7503
7504     return liAuthId;
7505 }
7506
7507 void
7508 AFSUnwindFileInfo( IN AFSFcb *Fcb,
7509                    IN AFSCcb *Ccb)
7510 {
7511
7512     UNREFERENCED_PARAMETER(Fcb);
7513     if( Ccb->FileUnwindInfo.FileAttributes != (ULONG)-1)
7514     {
7515         Ccb->DirectoryCB->ObjectInformation->FileAttributes = Ccb->FileUnwindInfo.FileAttributes;
7516     }
7517
7518     if( Ccb->FileUnwindInfo.CreationTime.QuadPart != (ULONGLONG)-1)
7519     {
7520         Ccb->DirectoryCB->ObjectInformation->CreationTime.QuadPart = Ccb->FileUnwindInfo.CreationTime.QuadPart;
7521     }
7522
7523     if( Ccb->FileUnwindInfo.LastAccessTime.QuadPart != (ULONGLONG)-1)
7524     {
7525         Ccb->DirectoryCB->ObjectInformation->LastAccessTime.QuadPart = Ccb->FileUnwindInfo.LastAccessTime.QuadPart;
7526     }
7527
7528     if( Ccb->FileUnwindInfo.LastWriteTime.QuadPart != (ULONGLONG)-1)
7529     {
7530         Ccb->DirectoryCB->ObjectInformation->LastWriteTime.QuadPart = Ccb->FileUnwindInfo.LastWriteTime.QuadPart;
7531     }
7532
7533     if( Ccb->FileUnwindInfo.ChangeTime.QuadPart != (ULONGLONG)-1)
7534     {
7535         Ccb->DirectoryCB->ObjectInformation->ChangeTime.QuadPart = Ccb->FileUnwindInfo.ChangeTime.QuadPart;
7536     }
7537
7538     return;
7539 }
7540
7541 BOOLEAN
7542 AFSValidateDirList( IN AFSObjectInfoCB *ObjectInfo)
7543 {
7544
7545     BOOLEAN bIsValid = TRUE;
7546     ULONG ulCount = 0;
7547     AFSDirectoryCB *pCurrentDirEntry = NULL, *pDirEntry = NULL;
7548
7549     pCurrentDirEntry = ObjectInfo->Specific.Directory.DirectoryNodeListHead;
7550
7551     while( pCurrentDirEntry != NULL)
7552     {
7553
7554         if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_FAKE))
7555         {
7556             ulCount++;
7557
7558             if( !BooleanFlagOn( pCurrentDirEntry->Flags, AFS_DIR_ENTRY_NOT_IN_PARENT_TREE))
7559             {
7560
7561                 pDirEntry = NULL;
7562
7563                 AFSLocateCaseSensitiveDirEntry( ObjectInfo->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
7564                                                 (ULONG)pCurrentDirEntry->CaseSensitiveTreeEntry.HashIndex,
7565                                                 &pDirEntry);
7566
7567                 if( pDirEntry == NULL)
7568                 {
7569                     DbgBreakPoint();
7570                 }
7571             }
7572         }
7573
7574         pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
7575     }
7576
7577     if( ulCount != (ULONG) ObjectInfo->Specific.Directory.DirectoryNodeCount)
7578     {
7579
7580         AFSPrint("AFSValidateDirList Count off Calc: %d Stored: %d\n",
7581                   ulCount,
7582                   ObjectInfo->Specific.Directory.DirectoryNodeCount);
7583
7584         ObjectInfo->Specific.Directory.DirectoryNodeCount = ulCount;
7585
7586         bIsValid = FALSE;
7587     }
7588
7589     return bIsValid;
7590 }
7591
7592 PFILE_OBJECT
7593 AFSReferenceCacheFileObject()
7594 {
7595
7596     AFSDeviceExt       *pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
7597     FILE_OBJECT        *pCacheFileObject = NULL;
7598
7599     AFSAcquireShared( &pRdrDevExt->Specific.RDR.CacheFileLock,
7600                       TRUE);
7601
7602     pCacheFileObject = pRdrDevExt->Specific.RDR.CacheFileObject;
7603
7604     if( pCacheFileObject != NULL)
7605     {
7606         ObReferenceObject( pCacheFileObject);
7607     }
7608
7609     AFSReleaseResource( &pRdrDevExt->Specific.RDR.CacheFileLock);
7610
7611     return pCacheFileObject;
7612 }
7613
7614 void
7615 AFSReleaseCacheFileObject( IN PFILE_OBJECT CacheFileObject)
7616 {
7617
7618     ASSERT( CacheFileObject != NULL);
7619
7620     ObDereferenceObject( CacheFileObject);
7621
7622     return;
7623 }
7624
7625 NTSTATUS
7626 AFSInitializeLibrary( IN AFSLibraryInitCB *LibraryInit)
7627 {
7628
7629     NTSTATUS ntStatus = STATUS_SUCCESS;
7630     AFSDeviceExt *pControlDevExt = NULL;
7631     ULONG ulTimeIncrement = 0;
7632     LONG lCount;
7633
7634     __Enter
7635     {
7636
7637         AFSControlDeviceObject = LibraryInit->AFSControlDeviceObject;
7638
7639         AFSRDRDeviceObject = LibraryInit->AFSRDRDeviceObject;
7640
7641         AFSServerName = LibraryInit->AFSServerName;
7642
7643         AFSMountRootName = LibraryInit->AFSMountRootName;
7644
7645         AFSDebugFlags = LibraryInit->AFSDebugFlags;
7646
7647         //
7648         // Callbacks in the framework
7649         //
7650
7651         AFSProcessRequest = LibraryInit->AFSProcessRequest;
7652
7653         AFSDbgLogMsg = LibraryInit->AFSDbgLogMsg;
7654
7655         AFSDebugTraceFnc = AFSDbgLogMsg;
7656
7657         AFSAddConnectionEx = LibraryInit->AFSAddConnectionEx;
7658
7659         AFSExAllocatePoolWithTag = LibraryInit->AFSExAllocatePoolWithTag;
7660
7661         AFSExFreePoolWithTag = LibraryInit->AFSExFreePoolWithTag;
7662
7663         AFSDumpTraceFilesFnc = LibraryInit->AFSDumpTraceFiles;
7664
7665         AFSRetrieveAuthGroupFnc = LibraryInit->AFSRetrieveAuthGroup;
7666
7667         AFSLibCacheManagerCallbacks = LibraryInit->AFSCacheManagerCallbacks;
7668
7669         if( LibraryInit->AFSCacheBaseAddress != NULL)
7670         {
7671
7672             SetFlag( AFSLibControlFlags, AFS_REDIR_LIB_FLAGS_NONPERSISTENT_CACHE);
7673
7674             AFSLibCacheBaseAddress = LibraryInit->AFSCacheBaseAddress;
7675
7676             AFSLibCacheLength = LibraryInit->AFSCacheLength;
7677         }
7678
7679         //
7680         // Initialize some flush parameters
7681         //
7682
7683         pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
7684
7685         ulTimeIncrement = KeQueryTimeIncrement();
7686
7687         pControlDevExt->Specific.Control.ObjectLifeTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_OBJECT_LIFETIME / (ULONGLONG)ulTimeIncrement);
7688         pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart = AFS_SERVER_PURGE_DELAY;
7689         pControlDevExt->Specific.Control.FcbPurgeTimeCount.QuadPart /= ulTimeIncrement;
7690         pControlDevExt->Specific.Control.FcbFlushTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_SERVER_FLUSH_DELAY / (ULONGLONG)ulTimeIncrement);
7691         pControlDevExt->Specific.Control.ExtentRequestTimeCount.QuadPart = (ULONGLONG)((ULONGLONG)AFS_EXTENT_REQUEST_TIME/(ULONGLONG)ulTimeIncrement);
7692
7693         //
7694         // Initialize the global root entry
7695         //
7696
7697         ntStatus = AFSInitVolume( NULL,
7698                                   &LibraryInit->GlobalRootFid,
7699                                   AFS_VOLUME_REFERENCE_GLOBAL_ROOT,
7700                                   &AFSGlobalRoot);
7701
7702         if( !NT_SUCCESS( ntStatus))
7703         {
7704
7705             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
7706                           AFS_TRACE_LEVEL_ERROR,
7707                           "AFSInitializeLibrary AFSInitVolume failure %08lX\n",
7708                           ntStatus));
7709
7710             try_return( ntStatus);
7711         }
7712
7713         ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
7714                                    AFSGlobalRoot);
7715
7716         if( !NT_SUCCESS( ntStatus))
7717         {
7718
7719             AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
7720                           AFS_TRACE_LEVEL_ERROR,
7721                           "AFSInitializeLibrary AFSInitRootFcb failure %08lX\n",
7722                           ntStatus));
7723
7724             lCount = AFSVolumeDecrement( AFSGlobalRoot,
7725                                          AFS_VOLUME_REFERENCE_GLOBAL_ROOT);
7726
7727             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7728                           AFS_TRACE_LEVEL_VERBOSE,
7729                           "AFSInitializeLibrary Decrement count on volume %p Cnt %d\n",
7730                           AFSGlobalRoot,
7731                           lCount));
7732
7733             AFSReleaseResource( AFSGlobalRoot->VolumeLock);
7734
7735             try_return( ntStatus);
7736         }
7737
7738         //
7739         // Update the node type code to AFS_ROOT_ALL
7740         //
7741
7742         AFSGlobalRoot->ObjectInformation.Fcb->Header.NodeTypeCode = AFS_ROOT_ALL;
7743
7744         SetFlag( AFSGlobalRoot->Flags, AFS_VOLUME_ACTIVE_GLOBAL_ROOT);
7745
7746         //
7747         // Invalidate all known volumes since contact with the service and therefore
7748         // the file server was lost.
7749         //
7750
7751         AFSInvalidateAllVolumes();
7752
7753         //
7754         // Drop the locks acquired above
7755         //
7756
7757         AFSInitVolumeWorker( AFSGlobalRoot);
7758
7759         lCount = AFSVolumeDecrement( AFSGlobalRoot,
7760                                      AFS_VOLUME_REFERENCE_GLOBAL_ROOT);
7761
7762         AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7763                       AFS_TRACE_LEVEL_VERBOSE,
7764                       "AFSInitializeLibrary Decrement count on volume %p Cnt %d\n",
7765                       AFSGlobalRoot,
7766                       lCount));
7767
7768         AFSReleaseResource( AFSGlobalRoot->VolumeLock);
7769
7770         AFSReleaseResource( AFSGlobalRoot->ObjectInformation.Fcb->Header.Resource);
7771
7772 try_exit:
7773
7774         NOTHING;
7775     }
7776
7777     return ntStatus;
7778 }
7779
7780 NTSTATUS
7781 AFSCloseLibrary()
7782 {
7783
7784     NTSTATUS ntStatus = STATUS_SUCCESS;
7785     AFSDirectoryCB *pDirNode = NULL, *pLastDirNode = NULL;
7786     LONG lCount;
7787
7788     __Enter
7789     {
7790
7791         if( AFSGlobalDotDirEntry != NULL)
7792         {
7793
7794             lCount = AFSObjectInfoDecrement( AFSGlobalDotDirEntry->ObjectInformation,
7795                                              AFS_OBJECT_REFERENCE_GLOBAL);
7796
7797             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
7798                           AFS_TRACE_LEVEL_VERBOSE,
7799                           "AFSCloseLibrary Decrement count on parent object %p Cnt %d\n",
7800                           AFSGlobalDotDirEntry->ObjectInformation,
7801                           lCount));
7802
7803             if ( lCount == 0)
7804             {
7805
7806                 AFSDeleteObjectInfo( &AFSGlobalDotDirEntry->ObjectInformation);
7807             }
7808
7809             ExDeleteResourceLite( &AFSGlobalDotDirEntry->NonPaged->Lock);
7810
7811             ExFreePool( AFSGlobalDotDirEntry->NonPaged);
7812
7813             ExFreePool( AFSGlobalDotDirEntry);
7814
7815             AFSGlobalDotDirEntry = NULL;
7816         }
7817
7818         if( AFSGlobalDotDotDirEntry != NULL)
7819         {
7820
7821             lCount = AFSObjectInfoDecrement( AFSGlobalDotDotDirEntry->ObjectInformation,
7822                                              AFS_OBJECT_REFERENCE_GLOBAL);
7823
7824             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
7825                           AFS_TRACE_LEVEL_VERBOSE,
7826                           "AFSCloseLibrary Decrement count on parent object %p Cnt %d\n",
7827                           AFSGlobalDotDotDirEntry->ObjectInformation,
7828                           lCount));
7829
7830             if ( lCount == 0)
7831             {
7832
7833                 AFSDeleteObjectInfo( &AFSGlobalDotDotDirEntry->ObjectInformation);
7834             }
7835
7836             ExDeleteResourceLite( &AFSGlobalDotDotDirEntry->NonPaged->Lock);
7837
7838             ExFreePool( AFSGlobalDotDotDirEntry->NonPaged);
7839
7840             ExFreePool( AFSGlobalDotDotDirEntry);
7841
7842             AFSGlobalDotDotDirEntry = NULL;
7843         }
7844
7845         if( AFSSpecialShareNames != NULL)
7846         {
7847
7848             pDirNode = AFSSpecialShareNames;
7849
7850             while( pDirNode != NULL)
7851             {
7852
7853                 pLastDirNode = (AFSDirectoryCB *)pDirNode->ListEntry.fLink;
7854
7855                 lCount = AFSObjectInfoDecrement( pDirNode->ObjectInformation,
7856                                                  AFS_OBJECT_REFERENCE_GLOBAL);
7857
7858                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
7859                               AFS_TRACE_LEVEL_VERBOSE,
7860                               "AFSCloseLibrary Decrement count on parent object %p Cnt %d\n",
7861                               pDirNode->ObjectInformation,
7862                               lCount));
7863
7864                 if ( lCount == 0)
7865                 {
7866
7867                     AFSDeleteObjectInfo( &pDirNode->ObjectInformation);
7868                 }
7869
7870                 ExDeleteResourceLite( &pDirNode->NonPaged->Lock);
7871
7872                 ExFreePool( pDirNode->NonPaged);
7873
7874                 ExFreePool( pDirNode);
7875
7876                 pDirNode = pLastDirNode;
7877             }
7878
7879             AFSSpecialShareNames = NULL;
7880         }
7881     }
7882
7883     return ntStatus;
7884 }
7885
7886 NTSTATUS
7887 AFSDefaultLogMsg( IN ULONG Subsystem,
7888                   IN ULONG Level,
7889                   IN PCCH Format,
7890                   ...)
7891 {
7892
7893     UNREFERENCED_PARAMETER(Subsystem);
7894     UNREFERENCED_PARAMETER(Level);
7895     NTSTATUS ntStatus = STATUS_SUCCESS;
7896     va_list va_args;
7897     char chDebugBuffer[ 256];
7898
7899     __Enter
7900     {
7901
7902         va_start( va_args, Format);
7903
7904         ntStatus = RtlStringCbVPrintfA( chDebugBuffer,
7905                                         256,
7906                                         Format,
7907                                         va_args);
7908
7909         if( NT_SUCCESS( ntStatus))
7910         {
7911             DbgPrint( chDebugBuffer);
7912         }
7913
7914         va_end( va_args);
7915     }
7916
7917     return ntStatus;
7918 }
7919
7920 NTSTATUS
7921 AFSGetObjectStatus( IN AFSGetStatusInfoCB *GetStatusInfo,
7922                     IN ULONG InputBufferLength,
7923                     IN AFSStatusInfoCB *StatusInfo,
7924                     OUT ULONG *ReturnLength)
7925 {
7926
7927     NTSTATUS ntStatus = STATUS_SUCCESS;
7928     AFSVolumeCB *pVolumeCB = NULL;
7929     LONG VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
7930     AFSVolumeCB *pNewVolumeCB = NULL;
7931     LONG NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
7932     AFSDeviceExt *pDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
7933     AFSObjectInfoCB *pObjectInfo = NULL;
7934     ULONGLONG   ullIndex = 0;
7935     UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName, uniParsedName;
7936     AFSNameArrayHdr *pNameArray = NULL;
7937     AFSDirectoryCB *pDirectoryEntry = NULL, *pParentDirEntry = NULL;
7938     AFSDirectoryCB *pNewParentDirEntry = NULL;
7939     LONG lCount;
7940
7941     __Enter
7942     {
7943
7944         //
7945         // If we are given a FID then look up the entry by that, otherwise
7946         // do it by name
7947         //
7948
7949         if( GetStatusInfo->FileID.Cell != 0 &&
7950             GetStatusInfo->FileID.Volume != 0 &&
7951             GetStatusInfo->FileID.Vnode != 0 &&
7952             GetStatusInfo->FileID.Unique != 0)
7953         {
7954
7955             AFSAcquireShared( &pDevExt->Specific.RDR.VolumeTreeLock, TRUE);
7956
7957             //
7958             // Locate the volume node
7959             //
7960
7961             ullIndex = AFSCreateHighIndex( &GetStatusInfo->FileID);
7962
7963             ntStatus = AFSLocateHashEntry( pDevExt->Specific.RDR.VolumeTree.TreeHead,
7964                                            ullIndex,
7965                                            (AFSBTreeEntry **)&pVolumeCB);
7966
7967             if( pVolumeCB != NULL)
7968             {
7969
7970                 VolumeReferenceReason = AFS_VOLUME_REFERENCE_GET_OBJECT;
7971
7972                 lCount = AFSVolumeIncrement( pVolumeCB,
7973                                              VolumeReferenceReason);
7974
7975                 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
7976                               AFS_TRACE_LEVEL_VERBOSE,
7977                               "AFSGetObjectStatus Increment count on volume %p Reason %u Cnt %d\n",
7978                               pVolumeCB,
7979                               VolumeReferenceReason,
7980                               lCount));
7981             }
7982
7983             AFSReleaseResource( &pDevExt->Specific.RDR.VolumeTreeLock);
7984
7985             if( !NT_SUCCESS( ntStatus) ||
7986                 pVolumeCB == NULL)
7987             {
7988                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
7989             }
7990
7991             if( AFSIsVolumeFID( &GetStatusInfo->FileID))
7992             {
7993
7994                 pObjectInfo = &pVolumeCB->ObjectInformation;
7995
7996                 lCount = AFSObjectInfoIncrement( pObjectInfo,
7997                                                  AFS_OBJECT_REFERENCE_STATUS);
7998
7999                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8000                               AFS_TRACE_LEVEL_VERBOSE,
8001                               "AFSGetObjectStatus Increment1 count on object %p Cnt %d\n",
8002                               pObjectInfo,
8003                               lCount));
8004             }
8005             else
8006             {
8007
8008                 AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
8009                                   TRUE);
8010
8011                 ullIndex = AFSCreateLowIndex( &GetStatusInfo->FileID);
8012
8013                 ntStatus = AFSLocateHashEntry( pVolumeCB->ObjectInfoTree.TreeHead,
8014                                                ullIndex,
8015                                                (AFSBTreeEntry **)&pObjectInfo);
8016
8017                 if( pObjectInfo != NULL)
8018                 {
8019
8020                     //
8021                     // Reference the node so it won't be torn down
8022                     //
8023
8024                     lCount = AFSObjectInfoIncrement( pObjectInfo,
8025                                                      AFS_OBJECT_REFERENCE_STATUS);
8026
8027                     AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8028                                   AFS_TRACE_LEVEL_VERBOSE,
8029                                   "AFSGetObjectStatus Increment2 count on object %p Cnt %d\n",
8030                                   pObjectInfo,
8031                                   lCount));
8032                 }
8033
8034                 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
8035
8036                 if( !NT_SUCCESS( ntStatus) ||
8037                     pObjectInfo == NULL)
8038                 {
8039                     try_return( ntStatus = STATUS_INVALID_PARAMETER);
8040                 }
8041             }
8042         }
8043         else
8044         {
8045
8046             if( GetStatusInfo->FileNameLength == 0 ||
8047                 InputBufferLength < (ULONG)(FIELD_OFFSET( AFSGetStatusInfoCB, FileName) + GetStatusInfo->FileNameLength))
8048             {
8049                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
8050             }
8051
8052             uniFullPathName.Length = GetStatusInfo->FileNameLength;
8053             uniFullPathName.MaximumLength = uniFullPathName.Length;
8054
8055             uniFullPathName.Buffer = (WCHAR *)GetStatusInfo->FileName;
8056
8057             //
8058             // This name should begin with the \afs server so parse it off and check it
8059             //
8060
8061             FsRtlDissectName( uniFullPathName,
8062                               &uniComponentName,
8063                               &uniRemainingPath);
8064
8065             if( RtlCompareUnicodeString( &uniComponentName,
8066                                          &AFSServerName,
8067                                          TRUE) != 0)
8068             {
8069                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8070                               AFS_TRACE_LEVEL_ERROR,
8071                               "AFSGetObjectStatus Name %wZ contains invalid server name\n",
8072                               &uniFullPathName));
8073
8074                 try_return( ntStatus = STATUS_OBJECT_PATH_INVALID);
8075             }
8076
8077             uniFullPathName = uniRemainingPath;
8078
8079             uniParsedName = uniFullPathName;
8080
8081             //
8082             // Our name array
8083             //
8084
8085             pNameArray = AFSInitNameArray( AFSGlobalRoot->DirectoryCB,
8086                                            0);
8087
8088             if( pNameArray == NULL)
8089             {
8090                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8091             }
8092
8093             pVolumeCB = AFSGlobalRoot;
8094
8095             pParentDirEntry = AFSGlobalRoot->DirectoryCB;
8096
8097             //
8098             // Increment the ref count on the volume and dir entry for correct processing below
8099             //
8100
8101             VolumeReferenceReason = AFS_VOLUME_REFERENCE_GET_OBJECT;
8102
8103             lCount = AFSVolumeIncrement( pVolumeCB,
8104                                          VolumeReferenceReason);
8105
8106             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8107                           AFS_TRACE_LEVEL_VERBOSE,
8108                           "AFSGetObjectStatus Increment2 count on volume %p Reason %u Cnt %d\n",
8109                           pVolumeCB,
8110                           VolumeReferenceReason,
8111                           lCount));
8112
8113             lCount = InterlockedIncrement( &pParentDirEntry->DirOpenReferenceCount);
8114
8115             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8116                           AFS_TRACE_LEVEL_VERBOSE,
8117                           "AFSGetObjectStatus Increment count on %wZ DE %p Ccb %p Cnt %d\n",
8118                           &pParentDirEntry->NameInformation.FileName,
8119                           pParentDirEntry,
8120                           NULL,
8121                           lCount));
8122
8123             ntStatus = AFSLocateNameEntry( NULL,
8124                                            NULL,
8125                                            &uniFullPathName,
8126                                            &uniParsedName,
8127                                            pNameArray,
8128                                            AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL |
8129                                                AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL,
8130                                            pVolumeCB,
8131                                            pParentDirEntry,
8132                                            &pNewVolumeCB,
8133                                            &NewVolumeReferenceReason,
8134                                            &pNewParentDirEntry,
8135                                            &pDirectoryEntry,
8136                                            NULL);
8137
8138             if ( pNewVolumeCB != NULL)
8139             {
8140
8141                 //
8142                 // AFSLocateNameEntry returns pNewVolumeCB with a reference held
8143                 // even if pVolumeCB == pNewVolumeCB.  It is always safe to release
8144                 // the reference on pVolumeCB that was held prior to the call.
8145                 // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
8146                 // will be released second.
8147                 //
8148
8149                 lCount = AFSVolumeDecrement( pVolumeCB,
8150                                              VolumeReferenceReason);
8151
8152                 AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8153                               AFS_TRACE_LEVEL_VERBOSE,
8154                               "AFSGetObjectStatus Decrement count on volume %p Reason %u Cnt %d\n",
8155                               pVolumeCB,
8156                               VolumeReferenceReason,
8157                               lCount));
8158
8159                 pVolumeCB = pNewVolumeCB;
8160
8161                 pNewVolumeCB = NULL;
8162
8163                 VolumeReferenceReason = NewVolumeReferenceReason;
8164
8165                 NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
8166             }
8167
8168             //
8169             // AFSLocateNameEntry does not alter the reference count of
8170             // pParentDirectoryCB and it returns pNewParentDirectoryCB with
8171             // a reference held.
8172             //
8173
8174             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
8175
8176             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8177                           AFS_TRACE_LEVEL_VERBOSE,
8178                           "AFSGetObjectStatus DecrementX count on %wZ DE %p Cnt %d\n",
8179                           &pParentDirEntry->NameInformation.FileName,
8180                           pParentDirEntry,
8181                           lCount));
8182
8183             pParentDirEntry = pNewParentDirEntry;
8184
8185             pNewParentDirEntry = NULL;
8186
8187             if( !NT_SUCCESS( ntStatus) ||
8188                 ntStatus == STATUS_REPARSE)
8189             {
8190
8191                 pVolumeCB = NULL;
8192
8193                 try_return( ntStatus);
8194             }
8195
8196             pObjectInfo = pDirectoryEntry->ObjectInformation;
8197
8198             lCount = AFSObjectInfoIncrement( pObjectInfo,
8199                                              AFS_OBJECT_REFERENCE_STATUS);
8200
8201             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8202                           AFS_TRACE_LEVEL_VERBOSE,
8203                           "AFSGetObjectStatus Increment3 count on object %p Cnt %d\n",
8204                           pObjectInfo,
8205                           lCount));
8206         }
8207
8208         //
8209         // At this point we have an object info block, return the information
8210         //
8211
8212         StatusInfo->FileId = pObjectInfo->FileId;
8213
8214         StatusInfo->TargetFileId = pObjectInfo->TargetFileId;
8215
8216         StatusInfo->Expiration = pObjectInfo->Expiration;
8217
8218         StatusInfo->DataVersion = pObjectInfo->DataVersion;
8219
8220         StatusInfo->FileType = pObjectInfo->FileType;
8221
8222         StatusInfo->ObjectFlags = pObjectInfo->Flags;
8223
8224         StatusInfo->CreationTime = pObjectInfo->CreationTime;
8225
8226         StatusInfo->LastAccessTime = pObjectInfo->LastAccessTime;
8227
8228         StatusInfo->LastWriteTime = pObjectInfo->LastWriteTime;
8229
8230         StatusInfo->ChangeTime = pObjectInfo->ChangeTime;
8231
8232         StatusInfo->FileAttributes = pObjectInfo->FileAttributes;
8233
8234         StatusInfo->EndOfFile = pObjectInfo->EndOfFile;
8235
8236         StatusInfo->AllocationSize = pObjectInfo->AllocationSize;
8237
8238         StatusInfo->EaSize = pObjectInfo->EaSize;
8239
8240         StatusInfo->Links = pObjectInfo->Links;
8241
8242         //
8243         // Return the information length
8244         //
8245
8246         *ReturnLength = sizeof( AFSStatusInfoCB);
8247
8248 try_exit:
8249
8250         if( pDirectoryEntry != NULL)
8251         {
8252
8253             lCount = InterlockedDecrement( &pDirectoryEntry->DirOpenReferenceCount);
8254
8255             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8256                           AFS_TRACE_LEVEL_VERBOSE,
8257                           "AFSGetObjectStatus Decrement1 count on %wZ DE %p Ccb %p Cnt %d\n",
8258                           &pDirectoryEntry->NameInformation.FileName,
8259                           pDirectoryEntry,
8260                           NULL,
8261                           lCount));
8262
8263             ASSERT( lCount >= 0);
8264         }
8265
8266         if ( pParentDirEntry != NULL)
8267         {
8268
8269             lCount = InterlockedDecrement( &pParentDirEntry->DirOpenReferenceCount);
8270
8271             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8272                           AFS_TRACE_LEVEL_VERBOSE,
8273                           "AFSGetObjectStatus Decrement2 count on %wZ DE %p Ccb %p Cnt %d\n",
8274                           &pParentDirEntry->NameInformation.FileName,
8275                           pParentDirEntry,
8276                           NULL,
8277                           lCount));
8278
8279             ASSERT( lCount >= 0);
8280         }
8281
8282         if( pObjectInfo != NULL)
8283         {
8284
8285             lCount = AFSObjectInfoDecrement( pObjectInfo,
8286                                              AFS_OBJECT_REFERENCE_STATUS);
8287
8288             AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
8289                           AFS_TRACE_LEVEL_VERBOSE,
8290                           "AFSGetObjectStatus Decrement count on object %p Cnt %d\n",
8291                           pObjectInfo,
8292                           lCount));
8293         }
8294
8295         if( pVolumeCB != NULL)
8296         {
8297
8298             lCount = AFSVolumeDecrement( pVolumeCB,
8299                                          VolumeReferenceReason);
8300
8301             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
8302                           AFS_TRACE_LEVEL_VERBOSE,
8303                           "AFSGetObjectStatus Decrement4 count on volume %p Reason %u Cnt %d\n",
8304                           pVolumeCB,
8305                           VolumeReferenceReason,
8306                           lCount));
8307         }
8308
8309         if( pNameArray != NULL)
8310         {
8311
8312             AFSFreeNameArray( pNameArray);
8313         }
8314     }
8315
8316     return ntStatus;
8317 }
8318
8319 NTSTATUS
8320 AFSCheckSymlinkAccess( IN AFSDirectoryCB *ParentDirectoryCB,
8321                        IN UNICODE_STRING *ComponentName)
8322 {
8323
8324     NTSTATUS ntStatus = STATUS_SUCCESS;
8325     AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
8326     AFSDirectoryCB *pDirEntry = NULL;
8327     ULONG ulCRC = 0;
8328     LONG lCount;
8329
8330     __Enter
8331     {
8332
8333         //
8334         // Search for the entry in the parent
8335         //
8336
8337         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8338                       AFS_TRACE_LEVEL_VERBOSE_2,
8339                       "AFSCheckSymlinkAccess Searching for entry %wZ case sensitive\n",
8340                       ComponentName));
8341
8342         ulCRC = AFSGenerateCRC( ComponentName,
8343                                 FALSE);
8344
8345         AFSAcquireShared( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
8346                           TRUE);
8347
8348         AFSLocateCaseSensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead,
8349                                         ulCRC,
8350                                         &pDirEntry);
8351
8352         if( pDirEntry == NULL)
8353         {
8354
8355             //
8356             // Missed so perform a case insensitive lookup
8357             //
8358
8359             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8360                           AFS_TRACE_LEVEL_VERBOSE_2,
8361                           "AFSCheckSymlinkAccess Searching for entry %wZ case insensitive\n",
8362                           ComponentName));
8363
8364             ulCRC = AFSGenerateCRC( ComponentName,
8365                                     TRUE);
8366
8367             AFSLocateCaseInsensitiveDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead,
8368                                               ulCRC,
8369                                               &pDirEntry);
8370
8371             if( pDirEntry == NULL)
8372             {
8373
8374                 //
8375                 // OK, if this component is a valid short name then try
8376                 // a lookup in the short name tree
8377                 //
8378
8379                 if( !BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES) &&
8380                     RtlIsNameLegalDOS8Dot3( ComponentName,
8381                                             NULL,
8382                                             NULL))
8383                 {
8384
8385                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8386                                   AFS_TRACE_LEVEL_VERBOSE_2,
8387                                   "AFSCheckSymlinkAccess Searching for entry %wZ short name\n",
8388                                   ComponentName));
8389
8390                     AFSLocateShortNameDirEntry( ParentDirectoryCB->ObjectInformation->Specific.Directory.ShortNameTree,
8391                                                 ulCRC,
8392                                                 &pDirEntry);
8393                 }
8394             }
8395         }
8396
8397         if( pDirEntry != NULL)
8398         {
8399             lCount = InterlockedIncrement( &pDirEntry->DirOpenReferenceCount);
8400
8401             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8402                           AFS_TRACE_LEVEL_VERBOSE,
8403                           "AFSCheckSymlinkAccess Increment count on %wZ DE %p Ccb %p Cnt %d\n",
8404                           &pDirEntry->NameInformation.FileName,
8405                           pDirEntry,
8406                           NULL,
8407                           lCount));
8408
8409             ASSERT( lCount >= 0);
8410         }
8411
8412         AFSReleaseResource( ParentDirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
8413
8414         if( pDirEntry == NULL)
8415         {
8416
8417             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8418                           AFS_TRACE_LEVEL_VERBOSE_2,
8419                           "AFSCheckSymlinkAccess Failed to locate entry %wZ ntStatus %08X\n",
8420                           ComponentName,
8421                           STATUS_OBJECT_NAME_NOT_FOUND));
8422
8423             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
8424         }
8425
8426         //
8427         // We have the symlink object but previously failed to process it so return access
8428         // denied.
8429         //
8430
8431         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
8432                       AFS_TRACE_LEVEL_VERBOSE_2,
8433                       "AFSCheckSymlinkAccess Failing symlink access to entry %wZ REPARSE_POINT_NOT_RESOLVED\n",
8434                       ComponentName));
8435
8436         ntStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
8437
8438         lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
8439
8440         AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
8441                       AFS_TRACE_LEVEL_VERBOSE,
8442                       "AFSCheckSymlinkAccess Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
8443                       &pDirEntry->NameInformation.FileName,
8444                       pDirEntry,
8445                       NULL,
8446                       lCount));
8447
8448         ASSERT( lCount >= 0);
8449
8450 try_exit:
8451
8452         NOTHING;
8453     }
8454
8455     return ntStatus;
8456 }
8457
8458 NTSTATUS
8459 AFSRetrieveFinalComponent( IN UNICODE_STRING *FullPathName,
8460                            OUT UNICODE_STRING *ComponentName)
8461 {
8462
8463     NTSTATUS ntStatus = STATUS_SUCCESS;
8464     UNICODE_STRING uniFullPathName, uniRemainingPath, uniComponentName;
8465
8466     uniFullPathName = *FullPathName;
8467
8468     while( TRUE)
8469     {
8470
8471         FsRtlDissectName( uniFullPathName,
8472                           &uniComponentName,
8473                           &uniRemainingPath);
8474
8475         if( uniRemainingPath.Length == 0)
8476         {
8477             break;
8478         }
8479
8480         uniFullPathName = uniRemainingPath;
8481     }
8482
8483     if( uniComponentName.Length > 0)
8484     {
8485         *ComponentName = uniComponentName;
8486     }
8487
8488     return ntStatus;
8489 }
8490
8491 void
8492 AFSDumpTraceFiles_Default()
8493 {
8494     return;
8495 }
8496
8497 BOOLEAN
8498 AFSValidNameFormat( IN UNICODE_STRING *FileName)
8499 {
8500
8501     BOOLEAN bIsValidName = TRUE;
8502     USHORT usIndex = 0;
8503
8504     __Enter
8505     {
8506
8507         while( usIndex < FileName->Length/sizeof( WCHAR))
8508         {
8509
8510             if( FileName->Buffer[ usIndex] == L':' ||
8511                 FileName->Buffer[ usIndex] == L'*' ||
8512                 FileName->Buffer[ usIndex] == L'?' ||
8513                 FileName->Buffer[ usIndex] == L'"' ||
8514                 FileName->Buffer[ usIndex] == L'<' ||
8515                 FileName->Buffer[ usIndex] == L'>')
8516             {
8517                 bIsValidName = FALSE;
8518                 break;
8519             }
8520
8521             usIndex++;
8522         }
8523     }
8524
8525     return bIsValidName;
8526 }
8527
8528 NTSTATUS
8529 AFSCreateDefaultSecurityDescriptor()
8530 {
8531
8532     NTSTATUS ntStatus = STATUS_SUCCESS;
8533     PACL pSACL = NULL;
8534     ULONG ulSACLSize = 0;
8535     SYSTEM_MANDATORY_LABEL_ACE* pACE = NULL;
8536     ULONG ulACESize = 0;
8537     SECURITY_DESCRIPTOR *pSecurityDescr = NULL;
8538     ULONG ulSDLength = 0;
8539     SECURITY_DESCRIPTOR *pRelativeSecurityDescr = NULL;
8540     PSID pWorldSID = NULL;
8541     ULONG *pulSubAuthority = NULL;
8542     ULONG ulWorldSIDLEngth = 0;
8543
8544     __Enter
8545     {
8546
8547         ulWorldSIDLEngth = RtlLengthRequiredSid( 1);
8548
8549         pWorldSID = (PSID)ExAllocatePoolWithTag( PagedPool,
8550                                                  ulWorldSIDLEngth,
8551                                                  AFS_GENERIC_MEMORY_29_TAG);
8552
8553         if( pWorldSID == NULL)
8554         {
8555             AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate World SID\n");
8556
8557             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8558         }
8559
8560         RtlZeroMemory( pWorldSID,
8561                        ulWorldSIDLEngth);
8562
8563         RtlInitializeSid( pWorldSID,
8564                           &SeWorldSidAuthority,
8565                           1);
8566
8567         pulSubAuthority = RtlSubAuthoritySid(pWorldSID, 0);
8568         *pulSubAuthority = SECURITY_WORLD_RID;
8569
8570         if( AFSRtlSetSaclSecurityDescriptor == NULL)
8571         {
8572
8573             AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor == NULL\n");
8574         }
8575         else
8576         {
8577
8578             ulACESize = sizeof( SYSTEM_MANDATORY_LABEL_ACE) + 128;
8579
8580             pACE = (SYSTEM_MANDATORY_LABEL_ACE *)ExAllocatePoolWithTag( PagedPool,
8581                                                                         ulACESize,
8582                                                                         AFS_GENERIC_MEMORY_29_TAG);
8583
8584             if( pACE == NULL)
8585             {
8586
8587                 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8588
8589                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8590             }
8591
8592             RtlZeroMemory( pACE,
8593                            ulACESize);
8594
8595             pACE->Header.AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
8596             pACE->Header.AceType = SYSTEM_MANDATORY_LABEL_ACE_TYPE;
8597             pACE->Header.AceSize = FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + (USHORT)RtlLengthSid( SeExports->SeLowMandatorySid);
8598             pACE->Mask = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP;
8599
8600             RtlCopySid( RtlLengthSid( SeExports->SeLowMandatorySid),
8601                         &pACE->SidStart,
8602                         SeExports->SeLowMandatorySid);
8603
8604             ulSACLSize = sizeof(ACL) + RtlLengthSid( SeExports->SeLowMandatorySid) +
8605                 FIELD_OFFSET( SYSTEM_MANDATORY_LABEL_ACE, SidStart) + ulACESize;
8606
8607             pSACL = (PACL)ExAllocatePoolWithTag( PagedPool,
8608                                                  ulSACLSize,
8609                                                  AFS_GENERIC_MEMORY_29_TAG);
8610
8611             if( pSACL == NULL)
8612             {
8613
8614                 AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_29_TAG\n");
8615
8616                 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8617             }
8618
8619             ntStatus = RtlCreateAcl( pSACL,
8620                                      ulSACLSize,
8621                                      ACL_REVISION);
8622
8623             if( !NT_SUCCESS( ntStatus))
8624             {
8625
8626                 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateAcl ntStatus %08lX\n",
8627                           ntStatus);
8628
8629                 try_return( ntStatus);
8630             }
8631
8632             ntStatus = RtlAddAce( pSACL,
8633                                   ACL_REVISION,
8634                                   0,
8635                                   pACE,
8636                                   pACE->Header.AceSize);
8637
8638             if( !NT_SUCCESS( ntStatus))
8639             {
8640
8641                 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAddAce ntStatus %08lX\n",
8642                           ntStatus);
8643
8644                 try_return( ntStatus);
8645             }
8646         }
8647
8648         pSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
8649                                                                        sizeof( SECURITY_DESCRIPTOR),
8650                                                                        AFS_GENERIC_MEMORY_27_TAG);
8651
8652         if( pSecurityDescr == NULL)
8653         {
8654
8655             AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8656
8657             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8658         }
8659
8660         ntStatus = RtlCreateSecurityDescriptor( pSecurityDescr,
8661                                                 SECURITY_DESCRIPTOR_REVISION);
8662
8663         if( !NT_SUCCESS( ntStatus))
8664         {
8665
8666             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlCreateSecurityDescriptor ntStatus %08lX\n",
8667                       ntStatus);
8668
8669             try_return( ntStatus);
8670         }
8671
8672         if( AFSRtlSetSaclSecurityDescriptor != NULL)
8673         {
8674             ntStatus = AFSRtlSetSaclSecurityDescriptor( pSecurityDescr,
8675                                                         TRUE,
8676                                                         pSACL,
8677                                                         FALSE);
8678
8679             if( !NT_SUCCESS( ntStatus))
8680             {
8681
8682                 AFSPrint( "AFSCreateDefaultSecurityDescriptor AFSRtlSetSaclSecurityDescriptor ntStatus %08lX\n",
8683                           ntStatus);
8684
8685                 try_return( ntStatus);
8686             }
8687         }
8688
8689         //
8690         // Add in the group and owner to the SD
8691         //
8692
8693         if( AFSRtlSetGroupSecurityDescriptor != NULL)
8694         {
8695             ntStatus = AFSRtlSetGroupSecurityDescriptor( pSecurityDescr,
8696                                                          pWorldSID,
8697                                                          FALSE);
8698
8699             if( !NT_SUCCESS( ntStatus))
8700             {
8701
8702                 AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetGroupSecurityDescriptor failed ntStatus %08lX\n",
8703                           ntStatus);
8704
8705                 try_return( ntStatus);
8706             }
8707         }
8708
8709         ntStatus = RtlSetOwnerSecurityDescriptor( pSecurityDescr,
8710                                                   pWorldSID,
8711                                                   FALSE);
8712
8713         if( !NT_SUCCESS( ntStatus))
8714         {
8715
8716             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlSetOwnerSecurityDescriptor failed ntStatus %08lX\n",
8717                       ntStatus);
8718
8719             try_return( ntStatus);
8720         }
8721
8722         if( !RtlValidSecurityDescriptor( pSecurityDescr))
8723         {
8724
8725             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlValidSecurityDescriptor NOT\n");
8726
8727             try_return( ntStatus = STATUS_INVALID_PARAMETER);
8728         }
8729
8730         pRelativeSecurityDescr = (SECURITY_DESCRIPTOR *)ExAllocatePoolWithTag( NonPagedPool,
8731                                                                                PAGE_SIZE,
8732                                                                                AFS_GENERIC_MEMORY_27_TAG);
8733
8734         if( pRelativeSecurityDescr == NULL)
8735         {
8736
8737             AFSPrint( "AFSCreateDefaultSecurityDescriptor unable to allocate AFS_GENERIC_MEMORY_27_TAG\n");
8738
8739             try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
8740         }
8741
8742         ulSDLength = PAGE_SIZE;
8743
8744         ntStatus = RtlAbsoluteToSelfRelativeSD( pSecurityDescr,
8745                                                 pRelativeSecurityDescr,
8746                                                 &ulSDLength);
8747
8748         if( !NT_SUCCESS( ntStatus))
8749         {
8750
8751             AFSPrint( "AFSCreateDefaultSecurityDescriptor RtlAbsoluteToSelfRelativeSD ntStatus %08lX\n",
8752                       ntStatus);
8753
8754             try_return( ntStatus);
8755         }
8756
8757         AFSDefaultSD = pRelativeSecurityDescr;
8758
8759 try_exit:
8760
8761         if( !NT_SUCCESS( ntStatus))
8762         {
8763
8764             if( pRelativeSecurityDescr != NULL)
8765             {
8766                 ExFreePool( pRelativeSecurityDescr);
8767             }
8768         }
8769
8770         if( pSecurityDescr != NULL)
8771         {
8772             ExFreePool( pSecurityDescr);
8773         }
8774
8775         if( pSACL != NULL)
8776         {
8777             ExFreePool( pSACL);
8778         }
8779
8780         if( pACE != NULL)
8781         {
8782             ExFreePool( pACE);
8783         }
8784
8785         if( pWorldSID != NULL)
8786         {
8787             ExFreePool( pWorldSID);
8788         }
8789     }
8790
8791     return ntStatus;
8792 }
8793
8794 void
8795 AFSRetrieveParentPath( IN UNICODE_STRING *FullFileName,
8796                        OUT UNICODE_STRING *ParentPath)
8797 {
8798
8799     *ParentPath = *FullFileName;
8800
8801     //
8802     // If the final character is a \, jump over it
8803     //
8804
8805     if( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] == L'\\')
8806     {
8807         ParentPath->Length -= sizeof( WCHAR);
8808     }
8809
8810     while( ParentPath->Buffer[ (ParentPath->Length/sizeof( WCHAR)) - 1] != L'\\')
8811     {
8812         ParentPath->Length -= sizeof( WCHAR);
8813     }
8814
8815     //
8816     // And the separator
8817     //
8818
8819     ParentPath->Length -= sizeof( WCHAR);
8820
8821     return;
8822 }
8823
8824 NTSTATUS
8825 AFSRetrieveValidAuthGroup( IN AFSFcb *Fcb,
8826                            IN AFSObjectInfoCB *ObjectInfo,
8827                            IN BOOLEAN WriteAccess,
8828                            OUT GUID *AuthGroup)
8829 {
8830
8831     NTSTATUS ntStatus = STATUS_SUCCESS;
8832     GUID     stAuthGroup, stZeroAuthGroup;
8833     BOOLEAN  bFoundAuthGroup = FALSE;
8834     AFSCcb  *pCcb = NULL;
8835     AFSFcb *pFcb = Fcb;
8836
8837     __Enter
8838     {
8839
8840         RtlZeroMemory( &stAuthGroup,
8841                        sizeof( GUID));
8842
8843         RtlZeroMemory( &stZeroAuthGroup,
8844                        sizeof( GUID));
8845
8846         if( Fcb == NULL)
8847         {
8848
8849             if( ObjectInfo != NULL &&
8850                 ObjectInfo->Fcb != NULL)
8851             {
8852                 pFcb = ObjectInfo->Fcb;
8853             }
8854         }
8855
8856         if( pFcb != NULL)
8857         {
8858
8859             AFSAcquireShared( &Fcb->NPFcb->CcbListLock,
8860                               TRUE);
8861
8862             pCcb = Fcb->CcbListHead;
8863
8864             while( pCcb != NULL)
8865             {
8866
8867                 if( WriteAccess &&
8868                     pCcb->GrantedAccess & FILE_WRITE_DATA)
8869                 {
8870                     RtlCopyMemory( &stAuthGroup,
8871                                    &pCcb->AuthGroup,
8872                                    sizeof( GUID));
8873
8874                     bFoundAuthGroup = TRUE;
8875
8876                     break;
8877                 }
8878                 else if( pCcb->GrantedAccess & FILE_READ_DATA)
8879                 {
8880                     //
8881                     // At least get the read-only access
8882                     //
8883
8884                     RtlCopyMemory( &stAuthGroup,
8885                                    &pCcb->AuthGroup,
8886                                    sizeof( GUID));
8887
8888                     bFoundAuthGroup = TRUE;
8889                 }
8890
8891                 pCcb = (AFSCcb *)pCcb->ListEntry.fLink;
8892             }
8893
8894             AFSReleaseResource( &Fcb->NPFcb->CcbListLock);
8895         }
8896
8897         if( !bFoundAuthGroup)
8898         {
8899
8900             AFSRetrieveAuthGroupFnc( (ULONGLONG)PsGetCurrentProcessId(),
8901                                      (ULONGLONG)PsGetCurrentThreadId(),
8902                                       &stAuthGroup);
8903
8904             if( RtlCompareMemory( &stZeroAuthGroup,
8905                                   &stAuthGroup,
8906                                   sizeof( GUID)) == sizeof( GUID))
8907             {
8908
8909                 DbgPrint("AFSRetrieveValidAuthGroup Failed to locate PAG\n");
8910
8911                 try_return( ntStatus = STATUS_ACCESS_DENIED);
8912             }
8913         }
8914
8915         RtlCopyMemory( AuthGroup,
8916                        &stAuthGroup,
8917                        sizeof( GUID));
8918
8919 try_exit:
8920
8921         NOTHING;
8922     }
8923
8924     return ntStatus;
8925 }
8926
8927 NTSTATUS
8928 AFSPerformObjectInvalidate( IN AFSObjectInfoCB *ObjectInfo,
8929                             IN ULONG InvalidateReason)
8930 {
8931
8932     NTSTATUS            ntStatus = STATUS_SUCCESS;
8933     LIST_ENTRY         *le;
8934     AFSExtent          *pEntry;
8935     ULONG               ulProcessCount = 0;
8936     ULONG               ulCount = 0;
8937     LONG                lCount;
8938
8939     __Enter
8940     {
8941
8942         switch( InvalidateReason)
8943         {
8944
8945             case AFS_INVALIDATE_DELETED:
8946             {
8947
8948                 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
8949                     ObjectInfo->Fcb != NULL)
8950                 {
8951
8952                     AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
8953                                     TRUE);
8954
8955                     ObjectInfo->Links = 0;
8956
8957                     ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_FILE_DELETED;
8958
8959                     KeSetEvent( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsRequestComplete,
8960                                 0,
8961                                 FALSE);
8962
8963                     //
8964                     // Clear out the extents
8965                     // And get rid of them (note this involves waiting
8966                     // for any writes or reads to the cache to complete)
8967                     //
8968
8969                     AFSTearDownFcbExtents( ObjectInfo->Fcb,
8970                                            NULL);
8971
8972                     AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource);
8973                 }
8974
8975                 break;
8976             }
8977
8978             case AFS_INVALIDATE_DATA_VERSION:
8979             {
8980
8981                 LARGE_INTEGER liCurrentOffset = {0,0};
8982                 LARGE_INTEGER liFlushLength = {0,0};
8983                 ULONG ulFlushLength = 0;
8984                 BOOLEAN bLocked = FALSE;
8985                 BOOLEAN bExtentsLocked = FALSE;
8986                 BOOLEAN bCleanExtents = FALSE;
8987
8988                 if( ObjectInfo->FileType == AFS_FILE_TYPE_FILE &&
8989                     ObjectInfo->Fcb != NULL)
8990                 {
8991
8992                     AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->Resource,
8993                                     TRUE);
8994
8995                     bLocked = TRUE;
8996
8997                     AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
8998                                   AFS_TRACE_LEVEL_VERBOSE,
8999                                   "AFSPerformObjectInvalidate Acquiring Fcb extents lock %p SHARED %08lX\n",
9000                                   &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9001                                   PsGetCurrentThread()));
9002
9003                     AFSAcquireShared( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9004                                       TRUE);
9005
9006                     bExtentsLocked = TRUE;
9007
9008                     //
9009                     // There are several possibilities here:
9010                     //
9011                     // 0. If there are no extents or all of the extents are dirty, do nothing.
9012                     //
9013                     // 1. There could be nothing dirty and an open reference count of zero
9014                     //    in which case we can just tear down all of the extents without
9015                     //    holding any resources.
9016                     //
9017                     // 2. There could be nothing dirty and a non-zero open reference count
9018                     //    in which case we can issue a CcPurge against the entire file
9019                     //    while holding just the Fcb Resource.
9020                     //
9021                     // 3. There can be dirty extents in which case we need to identify
9022                     //    the non-dirty ranges and then perform a CcPurge on just the
9023                     //    non-dirty ranges while holding just the Fcb Resource.
9024                     //
9025
9026                     if ( ObjectInfo->Fcb->Specific.File.ExtentCount != ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount)
9027                     {
9028
9029                         if ( ObjectInfo->Fcb->Specific.File.ExtentsDirtyCount == 0)
9030                         {
9031
9032                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9033
9034                             bExtentsLocked = FALSE;
9035
9036                             if ( ObjectInfo->Fcb->OpenReferenceCount == 0)
9037                             {
9038
9039                                 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9040
9041                                 bLocked = FALSE;
9042
9043                                 AFSTearDownFcbExtents( ObjectInfo->Fcb,
9044                                                        NULL);
9045                             }
9046                             else
9047                             {
9048
9049                                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9050                                               AFS_TRACE_LEVEL_VERBOSE,
9051                                               "AFSPerformObjectInvalidation Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
9052                                               &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9053                                               PsGetCurrentThread()));
9054
9055                                 AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9056                                                 TRUE);
9057
9058                                 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9059
9060                                 bLocked = FALSE;
9061
9062                                 __try
9063                                 {
9064
9065                                     if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
9066                                         !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9067                                                               NULL,
9068                                                               0,
9069                                                               FALSE))
9070                                     {
9071
9072                                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9073                                                       AFS_TRACE_LEVEL_WARNING,
9074                                                       "AFSPerformObjectInvalidation CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9075                                                       ObjectInfo->FileId.Cell,
9076                                                       ObjectInfo->FileId.Volume,
9077                                                       ObjectInfo->FileId.Vnode,
9078                                                       ObjectInfo->FileId.Unique));
9079
9080                                         SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9081                                     }
9082                                     else
9083                                     {
9084
9085                                         bCleanExtents = TRUE;
9086                                     }
9087                                 }
9088                                 __except( EXCEPTION_EXECUTE_HANDLER)
9089                                 {
9090
9091                                     ntStatus = GetExceptionCode();
9092
9093                                     AFSDbgTrace(( 0,
9094                                                   0,
9095                                                   "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
9096                                                   ObjectInfo->FileId.Cell,
9097                                                   ObjectInfo->FileId.Volume,
9098                                                   ObjectInfo->FileId.Vnode,
9099                                                   ObjectInfo->FileId.Unique,
9100                                                   ntStatus));
9101
9102                                     SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9103                                 }
9104
9105                                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9106                                               AFS_TRACE_LEVEL_VERBOSE,
9107                                               "AFSPerformObjectInvalidation Releasing Fcb SectionObject lock %p EXCL %08lX\n",
9108                                               &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9109                                               PsGetCurrentThread()));
9110
9111                                 AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
9112                             }
9113                         }
9114                         else
9115                         {
9116
9117                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9118
9119                             bExtentsLocked = FALSE;
9120
9121                             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9122                                           AFS_TRACE_LEVEL_VERBOSE,
9123                                           "AFSPerformObjectInvalidation Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
9124                                           &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9125                                           PsGetCurrentThread()));
9126
9127                             AFSAcquireExcl( &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9128                                             TRUE);
9129
9130                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9131
9132                             bLocked = FALSE;
9133
9134                             //
9135                             // Must build a list of non-dirty ranges from the beginning of the file
9136                             // to the end.  There can be at most (Fcb->Specific.File.ExtentsDirtyCount + 1)
9137                             // ranges.  In all but the most extreme random data write scenario there will
9138                             // be significantly fewer.
9139                             //
9140                             // For each range we need offset and size.
9141                             //
9142
9143                             AFSByteRange * ByteRangeList = NULL;
9144                             ULONG          ulByteRangeCount = 0;
9145                             ULONG          ulIndex;
9146                             BOOLEAN        bPurgeOnClose = FALSE;
9147
9148                             __try
9149                             {
9150
9151                                 ulByteRangeCount = AFSConstructCleanByteRangeList( ObjectInfo->Fcb,
9152                                                                                    &ByteRangeList);
9153
9154                                 if ( ByteRangeList != NULL ||
9155                                      ulByteRangeCount == 0)
9156                                 {
9157
9158                                     for ( ulIndex = 0; ulIndex < ulByteRangeCount; ulIndex++)
9159                                     {
9160
9161                                         ULONG ulSize;
9162
9163                                         do {
9164
9165                                             ulSize = ByteRangeList[ulIndex].Length.QuadPart > DWORD_MAX ? DWORD_MAX : ByteRangeList[ulIndex].Length.LowPart;
9166
9167                                             if( ObjectInfo->Fcb->NPFcb->SectionObjectPointers.DataSectionObject != NULL &&
9168                                                 !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9169                                                                       &ByteRangeList[ulIndex].FileOffset,
9170                                                                       ulSize,
9171                                                                       FALSE))
9172                                             {
9173
9174                                                 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9175                                                               AFS_TRACE_LEVEL_WARNING,
9176                                                               "AFSPerformObjectInvalidation [1] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9177                                                               ObjectInfo->FileId.Cell,
9178                                                               ObjectInfo->FileId.Volume,
9179                                                               ObjectInfo->FileId.Vnode,
9180                                                               ObjectInfo->FileId.Unique));
9181
9182                                                 bPurgeOnClose = TRUE;
9183                                             }
9184                                             else
9185                                             {
9186
9187                                                 bCleanExtents = TRUE;
9188                                             }
9189
9190                                             ByteRangeList[ulIndex].Length.QuadPart -= ulSize;
9191
9192                                             ByteRangeList[ulIndex].FileOffset.QuadPart += ulSize;
9193
9194                                         } while ( ByteRangeList[ulIndex].Length.QuadPart > 0);
9195                                     }
9196                                 }
9197                                 else
9198                                 {
9199
9200                                     //
9201                                     // We couldn't allocate the memory to build the purge list
9202                                     // so just walk the extent list while holding the ExtentsList Resource.
9203                                     // This could deadlock but we do not have much choice.
9204                                     //
9205
9206                                     AFSAcquireExcl(  &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource,
9207                                                     TRUE);
9208                                     bExtentsLocked = TRUE;
9209
9210                                     le = ObjectInfo->Fcb->Specific.File.ExtentsLists[AFS_EXTENTS_LIST].Flink;
9211
9212                                     ulProcessCount = 0;
9213
9214                                     ulCount = (ULONG)ObjectInfo->Fcb->Specific.File.ExtentCount;
9215
9216                                     if( ulCount > 0)
9217                                     {
9218                                         pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
9219
9220                                         while( ulProcessCount < ulCount)
9221                                         {
9222                                             pEntry = ExtentFor( le, AFS_EXTENTS_LIST );
9223
9224                                             if( !BooleanFlagOn( pEntry->Flags, AFS_EXTENT_DIRTY))
9225                                             {
9226                                                 if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9227                                                                           &pEntry->FileOffset,
9228                                                                           pEntry->Size,
9229                                                                           FALSE))
9230                                                 {
9231
9232                                                     AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9233                                                                   AFS_TRACE_LEVEL_WARNING,
9234                                                                   "AFSPerformObjectInvalidation [2] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9235                                                                   ObjectInfo->FileId.Cell,
9236                                                                   ObjectInfo->FileId.Volume,
9237                                                                   ObjectInfo->FileId.Vnode,
9238                                                                   ObjectInfo->FileId.Unique));
9239
9240                                                     bPurgeOnClose = TRUE;
9241                                                 }
9242                                                 else
9243                                                 {
9244
9245                                                     bCleanExtents = TRUE;
9246                                                 }
9247                                             }
9248
9249                                             if( liCurrentOffset.QuadPart < pEntry->FileOffset.QuadPart)
9250                                             {
9251
9252                                                 liFlushLength.QuadPart = pEntry->FileOffset.QuadPart - liCurrentOffset.QuadPart;
9253
9254                                                 while( liFlushLength.QuadPart > 0)
9255                                                 {
9256
9257                                                     if( liFlushLength.QuadPart > 512 * 1024000)
9258                                                     {
9259                                                         ulFlushLength = 512 * 1024000;
9260                                                     }
9261                                                     else
9262                                                     {
9263                                                         ulFlushLength = liFlushLength.LowPart;
9264                                                     }
9265
9266                                                     if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9267                                                                               &liCurrentOffset,
9268                                                                               ulFlushLength,
9269                                                                               FALSE))
9270                                                     {
9271
9272                                                         AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9273                                                                       AFS_TRACE_LEVEL_WARNING,
9274                                                                       "AFSPerformObjectInvalidation [3] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9275                                                                       ObjectInfo->FileId.Cell,
9276                                                                       ObjectInfo->FileId.Volume,
9277                                                                       ObjectInfo->FileId.Vnode,
9278                                                                       ObjectInfo->FileId.Unique));
9279
9280                                                         bPurgeOnClose = TRUE;
9281                                                     }
9282                                                     else
9283                                                     {
9284
9285                                                         bCleanExtents = TRUE;
9286                                                     }
9287
9288                                                     liFlushLength.QuadPart -= ulFlushLength;
9289                                                 }
9290                                             }
9291
9292                                             liCurrentOffset.QuadPart = pEntry->FileOffset.QuadPart + pEntry->Size;
9293
9294                                             ulProcessCount++;
9295                                             le = le->Flink;
9296                                         }
9297                                     }
9298                                     else
9299                                     {
9300                                         if( !CcPurgeCacheSection( &ObjectInfo->Fcb->NPFcb->SectionObjectPointers,
9301                                                                   NULL,
9302                                                                   0,
9303                                                                   FALSE))
9304                                         {
9305
9306                                             AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
9307                                                           AFS_TRACE_LEVEL_WARNING,
9308                                                           "AFSPerformObjectInvalidation [4] CcPurgeCacheSection failure FID %08lX-%08lX-%08lX-%08lX\n",
9309                                                           ObjectInfo->FileId.Cell,
9310                                                           ObjectInfo->FileId.Volume,
9311                                                           ObjectInfo->FileId.Vnode,
9312                                                           ObjectInfo->FileId.Unique));
9313
9314                                             bPurgeOnClose = TRUE;
9315                                         }
9316                                         else
9317                                         {
9318
9319                                             bCleanExtents = TRUE;
9320                                         }
9321                                     }
9322
9323                                     if ( bPurgeOnClose)
9324                                     {
9325
9326                                         SetFlag( ObjectInfo->Fcb->Flags, AFS_FCB_FLAG_PURGE_ON_CLOSE);
9327                                     }
9328                                 }
9329                             }
9330                             __except( EXCEPTION_EXECUTE_HANDLER)
9331                             {
9332
9333                                 ntStatus = GetExceptionCode();
9334
9335                                 AFSDbgTrace(( 0,
9336                                               0,
9337                                               "EXCEPTION - AFSPerformObjectInvalidation FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
9338                                               ObjectInfo->FileId.Cell,
9339                                               ObjectInfo->FileId.Volume,
9340                                               ObjectInfo->FileId.Vnode,
9341                                               ObjectInfo->FileId.Unique,
9342                                               ntStatus));
9343                             }
9344
9345                             AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
9346                                           AFS_TRACE_LEVEL_VERBOSE,
9347                                           "AFSPerformObjectInvalidation Releasing Fcb SectionObject lock %p EXCL %08lX\n",
9348                                           &ObjectInfo->Fcb->NPFcb->SectionObjectResource,
9349                                           PsGetCurrentThread()));
9350
9351                             AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->SectionObjectResource);
9352                         }
9353                     }
9354
9355                     if ( bExtentsLocked)
9356                     {
9357
9358                         AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Specific.File.ExtentsResource );
9359                     }
9360
9361                     if ( bLocked)
9362                     {
9363
9364                         AFSReleaseResource( &ObjectInfo->Fcb->NPFcb->Resource);
9365                     }
9366
9367                     if ( bCleanExtents)
9368                     {
9369
9370                         AFSReleaseCleanExtents( ObjectInfo->Fcb,
9371                                                 NULL);
9372                     }
9373                 }
9374
9375                 break;
9376             }
9377         }
9378
9379         //
9380         // Destroy the reference passed in by the caller to AFSInvalidateObject
9381         // or AFSQueueInvalidateObject
9382         //
9383
9384         lCount = AFSObjectInfoDecrement( ObjectInfo,
9385                                          AFS_OBJECT_REFERENCE_INVALIDATION);
9386
9387         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
9388                       AFS_TRACE_LEVEL_VERBOSE,
9389                       "AFSPerformObjectInvalidation Decrement count on object %p Cnt %d\n",
9390                       ObjectInfo,
9391                       lCount));
9392     }
9393
9394     return ntStatus;
9395 }