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