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