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