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