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