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