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