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