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