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