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