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