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