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