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